Separated the Classic Datapack to it's own folder.
This commit is contained in:
483
trunk/dist/game/data_classic/scripts/ai/group_template/BeastFarm.java
vendored
Normal file
483
trunk/dist/game/data_classic/scripts/ai/group_template/BeastFarm.java
vendored
Normal file
@@ -0,0 +1,483 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.ai.CtrlIntention;
|
||||
import com.l2jserver.gameserver.datatables.SkillData;
|
||||
import com.l2jserver.gameserver.model.L2Object;
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2TamedBeastInstance;
|
||||
import com.l2jserver.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
import com.l2jserver.gameserver.network.serverpackets.NpcInfo;
|
||||
import com.l2jserver.gameserver.util.Util;
|
||||
|
||||
/**
|
||||
* Growth-capable mobs: Polymorphing upon successful feeding.<br>
|
||||
* Updated to Freya.
|
||||
* @author Fulminus, Gigiikun
|
||||
*/
|
||||
public final class BeastFarm extends AbstractNpcAI
|
||||
{
|
||||
private static final int GOLDEN_SPICE = 15474;
|
||||
private static final int CRYSTAL_SPICE = 15475;
|
||||
private static final int SKILL_GOLDEN_SPICE = 9049;
|
||||
private static final int SKILL_CRYSTAL_SPICE = 9050;
|
||||
private static final int SKILL_BLESSED_GOLDEN_SPICE = 9051;
|
||||
private static final int SKILL_BLESSED_CRYSTAL_SPICE = 9052;
|
||||
private static final int SKILL_SGRADE_GOLDEN_SPICE = 9053;
|
||||
private static final int SKILL_SGRADE_CRYSTAL_SPICE = 9054;
|
||||
private static final int[] TAMED_BEASTS =
|
||||
{
|
||||
18869,
|
||||
18870,
|
||||
18871,
|
||||
18872
|
||||
};
|
||||
private static final int TAME_CHANCE = 20;
|
||||
protected static final int[] SPECIAL_SPICE_CHANCES =
|
||||
{
|
||||
33,
|
||||
75
|
||||
};
|
||||
|
||||
// all mobs that can eat...
|
||||
private static final int[] FEEDABLE_BEASTS =
|
||||
{
|
||||
// Kookaburras
|
||||
18873,
|
||||
18874,
|
||||
18875,
|
||||
18876,
|
||||
18877,
|
||||
18878,
|
||||
18879,
|
||||
// Cougars
|
||||
18880,
|
||||
18881,
|
||||
18882,
|
||||
18883,
|
||||
18884,
|
||||
18885,
|
||||
18886,
|
||||
// Buffalos
|
||||
18887,
|
||||
18888,
|
||||
18889,
|
||||
18890,
|
||||
18891,
|
||||
18892,
|
||||
18893,
|
||||
// Grendels
|
||||
18894,
|
||||
18895,
|
||||
18896,
|
||||
18897,
|
||||
18898,
|
||||
18899,
|
||||
18900
|
||||
};
|
||||
|
||||
private static final Map<Integer, Integer> FEED_INFO = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, GrowthCapableMob> GROWTH_CAPABLE_MONSTERS = new HashMap<>();
|
||||
private static List<TamedBeast> TAMED_BEAST_DATA = new ArrayList<>();
|
||||
|
||||
private BeastFarm()
|
||||
{
|
||||
super(BeastFarm.class.getSimpleName(), "ai/group_template");
|
||||
addSkillSeeId(FEEDABLE_BEASTS);
|
||||
addKillId(FEEDABLE_BEASTS);
|
||||
|
||||
GrowthCapableMob temp;
|
||||
|
||||
// Kookabura
|
||||
temp = new GrowthCapableMob(100, 0, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18874);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18875);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_GOLDEN_SPICE, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_CRYSTAL_SPICE, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_GOLDEN_SPICE, 18878);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_CRYSTAL_SPICE, 18879);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18873, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18876);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18874, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18877);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18875, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18878);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18876, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18879);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18877, temp);
|
||||
|
||||
// Cougar
|
||||
temp = new GrowthCapableMob(100, 0, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18881);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18882);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_GOLDEN_SPICE, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_CRYSTAL_SPICE, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_GOLDEN_SPICE, 18885);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_CRYSTAL_SPICE, 18886);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18880, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18883);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18881, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18884);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18882, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18885);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18883, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18886);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18884, temp);
|
||||
|
||||
// Buffalo
|
||||
temp = new GrowthCapableMob(100, 0, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18888);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18889);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_GOLDEN_SPICE, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_CRYSTAL_SPICE, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_GOLDEN_SPICE, 18892);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_CRYSTAL_SPICE, 18893);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18887, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18890);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18888, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18891);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18889, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18892);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18890, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18893);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18891, temp);
|
||||
|
||||
// Grendel
|
||||
temp = new GrowthCapableMob(100, 0, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18895);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18896);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_GOLDEN_SPICE, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_CRYSTAL_SPICE, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_GOLDEN_SPICE, 18899);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_CRYSTAL_SPICE, 18900);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18894, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18897);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18895, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18898);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18896, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18899);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18897, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18900);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18898, temp);
|
||||
|
||||
// Tamed beasts data
|
||||
TAMED_BEAST_DATA.add(new TamedBeast("%name% of Focus", new SkillHolder(6432, 1), new SkillHolder(6668, 1)));
|
||||
TAMED_BEAST_DATA.add(new TamedBeast("%name% of Guiding", new SkillHolder(6433, 1), new SkillHolder(6670, 1)));
|
||||
TAMED_BEAST_DATA.add(new TamedBeast("%name% of Swifth", new SkillHolder(6434, 1), new SkillHolder(6667, 1)));
|
||||
TAMED_BEAST_DATA.add(new TamedBeast("Berserker %name%", new SkillHolder(6671, 1)));
|
||||
TAMED_BEAST_DATA.add(new TamedBeast("%name% of Protect", new SkillHolder(6669, 1), new SkillHolder(6672, 1)));
|
||||
TAMED_BEAST_DATA.add(new TamedBeast("%name% of Vigor", new SkillHolder(6431, 1), new SkillHolder(6666, 1)));
|
||||
}
|
||||
|
||||
public void spawnNext(L2Npc npc, L2PcInstance player, int nextNpcId, int food)
|
||||
{
|
||||
// remove the feedinfo of the mob that got despawned, if any
|
||||
if (FEED_INFO.containsKey(npc.getObjectId()))
|
||||
{
|
||||
if (FEED_INFO.get(npc.getObjectId()) == player.getObjectId())
|
||||
{
|
||||
FEED_INFO.remove(npc.getObjectId());
|
||||
}
|
||||
}
|
||||
// despawn the old mob
|
||||
// TODO: same code? FIXED?
|
||||
/*
|
||||
* if (_GrowthCapableMobs.get(npc.getNpcId()).getGrowthLevel() == 0) { npc.deleteMe(); } else {
|
||||
*/
|
||||
npc.deleteMe();
|
||||
// }
|
||||
|
||||
// if this is finally a trained mob, then despawn any other trained mobs that the
|
||||
// player might have and initialize the Tamed Beast.
|
||||
if (Util.contains(TAMED_BEASTS, nextNpcId))
|
||||
{
|
||||
final L2TamedBeastInstance nextNpc = new L2TamedBeastInstance(nextNpcId, player, food, npc.getX(), npc.getY(), npc.getZ(), true);
|
||||
|
||||
TamedBeast beast = TAMED_BEAST_DATA.get(getRandom(TAMED_BEAST_DATA.size()));
|
||||
String name = beast.getName();
|
||||
switch (nextNpcId)
|
||||
{
|
||||
case 18869:
|
||||
name = name.replace("%name%", "Alpine Kookaburra");
|
||||
break;
|
||||
case 18870:
|
||||
name = name.replace("%name%", "Alpine Cougar");
|
||||
break;
|
||||
case 18871:
|
||||
name = name.replace("%name%", "Alpine Buffalo");
|
||||
break;
|
||||
case 18872:
|
||||
name = name.replace("%name%", "Alpine Grendel");
|
||||
break;
|
||||
}
|
||||
nextNpc.setName(name);
|
||||
nextNpc.broadcastPacket(new NpcInfo(nextNpc));
|
||||
nextNpc.setRunning();
|
||||
|
||||
SkillData st = SkillData.getInstance();
|
||||
for (SkillHolder sh : beast.getSkills())
|
||||
{
|
||||
nextNpc.addBeastSkill(st.getSkill(sh.getSkillId(), sh.getSkillLvl()));
|
||||
}
|
||||
|
||||
// Q00020_BringUpWithLove.checkJewelOfInnocence(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if not trained, the newly spawned mob will automatically be agro against its feeder
|
||||
// (what happened to "never bite the hand that feeds you" anyway?!)
|
||||
L2Attackable nextNpc = (L2Attackable) addSpawn(nextNpcId, npc);
|
||||
|
||||
// register the player in the feedinfo for the mob that just spawned
|
||||
FEED_INFO.put(nextNpc.getObjectId(), player.getObjectId());
|
||||
nextNpc.setRunning();
|
||||
nextNpc.addDamageHate(player, 0, 99999);
|
||||
nextNpc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, player);
|
||||
|
||||
player.setTarget(nextNpc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
|
||||
{
|
||||
// this behavior is only run when the target of skill is the passed npc (chest)
|
||||
// i.e. when the player is attempting to open the chest using a skill
|
||||
if (!Util.contains(targets, npc))
|
||||
{
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
// gather some values on local variables
|
||||
int npcId = npc.getId();
|
||||
int skillId = skill.getId();
|
||||
// check if the npc and skills used are valid for this script. Exit if invalid.
|
||||
if (!Util.contains(FEEDABLE_BEASTS, npcId) || ((skillId != SKILL_GOLDEN_SPICE) && (skillId != SKILL_CRYSTAL_SPICE) && (skillId != SKILL_BLESSED_GOLDEN_SPICE) && (skillId != SKILL_BLESSED_CRYSTAL_SPICE) && (skillId != SKILL_SGRADE_GOLDEN_SPICE) && (skillId != SKILL_SGRADE_CRYSTAL_SPICE)))
|
||||
{
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
// first gather some values on local variables
|
||||
int objectId = npc.getObjectId();
|
||||
int growthLevel = 3; // if a mob is in FEEDABLE_BEASTS but not in _GrowthCapableMobs, then it's at max growth (3)
|
||||
if (GROWTH_CAPABLE_MONSTERS.containsKey(npcId))
|
||||
{
|
||||
growthLevel = GROWTH_CAPABLE_MONSTERS.get(npcId).getGrowthLevel();
|
||||
}
|
||||
|
||||
// prevent exploit which allows 2 players to simultaneously raise the same 0-growth beast
|
||||
// If the mob is at 0th level (when it still listens to all feeders) lock it to the first feeder!
|
||||
if ((growthLevel == 0) && FEED_INFO.containsKey(objectId))
|
||||
{
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
FEED_INFO.put(objectId, caster.getObjectId());
|
||||
|
||||
// display the social action of the beast eating the food.
|
||||
npc.broadcastSocialAction(2);
|
||||
|
||||
int food = 0;
|
||||
if ((skillId == SKILL_GOLDEN_SPICE) || (skillId == SKILL_BLESSED_GOLDEN_SPICE))
|
||||
{
|
||||
food = GOLDEN_SPICE;
|
||||
}
|
||||
else if ((skillId == SKILL_CRYSTAL_SPICE) || (skillId == SKILL_BLESSED_CRYSTAL_SPICE))
|
||||
{
|
||||
food = CRYSTAL_SPICE;
|
||||
}
|
||||
|
||||
// if this pet can't grow, it's all done.
|
||||
if (GROWTH_CAPABLE_MONSTERS.containsKey(npcId))
|
||||
{
|
||||
// do nothing if this mob doesn't eat the specified food (food gets consumed but has no effect).
|
||||
int newNpcId = GROWTH_CAPABLE_MONSTERS.get(npcId).getLeveledNpcId(skillId);
|
||||
if (newNpcId == -1)
|
||||
{
|
||||
if (growthLevel == 0)
|
||||
{
|
||||
FEED_INFO.remove(objectId);
|
||||
npc.setRunning();
|
||||
((L2Attackable) npc).addDamageHate(caster, 0, 1);
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, caster);
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
else if ((growthLevel > 0) && (FEED_INFO.get(objectId) != caster.getObjectId()))
|
||||
{
|
||||
// check if this is the same player as the one who raised it from growth 0.
|
||||
// if no, then do not allow a chance to raise the pet (food gets consumed but has no effect).
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
spawnNext(npc, caster, newNpcId, food);
|
||||
}
|
||||
else
|
||||
{
|
||||
caster.sendMessage("The beast spit out the feed instead of eating it.");
|
||||
npc.dropItem(caster, food, 1);
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
// remove the feedinfo of the mob that got killed, if any
|
||||
if (FEED_INFO.containsKey(npc.getObjectId()))
|
||||
{
|
||||
FEED_INFO.remove(npc.getObjectId());
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
// all mobs that grow by eating
|
||||
private static class GrowthCapableMob
|
||||
{
|
||||
private final int _chance;
|
||||
private final int _growthLevel;
|
||||
private final int _tameNpcId;
|
||||
private final Map<Integer, Integer> _skillSuccessNpcIdList = new HashMap<>();
|
||||
|
||||
public GrowthCapableMob(int chance, int growthLevel, int tameNpcId)
|
||||
{
|
||||
_chance = chance;
|
||||
_growthLevel = growthLevel;
|
||||
_tameNpcId = tameNpcId;
|
||||
}
|
||||
|
||||
public void addNpcIdForSkillId(int skillId, int npcId)
|
||||
{
|
||||
_skillSuccessNpcIdList.put(skillId, npcId);
|
||||
}
|
||||
|
||||
public int getGrowthLevel()
|
||||
{
|
||||
return _growthLevel;
|
||||
}
|
||||
|
||||
public int getLeveledNpcId(int skillId)
|
||||
{
|
||||
if (!_skillSuccessNpcIdList.containsKey(skillId))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if ((skillId == SKILL_BLESSED_GOLDEN_SPICE) || (skillId == SKILL_BLESSED_CRYSTAL_SPICE) || (skillId == SKILL_SGRADE_GOLDEN_SPICE) || (skillId == SKILL_SGRADE_CRYSTAL_SPICE))
|
||||
{
|
||||
if (getRandom(100) < SPECIAL_SPICE_CHANCES[0])
|
||||
{
|
||||
if (getRandom(100) < SPECIAL_SPICE_CHANCES[1])
|
||||
{
|
||||
return _skillSuccessNpcIdList.get(skillId);
|
||||
}
|
||||
else if ((skillId == SKILL_BLESSED_GOLDEN_SPICE) || (skillId == SKILL_SGRADE_GOLDEN_SPICE))
|
||||
{
|
||||
return _skillSuccessNpcIdList.get(SKILL_GOLDEN_SPICE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _skillSuccessNpcIdList.get(SKILL_CRYSTAL_SPICE);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else if ((_growthLevel == 2) && (getRandom(100) < TAME_CHANCE))
|
||||
{
|
||||
return _tameNpcId;
|
||||
}
|
||||
else if (getRandom(100) < _chance)
|
||||
{
|
||||
return _skillSuccessNpcIdList.get(skillId);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class TamedBeast
|
||||
{
|
||||
private final String name;
|
||||
private final SkillHolder[] sh;
|
||||
|
||||
public TamedBeast(String beastName, SkillHolder... holders)
|
||||
{
|
||||
name = beastName;
|
||||
sh = holders;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public SkillHolder[] getSkills()
|
||||
{
|
||||
return sh;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new BeastFarm();
|
||||
}
|
||||
}
|
246
trunk/dist/game/data_classic/scripts/ai/group_template/DenOfEvil.java
vendored
Normal file
246
trunk/dist/game/data_classic/scripts/ai/group_template/DenOfEvil.java
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.ThreadPoolManager;
|
||||
import com.l2jserver.gameserver.datatables.SkillData;
|
||||
import com.l2jserver.gameserver.instancemanager.ZoneManager;
|
||||
import com.l2jserver.gameserver.model.Location;
|
||||
import com.l2jserver.gameserver.model.actor.L2Character;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
import com.l2jserver.gameserver.model.zone.type.L2EffectZone;
|
||||
import com.l2jserver.gameserver.network.SystemMessageId;
|
||||
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
|
||||
import com.l2jserver.gameserver.util.Util;
|
||||
|
||||
/**
|
||||
* Dummy AI for spawns/respawns only for testing.
|
||||
* @author Gnacik
|
||||
*/
|
||||
public final class DenOfEvil extends AbstractNpcAI
|
||||
{
|
||||
// private static final int _buffer_id = 32656;
|
||||
protected static final int[] EYE_IDS =
|
||||
{
|
||||
18812,
|
||||
18813,
|
||||
18814
|
||||
};
|
||||
private static final int SKILL_ID = 6150; // others +2
|
||||
|
||||
private static final Location[] EYE_SPAWNS =
|
||||
{
|
||||
new Location(71544, -129400, -3360, 16472),
|
||||
new Location(70954, -128854, -3360, 16),
|
||||
new Location(72145, -128847, -3368, 32832),
|
||||
new Location(76147, -128372, -3144, 16152),
|
||||
new Location(71573, -128309, -3360, 49152),
|
||||
new Location(75211, -127441, -3152, 0),
|
||||
new Location(77005, -127406, -3144, 32784),
|
||||
new Location(75965, -126486, -3144, 49120),
|
||||
new Location(70972, -126429, -3016, 19208),
|
||||
new Location(69916, -125838, -3024, 2840),
|
||||
new Location(71658, -125459, -3016, 35136),
|
||||
new Location(70605, -124646, -3040, 52104),
|
||||
new Location(67283, -123237, -2912, 12376),
|
||||
new Location(68383, -122754, -2912, 27904),
|
||||
new Location(74137, -122733, -3024, 13272),
|
||||
new Location(66736, -122007, -2896, 60576),
|
||||
new Location(73289, -121769, -3024, 1024),
|
||||
new Location(67894, -121491, -2912, 43872),
|
||||
new Location(75530, -121477, -3008, 34424),
|
||||
new Location(74117, -120459, -3024, 52344),
|
||||
new Location(69608, -119855, -2534, 17251),
|
||||
new Location(71014, -119027, -2520, 31904),
|
||||
new Location(68944, -118964, -2527, 59874),
|
||||
new Location(62261, -118263, -3072, 12888),
|
||||
new Location(70300, -117942, -2528, 46208),
|
||||
new Location(74312, -117583, -2272, 15280),
|
||||
new Location(63276, -117409, -3064, 24760),
|
||||
new Location(68104, -117192, -2168, 15888),
|
||||
new Location(73758, -116945, -2216, 0),
|
||||
new Location(74944, -116858, -2220, 30892),
|
||||
new Location(61715, -116623, -3064, 59888),
|
||||
new Location(69140, -116464, -2168, 28952),
|
||||
new Location(67311, -116374, -2152, 1280),
|
||||
new Location(62459, -116370, -3064, 48624),
|
||||
new Location(74475, -116260, -2216, 47456),
|
||||
new Location(68333, -115015, -2168, 45136),
|
||||
new Location(68280, -108129, -1160, 17992),
|
||||
new Location(62983, -107259, -2384, 12552),
|
||||
new Location(67062, -107125, -1144, 64008),
|
||||
new Location(68893, -106954, -1160, 36704),
|
||||
new Location(63848, -106771, -2384, 32784),
|
||||
new Location(62372, -106514, -2384, 0),
|
||||
new Location(67838, -106143, -1160, 51232),
|
||||
new Location(62905, -106109, -2384, 51288)
|
||||
};
|
||||
|
||||
private final static boolean DEBUG = false;
|
||||
|
||||
private DenOfEvil()
|
||||
{
|
||||
super(DenOfEvil.class.getSimpleName(), "ai/group_template");
|
||||
addKillId(EYE_IDS);
|
||||
addSpawnId(EYE_IDS);
|
||||
for (Location loc : EYE_SPAWNS)
|
||||
{
|
||||
addSpawn(EYE_IDS[getRandom(EYE_IDS.length)], loc, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private int getSkillIdByNpcId(int npcId)
|
||||
{
|
||||
int diff = npcId - EYE_IDS[0];
|
||||
diff *= 2;
|
||||
return SKILL_ID + diff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
npc.disableCoreAI(true);
|
||||
npc.setIsImmobilized(true);
|
||||
L2EffectZone zone = ZoneManager.getInstance().getZone(npc, L2EffectZone.class);
|
||||
if (zone == null)
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
_log.warning("NPC " + npc + " spawned outside of L2EffectZone, check your zone coords! X:" + npc.getX() + " Y:" + npc.getY() + " Z:" + npc.getZ());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
int skillId = getSkillIdByNpcId(npc.getId());
|
||||
int skillLevel = zone.getSkillLevel(skillId);
|
||||
zone.addSkill(skillId, skillLevel + 1);
|
||||
if (skillLevel == 3) // 3+1=4
|
||||
{
|
||||
ThreadPoolManager.getInstance().scheduleAi(new KashaDestruction(zone), 2 * 60 * 1000l);
|
||||
zone.broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.DEFEAT_KASHA_S_EYES_TO_LIFT_THE_GREAT_CURSE));
|
||||
}
|
||||
else if (skillLevel == 2)
|
||||
{
|
||||
zone.broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.A_GREAT_CURSE_CAN_BE_FELT_FROM_KASHA_S_EYES));
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
ThreadPoolManager.getInstance().scheduleAi(new RespawnNewEye(npc.getLocation()), 15000);
|
||||
L2EffectZone zone = ZoneManager.getInstance().getZone(npc, L2EffectZone.class);
|
||||
if (zone == null)
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
_log.warning("NPC " + npc + " killed outside of L2EffectZone, check your zone coords! X:" + npc.getX() + " Y:" + npc.getY() + " Z:" + npc.getZ());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
int skillId = getSkillIdByNpcId(npc.getId());
|
||||
int skillLevel = zone.getSkillLevel(skillId);
|
||||
zone.addSkill(skillId, skillLevel - 1);
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
private class RespawnNewEye implements Runnable
|
||||
{
|
||||
private final Location _loc;
|
||||
|
||||
public RespawnNewEye(Location loc)
|
||||
{
|
||||
_loc = loc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
addSpawn(EYE_IDS[getRandom(EYE_IDS.length)], _loc, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private class KashaDestruction implements Runnable
|
||||
{
|
||||
L2EffectZone _zone;
|
||||
|
||||
public KashaDestruction(L2EffectZone zone)
|
||||
{
|
||||
_zone = zone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
for (int i = SKILL_ID; i <= (SKILL_ID + 4); i = i + 2)
|
||||
{
|
||||
// test 3 skills if some is lvl 4
|
||||
if (_zone.getSkillLevel(i) > 3)
|
||||
{
|
||||
destroyZone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void destroyZone()
|
||||
{
|
||||
for (L2Character character : _zone.getCharactersInside())
|
||||
{
|
||||
if (character == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (character.isPlayable())
|
||||
{
|
||||
Skill skill = SkillData.getInstance().getSkill(6149, 1);
|
||||
skill.applyEffects(character, character);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (character.doDie(null)) // mobs die
|
||||
{
|
||||
if (character.isNpc())
|
||||
{
|
||||
// respawn eye
|
||||
L2Npc npc = (L2Npc) character;
|
||||
if (Util.contains(EYE_IDS, npc.getId()))
|
||||
{
|
||||
ThreadPoolManager.getInstance().scheduleAi(new RespawnNewEye(npc.getLocation()), 15000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = SKILL_ID; i <= (SKILL_ID + 4); i = i + 2)
|
||||
{
|
||||
_zone.removeSkill(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new DenOfEvil();
|
||||
}
|
||||
}
|
90
trunk/dist/game/data_classic/scripts/ai/group_template/FairyTrees.java
vendored
Normal file
90
trunk/dist/game/data_classic/scripts/ai/group_template/FairyTrees.java
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.L2Playable;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.SkillHolder;
|
||||
|
||||
/**
|
||||
* Fairy Trees AI.
|
||||
* @author Charus
|
||||
*/
|
||||
public class FairyTrees extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int SOUL_GUARDIAN = 27189; // Soul of Tree Guardian
|
||||
|
||||
private static final int[] MOBS =
|
||||
{
|
||||
27185, // Fairy Tree of Wind
|
||||
27186, // Fairy Tree of Star
|
||||
27187, // Fairy Tree of Twilight
|
||||
27188, // Fairy Tree of Abyss
|
||||
};
|
||||
|
||||
// Skill
|
||||
private static SkillHolder VENOMOUS_POISON = new SkillHolder(4243, 1); // Venomous Poison
|
||||
|
||||
// Misc
|
||||
private static final int MIN_DISTANCE = 1500;
|
||||
|
||||
private FairyTrees()
|
||||
{
|
||||
super(FairyTrees.class.getSimpleName(), "ai/group_template");
|
||||
addKillId(MOBS);
|
||||
addSpawnId(MOBS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (npc.calculateDistance(killer, true, false) <= MIN_DISTANCE)
|
||||
{
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
final L2Npc guardian = addSpawn(SOUL_GUARDIAN, npc, false, 30000);
|
||||
final L2Playable attacker = isSummon ? killer.getServitors().values().stream().findFirst().orElse(killer.getPet()) : killer;
|
||||
addAttackPlayerDesire(guardian, attacker);
|
||||
if (getRandomBoolean())
|
||||
{
|
||||
guardian.setTarget(attacker);
|
||||
guardian.doCast(VENOMOUS_POISON.getSkill());
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
npc.setIsNoRndWalk(true);
|
||||
npc.setIsImmobilized(true);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new FairyTrees();
|
||||
}
|
||||
}
|
627
trunk/dist/game/data_classic/scripts/ai/group_template/FeedableBeasts.java
vendored
Normal file
627
trunk/dist/game/data_classic/scripts/ai/group_template/FeedableBeasts.java
vendored
Normal file
@@ -0,0 +1,627 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.ai.CtrlIntention;
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.L2Object;
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2TamedBeastInstance;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
|
||||
import com.l2jserver.gameserver.util.Util;
|
||||
|
||||
/**
|
||||
* Growth-capable mobs: Polymorphing upon successful feeding.
|
||||
* @author Fulminus
|
||||
*/
|
||||
public final class FeedableBeasts extends AbstractNpcAI
|
||||
{
|
||||
private static final int GOLDEN_SPICE = 6643;
|
||||
private static final int CRYSTAL_SPICE = 6644;
|
||||
private static final int SKILL_GOLDEN_SPICE = 2188;
|
||||
private static final int SKILL_CRYSTAL_SPICE = 2189;
|
||||
private static final int FOODSKILLDIFF = GOLDEN_SPICE - SKILL_GOLDEN_SPICE;
|
||||
// Tamed Wild Beasts
|
||||
private static final int TRAINED_BUFFALO1 = 16013;
|
||||
private static final int TRAINED_BUFFALO2 = 16014;
|
||||
private static final int TRAINED_COUGAR1 = 16015;
|
||||
private static final int TRAINED_COUGAR2 = 16016;
|
||||
private static final int TRAINED_KOOKABURRA1 = 16017;
|
||||
private static final int TRAINED_KOOKABURRA2 = 16018;
|
||||
// private static final int TRAINED_TINY_BABY_BUFFALO = 16020; // TODO: Implement.
|
||||
// private static final int TRAINED_TINY_BABY_COUGAR = 16022; // TODO: Implement.
|
||||
// private static final int TRAINED_TINY_BABY_KOOKABURRA = 16024; // TODO: Implement.
|
||||
// @formatter:off
|
||||
private static final int[] TAMED_BEASTS =
|
||||
{
|
||||
TRAINED_BUFFALO1, TRAINED_BUFFALO2, TRAINED_COUGAR1, TRAINED_COUGAR2, TRAINED_KOOKABURRA1, TRAINED_KOOKABURRA2
|
||||
};
|
||||
// all mobs that can eat...
|
||||
private static final int[] FEEDABLE_BEASTS =
|
||||
{
|
||||
21451, 21452, 21453, 21454, 21455, 21456, 21457, 21458, 21459, 21460,
|
||||
21461, 21462, 21463, 21464, 21465, 21466, 21467, 21468, 21469, 21470,
|
||||
21471, 21472, 21473, 21474, 21475, 21476, 21477, 21478, 21479, 21480,
|
||||
21481, 21482, 21483, 21484, 21485, 21486, 21487, 21488, 21489, 21490,
|
||||
21491, 21492, 21493, 21494, 21495, 21496, 21497, 21498, 21499, 21500,
|
||||
21501, 21502, 21503, 21504, 21505, 21506, 21507, 21824, 21825, 21826,
|
||||
21827, 21828, 21829, TRAINED_BUFFALO1, TRAINED_BUFFALO2, TRAINED_COUGAR1, TRAINED_COUGAR2, TRAINED_KOOKABURRA1, TRAINED_KOOKABURRA2
|
||||
};
|
||||
// @formatter:on
|
||||
|
||||
private static final Map<Integer, Integer> MAD_COW_POLYMORPH = new HashMap<>();
|
||||
static
|
||||
{
|
||||
MAD_COW_POLYMORPH.put(21824, 21468);
|
||||
MAD_COW_POLYMORPH.put(21825, 21469);
|
||||
MAD_COW_POLYMORPH.put(21826, 21487);
|
||||
MAD_COW_POLYMORPH.put(21827, 21488);
|
||||
MAD_COW_POLYMORPH.put(21828, 21506);
|
||||
MAD_COW_POLYMORPH.put(21829, 21507);
|
||||
}
|
||||
|
||||
private static final NpcStringId[][] TEXT =
|
||||
{
|
||||
{
|
||||
NpcStringId.WHAT_DID_YOU_JUST_DO_TO_ME,
|
||||
NpcStringId.ARE_YOU_TRYING_TO_TAME_ME_DON_T_DO_THAT,
|
||||
NpcStringId.DON_T_GIVE_SUCH_A_THING_YOU_CAN_ENDANGER_YOURSELF,
|
||||
NpcStringId.YUCK_WHAT_IS_THIS_IT_TASTES_TERRIBLE,
|
||||
NpcStringId.I_M_HUNGRY_GIVE_ME_A_LITTLE_MORE_PLEASE,
|
||||
NpcStringId.WHAT_IS_THIS_IS_THIS_EDIBLE,
|
||||
NpcStringId.DON_T_WORRY_ABOUT_ME,
|
||||
NpcStringId.THANK_YOU_THAT_WAS_DELICIOUS,
|
||||
NpcStringId.I_THINK_I_AM_STARTING_TO_LIKE_YOU,
|
||||
NpcStringId.EEEEEK_EEEEEK
|
||||
},
|
||||
{
|
||||
NpcStringId.DON_T_KEEP_TRYING_TO_TAME_ME_I_DON_T_WANT_TO_BE_TAMED,
|
||||
NpcStringId.IT_IS_JUST_FOOD_TO_ME_ALTHOUGH_IT_MAY_ALSO_BE_YOUR_HAND,
|
||||
NpcStringId.IF_I_KEEP_EATING_LIKE_THIS_WON_T_I_BECOME_FAT_CHOMP_CHOMP,
|
||||
NpcStringId.WHY_DO_YOU_KEEP_FEEDING_ME,
|
||||
NpcStringId.DON_T_TRUST_ME_I_M_AFRAID_I_MAY_BETRAY_YOU_LATER
|
||||
},
|
||||
{
|
||||
NpcStringId.GRRRRR,
|
||||
NpcStringId.YOU_BROUGHT_THIS_UPON_YOURSELF,
|
||||
NpcStringId.I_FEEL_STRANGE_I_KEEP_HAVING_THESE_EVIL_THOUGHTS,
|
||||
NpcStringId.ALAS_SO_THIS_IS_HOW_IT_ALL_ENDS,
|
||||
NpcStringId.I_DON_T_FEEL_SO_GOOD_OH_MY_MIND_IS_VERY_TROUBLED
|
||||
}
|
||||
};
|
||||
|
||||
private static final NpcStringId[] TAMED_TEXT =
|
||||
{
|
||||
NpcStringId.S1_SO_WHAT_DO_YOU_THINK_IT_IS_LIKE_TO_BE_TAMED,
|
||||
NpcStringId.S1_WHENEVER_I_SEE_SPICE_I_THINK_I_WILL_MISS_YOUR_HAND_THAT_USED_TO_FEED_IT_TO_ME,
|
||||
NpcStringId.S1_DON_T_GO_TO_THE_VILLAGE_I_DON_T_HAVE_THE_STRENGTH_TO_FOLLOW_YOU,
|
||||
NpcStringId.THANK_YOU_FOR_TRUSTING_ME_S1_I_HOPE_I_WILL_BE_HELPFUL_TO_YOU,
|
||||
NpcStringId.S1_WILL_I_BE_ABLE_TO_HELP_YOU,
|
||||
NpcStringId.I_GUESS_IT_S_JUST_MY_ANIMAL_MAGNETISM,
|
||||
NpcStringId.TOO_MUCH_SPICY_FOOD_MAKES_ME_SWEAT_LIKE_A_BEAST,
|
||||
NpcStringId.ANIMALS_NEED_LOVE_TOO
|
||||
};
|
||||
|
||||
private static final Map<Integer, Integer> FEED_INFO = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, GrowthCapableMob> GROWTH_CAPABLE_MONSTERS = new HashMap<>();
|
||||
|
||||
// all mobs that grow by eating
|
||||
private static class GrowthCapableMob
|
||||
{
|
||||
private final int _growthLevel;
|
||||
private final int _chance;
|
||||
|
||||
private final Map<Integer, int[][]> _spiceToMob = new HashMap<>();
|
||||
|
||||
public GrowthCapableMob(int growthLevel, int chance)
|
||||
{
|
||||
_growthLevel = growthLevel;
|
||||
_chance = chance;
|
||||
}
|
||||
|
||||
public void addMobs(int spice, int[][] Mobs)
|
||||
{
|
||||
_spiceToMob.put(spice, Mobs);
|
||||
}
|
||||
|
||||
public Integer getMob(int spice, int mobType, int classType)
|
||||
{
|
||||
if (_spiceToMob.containsKey(spice))
|
||||
{
|
||||
return _spiceToMob.get(spice)[mobType][classType];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getRandomMob(int spice)
|
||||
{
|
||||
int[][] temp;
|
||||
temp = _spiceToMob.get(spice);
|
||||
int rand = getRandom(temp[0].length);
|
||||
return temp[0][rand];
|
||||
}
|
||||
|
||||
public Integer getChance()
|
||||
{
|
||||
return _chance;
|
||||
}
|
||||
|
||||
public Integer getGrowthLevel()
|
||||
{
|
||||
return _growthLevel;
|
||||
}
|
||||
}
|
||||
|
||||
private FeedableBeasts()
|
||||
{
|
||||
super(FeedableBeasts.class.getSimpleName(), "ai/group_template");
|
||||
addKillId(FEEDABLE_BEASTS);
|
||||
addSkillSeeId(FEEDABLE_BEASTS);
|
||||
|
||||
// TODO: no grendels?
|
||||
GrowthCapableMob temp;
|
||||
|
||||
//@formatter:off
|
||||
final int[][] Kookabura_0_Gold = {{ 21452, 21453, 21454, 21455 }};
|
||||
final int[][] Kookabura_0_Crystal = {{ 21456, 21457, 21458, 21459 }};
|
||||
final int[][] Kookabura_1_Gold_1= {{ 21460, 21462 }};
|
||||
final int[][] Kookabura_1_Gold_2 = {{ 21461, 21463 }};
|
||||
final int[][] Kookabura_1_Crystal_1 = {{ 21464, 21466 }};
|
||||
final int[][] Kookabura_1_Crystal_2 = {{ 21465, 21467 }};
|
||||
final int[][] Kookabura_2_1 = {{ 21468, 21824}, { TRAINED_KOOKABURRA1, TRAINED_KOOKABURRA2 }};
|
||||
final int[][] Kookabura_2_2 = {{ 21469, 21825}, { TRAINED_KOOKABURRA1, TRAINED_KOOKABURRA2 }};
|
||||
|
||||
final int[][] Buffalo_0_Gold = {{ 21471, 21472, 21473, 21474 }};
|
||||
final int[][] Buffalo_0_Crystal = {{ 21475, 21476, 21477, 21478 }};
|
||||
final int[][] Buffalo_1_Gold_1 = {{ 21479, 21481 }};
|
||||
final int[][] Buffalo_1_Gold_2 = {{ 21481, 21482 }};
|
||||
final int[][] Buffalo_1_Crystal_1 = {{ 21483, 21485 }};
|
||||
final int[][] Buffalo_1_Crystal_2 = {{ 21484, 21486 }};
|
||||
final int[][] Buffalo_2_1 = {{ 21487, 21826}, {TRAINED_BUFFALO1, TRAINED_BUFFALO2 }};
|
||||
final int[][] Buffalo_2_2 = {{ 21488, 21827}, {TRAINED_BUFFALO1, TRAINED_BUFFALO2 }};
|
||||
|
||||
final int[][] Cougar_0_Gold = {{ 21490, 21491, 21492, 21493 }};
|
||||
final int[][] Cougar_0_Crystal = {{ 21494, 21495, 21496, 21497 }};
|
||||
final int[][] Cougar_1_Gold_1 = {{ 21498, 21500 }};
|
||||
final int[][] Cougar_1_Gold_2 = {{ 21499, 21501 }};
|
||||
final int[][] Cougar_1_Crystal_1 = {{ 21502, 21504 }};
|
||||
final int[][] Cougar_1_Crystal_2 = {{ 21503, 21505 }};
|
||||
final int[][] Cougar_2_1 = {{ 21506, 21828 }, { TRAINED_COUGAR1, TRAINED_COUGAR2 }};
|
||||
final int[][] Cougar_2_2 = {{ 21507, 21829 }, { TRAINED_COUGAR1, TRAINED_COUGAR2 }};
|
||||
//@formatter:on
|
||||
|
||||
// Alpen Kookabura
|
||||
temp = new GrowthCapableMob(0, 100);
|
||||
temp.addMobs(GOLDEN_SPICE, Kookabura_0_Gold);
|
||||
temp.addMobs(CRYSTAL_SPICE, Kookabura_0_Crystal);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21451, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(GOLDEN_SPICE, Kookabura_1_Gold_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21452, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21454, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(GOLDEN_SPICE, Kookabura_1_Gold_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21453, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21455, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(CRYSTAL_SPICE, Kookabura_1_Crystal_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21456, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21458, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(CRYSTAL_SPICE, Kookabura_1_Crystal_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21457, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21459, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(GOLDEN_SPICE, Kookabura_2_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21460, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21462, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(GOLDEN_SPICE, Kookabura_2_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21461, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21463, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(CRYSTAL_SPICE, Kookabura_2_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21464, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21466, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(CRYSTAL_SPICE, Kookabura_2_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21465, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21467, temp);
|
||||
|
||||
// Alpen Buffalo
|
||||
temp = new GrowthCapableMob(0, 100);
|
||||
temp.addMobs(GOLDEN_SPICE, Buffalo_0_Gold);
|
||||
temp.addMobs(CRYSTAL_SPICE, Buffalo_0_Crystal);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21470, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(GOLDEN_SPICE, Buffalo_1_Gold_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21471, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21473, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(GOLDEN_SPICE, Buffalo_1_Gold_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21472, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21474, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(CRYSTAL_SPICE, Buffalo_1_Crystal_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21475, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21477, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(CRYSTAL_SPICE, Buffalo_1_Crystal_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21476, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21478, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(GOLDEN_SPICE, Buffalo_2_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21479, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21481, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(GOLDEN_SPICE, Buffalo_2_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21480, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21482, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(CRYSTAL_SPICE, Buffalo_2_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21483, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21485, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(CRYSTAL_SPICE, Buffalo_2_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21484, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21486, temp);
|
||||
|
||||
// Alpen Cougar
|
||||
temp = new GrowthCapableMob(0, 100);
|
||||
temp.addMobs(GOLDEN_SPICE, Cougar_0_Gold);
|
||||
temp.addMobs(CRYSTAL_SPICE, Cougar_0_Crystal);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21489, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(GOLDEN_SPICE, Cougar_1_Gold_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21490, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21492, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(GOLDEN_SPICE, Cougar_1_Gold_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21491, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21493, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(CRYSTAL_SPICE, Cougar_1_Crystal_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21494, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21496, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(CRYSTAL_SPICE, Cougar_1_Crystal_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21495, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21497, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(GOLDEN_SPICE, Cougar_2_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21498, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21500, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(GOLDEN_SPICE, Cougar_2_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21499, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21501, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(CRYSTAL_SPICE, Cougar_2_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21502, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21504, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(CRYSTAL_SPICE, Cougar_2_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21503, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21505, temp);
|
||||
}
|
||||
|
||||
private void spawnNext(L2Npc npc, int growthLevel, L2PcInstance player, int food)
|
||||
{
|
||||
int npcId = npc.getId();
|
||||
int nextNpcId = 0;
|
||||
|
||||
// find the next mob to spawn, based on the current npcId, growthlevel, and food.
|
||||
if (growthLevel == 2)
|
||||
{
|
||||
// if tamed, the mob that will spawn depends on the class type (fighter/mage) of the player!
|
||||
if (getRandom(2) == 0)
|
||||
{
|
||||
if (player.getClassId().isMage())
|
||||
{
|
||||
nextNpcId = GROWTH_CAPABLE_MONSTERS.get(npcId).getMob(food, 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextNpcId = GROWTH_CAPABLE_MONSTERS.get(npcId).getMob(food, 1, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if not tamed, there is a small chance that have "mad cow" disease.
|
||||
// that is a stronger-than-normal animal that attacks its feeder
|
||||
if (getRandom(5) == 0)
|
||||
{
|
||||
nextNpcId = GROWTH_CAPABLE_MONSTERS.get(npcId).getMob(food, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextNpcId = GROWTH_CAPABLE_MONSTERS.get(npcId).getMob(food, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// all other levels of growth are straight-forward
|
||||
nextNpcId = GROWTH_CAPABLE_MONSTERS.get(npcId).getRandomMob(food);
|
||||
}
|
||||
|
||||
// remove the feedinfo of the mob that got despawned, if any
|
||||
if (FEED_INFO.containsKey(npc.getObjectId()))
|
||||
{
|
||||
if (FEED_INFO.get(npc.getObjectId()) == player.getObjectId())
|
||||
{
|
||||
FEED_INFO.remove(npc.getObjectId());
|
||||
}
|
||||
}
|
||||
// despawn the old mob
|
||||
// TODO: same code? FIXED?
|
||||
// @formatter:off
|
||||
/*
|
||||
* if (_GrowthCapableMobs.get(npcId).getGrowthLevel() == 0)
|
||||
{
|
||||
npc.deleteMe();
|
||||
}
|
||||
else
|
||||
{
|
||||
*/
|
||||
npc.deleteMe();
|
||||
// }
|
||||
// @formatter:on
|
||||
|
||||
// if this is finally a trained mob, then despawn any other trained mobs that the
|
||||
// player might have and initialize the Tamed Beast.
|
||||
if (Util.contains(TAMED_BEASTS, nextNpcId))
|
||||
{
|
||||
if ((player.getTrainedBeasts() != null) && !player.getTrainedBeasts().isEmpty())
|
||||
{
|
||||
for (L2TamedBeastInstance oldTrained : player.getTrainedBeasts())
|
||||
{
|
||||
oldTrained.deleteMe();
|
||||
}
|
||||
}
|
||||
|
||||
final L2TamedBeastInstance nextNpc = new L2TamedBeastInstance(nextNpcId, player, food - FOODSKILLDIFF, npc.getX(), npc.getY(), npc.getZ());
|
||||
nextNpc.setRunning();
|
||||
// Q00020_BringUpWithLove.checkJewelOfInnocence(player);
|
||||
|
||||
// Support for A Grand Plan for Taming Wild Beasts (655) quest.
|
||||
// Q00655_AGrandPlanForTamingWildBeasts.reward(player, nextNpc);
|
||||
|
||||
// also, perform a rare random chat
|
||||
if (getRandom(20) == 0)
|
||||
{
|
||||
NpcStringId message = NpcStringId.getNpcStringId(getRandom(2024, 2029));
|
||||
NpcSay packet = new NpcSay(nextNpc, ChatType.NPC_GENERAL, message);
|
||||
if (message.getParamCount() > 0) // player name, $s1
|
||||
{
|
||||
packet.addStringParameter(player.getName());
|
||||
}
|
||||
npc.broadcastPacket(packet);
|
||||
}
|
||||
// @formatter:off
|
||||
/*
|
||||
TODO: The tamed beast consumes one golden/crystal spice
|
||||
every 60 seconds with an initial delay of 60 seconds
|
||||
if (tamed beast exists and is alive)
|
||||
{
|
||||
if (player has 1+ golden/crystal spice)
|
||||
{
|
||||
take one golden/crystal spice;
|
||||
say random NpcString(getRandom(2029, 2038));
|
||||
}
|
||||
}
|
||||
*/
|
||||
// @formatter:on
|
||||
}
|
||||
else
|
||||
{
|
||||
// if not trained, the newly spawned mob will automatically be aggro against its feeder
|
||||
// (what happened to "never bite the hand that feeds you" anyway?!)
|
||||
L2Attackable nextNpc = (L2Attackable) addSpawn(nextNpcId, npc);
|
||||
|
||||
if (MAD_COW_POLYMORPH.containsKey(nextNpcId))
|
||||
{
|
||||
this.startQuestTimer("polymorph Mad Cow", 10000, nextNpc, player);
|
||||
}
|
||||
|
||||
// register the player in the feedinfo for the mob that just spawned
|
||||
FEED_INFO.put(nextNpc.getObjectId(), player.getObjectId());
|
||||
nextNpc.setRunning();
|
||||
nextNpc.addDamageHate(player, 0, 99999);
|
||||
nextNpc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("polymorph Mad Cow") && (npc != null) && (player != null))
|
||||
{
|
||||
if (MAD_COW_POLYMORPH.containsKey(npc.getId()))
|
||||
{
|
||||
// remove the feed info from the previous mob
|
||||
if (FEED_INFO.get(npc.getObjectId()) == player.getObjectId())
|
||||
{
|
||||
FEED_INFO.remove(npc.getObjectId());
|
||||
}
|
||||
// despawn the mad cow
|
||||
npc.deleteMe();
|
||||
// spawn the new mob
|
||||
L2Attackable nextNpc = (L2Attackable) addSpawn(MAD_COW_POLYMORPH.get(npc.getId()), npc);
|
||||
|
||||
// register the player in the feedinfo for the mob that just spawned
|
||||
FEED_INFO.put(nextNpc.getObjectId(), player.getObjectId());
|
||||
nextNpc.setRunning();
|
||||
nextNpc.addDamageHate(player, 0, 99999);
|
||||
nextNpc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, player);
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
|
||||
{
|
||||
// this behavior is only run when the target of skill is the passed npc (chest)
|
||||
// i.e. when the player is attempting to open the chest using a skill
|
||||
if (!Util.contains(targets, npc))
|
||||
{
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
// gather some values on local variables
|
||||
int npcId = npc.getId();
|
||||
int skillId = skill.getId();
|
||||
// check if the npc and skills used are valid for this script. Exit if invalid.
|
||||
if ((skillId != SKILL_GOLDEN_SPICE) && (skillId != SKILL_CRYSTAL_SPICE))
|
||||
{
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
// first gather some values on local variables
|
||||
int objectId = npc.getObjectId();
|
||||
int growthLevel = 3; // if a mob is in FEEDABLE_BEASTS but not in _GrowthCapableMobs, then it's at max growth (3)
|
||||
if (GROWTH_CAPABLE_MONSTERS.containsKey(npcId))
|
||||
{
|
||||
growthLevel = GROWTH_CAPABLE_MONSTERS.get(npcId).getGrowthLevel();
|
||||
}
|
||||
|
||||
// prevent exploit which allows 2 players to simultaneously raise the same 0-growth beast
|
||||
// If the mob is at 0th level (when it still listens to all feeders) lock it to the first feeder!
|
||||
if ((growthLevel == 0) && FEED_INFO.containsKey(objectId))
|
||||
{
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
FEED_INFO.put(objectId, caster.getObjectId());
|
||||
|
||||
int food = 0;
|
||||
if (skillId == SKILL_GOLDEN_SPICE)
|
||||
{
|
||||
food = GOLDEN_SPICE;
|
||||
}
|
||||
else if (skillId == SKILL_CRYSTAL_SPICE)
|
||||
{
|
||||
food = CRYSTAL_SPICE;
|
||||
}
|
||||
|
||||
// display the social action of the beast eating the food.
|
||||
npc.broadcastSocialAction(2);
|
||||
|
||||
// if this pet can't grow, it's all done.
|
||||
if (GROWTH_CAPABLE_MONSTERS.containsKey(npcId))
|
||||
{
|
||||
// do nothing if this mob doesn't eat the specified food (food gets consumed but has no effect).
|
||||
if (GROWTH_CAPABLE_MONSTERS.get(npcId).getMob(food, 0, 0) == null)
|
||||
{
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
// rare random talk...
|
||||
if (getRandom(20) == 0)
|
||||
{
|
||||
NpcStringId message = TEXT[growthLevel][getRandom(TEXT[growthLevel].length)];
|
||||
NpcSay packet = new NpcSay(npc, ChatType.NPC_GENERAL, message);
|
||||
if (message.getParamCount() > 0) // player name, $s1
|
||||
{
|
||||
packet.addStringParameter(caster.getName());
|
||||
}
|
||||
npc.broadcastPacket(packet);
|
||||
}
|
||||
|
||||
if ((growthLevel > 0) && (FEED_INFO.get(objectId) != caster.getObjectId()))
|
||||
{
|
||||
// check if this is the same player as the one who raised it from growth 0.
|
||||
// if no, then do not allow a chance to raise the pet (food gets consumed but has no effect).
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
// Polymorph the mob, with a certain chance, given its current growth level
|
||||
if (getRandom(100) < GROWTH_CAPABLE_MONSTERS.get(npcId).getChance())
|
||||
{
|
||||
spawnNext(npc, growthLevel, caster, food);
|
||||
}
|
||||
}
|
||||
else if (Util.contains(TAMED_BEASTS, npcId) && (npc instanceof L2TamedBeastInstance))
|
||||
{
|
||||
L2TamedBeastInstance beast = ((L2TamedBeastInstance) npc);
|
||||
if (skillId == beast.getFoodType())
|
||||
{
|
||||
beast.onReceiveFood();
|
||||
NpcStringId message = TAMED_TEXT[getRandom(TAMED_TEXT.length)];
|
||||
NpcSay packet = new NpcSay(npc, ChatType.NPC_GENERAL, message);
|
||||
if (message.getParamCount() > 0)
|
||||
{
|
||||
packet.addStringParameter(caster.getName());
|
||||
}
|
||||
beast.broadcastPacket(packet);
|
||||
}
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
// remove the feedinfo of the mob that got killed, if any
|
||||
if (FEED_INFO.containsKey(npc.getObjectId()))
|
||||
{
|
||||
FEED_INFO.remove(npc.getObjectId());
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new FeedableBeasts();
|
||||
}
|
||||
}
|
85
trunk/dist/game/data_classic/scripts/ai/group_template/FleeMonsters.java
vendored
Normal file
85
trunk/dist/game/data_classic/scripts/ai/group_template/FleeMonsters.java
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.GeoData;
|
||||
import com.l2jserver.gameserver.ai.CtrlIntention;
|
||||
import com.l2jserver.gameserver.model.Location;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.L2Summon;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.interfaces.ILocational;
|
||||
import com.l2jserver.gameserver.util.Util;
|
||||
|
||||
/**
|
||||
* Flee Monsters AI.
|
||||
* @author Pandragon, NosBit
|
||||
*/
|
||||
public final class FleeMonsters extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int[] MOBS =
|
||||
{
|
||||
18150, // Victim
|
||||
18151, // Victim
|
||||
18152, // Victim
|
||||
18153, // Victim
|
||||
18154, // Victim
|
||||
18155, // Victim
|
||||
18156, // Victim
|
||||
18157, // Victim
|
||||
20002, // Rabbit
|
||||
20432, // Elpy
|
||||
22228, // Grey Elpy
|
||||
25604, // Mutated Elpy
|
||||
};
|
||||
// Misc
|
||||
private static final int FLEE_DISTANCE = 500;
|
||||
|
||||
private FleeMonsters()
|
||||
{
|
||||
super(FleeMonsters.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(MOBS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
npc.disableCoreAI(true);
|
||||
npc.setRunning();
|
||||
|
||||
final L2Summon summon = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : null;
|
||||
final ILocational attackerLoc = summon == null ? attacker : summon;
|
||||
final double radians = Math.toRadians(Util.calculateAngleFrom(attackerLoc, npc));
|
||||
final int posX = (int) (npc.getX() + (FLEE_DISTANCE * Math.cos(radians)));
|
||||
final int posY = (int) (npc.getY() + (FLEE_DISTANCE * Math.sin(radians)));
|
||||
final int posZ = npc.getZ();
|
||||
|
||||
final Location destination = GeoData.getInstance().moveCheck(npc.getX(), npc.getY(), npc.getZ(), posX, posY, posZ, attacker.getInstanceId());
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new FleeMonsters();
|
||||
}
|
||||
}
|
71
trunk/dist/game/data_classic/scripts/ai/group_template/FrozenLabyrinth.java
vendored
Normal file
71
trunk/dist/game/data_classic/scripts/ai/group_template/FrozenLabyrinth.java
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
|
||||
/**
|
||||
* Frozen Labyrinth AI.
|
||||
* @author malyelfik
|
||||
*/
|
||||
public final class FrozenLabyrinth extends AbstractNpcAI
|
||||
{
|
||||
// Monsters
|
||||
private static final int PRONGHORN_SPIRIT = 22087;
|
||||
private static final int PRONGHORN = 22088;
|
||||
private static final int LOST_BUFFALO = 22093;
|
||||
private static final int FROST_BUFFALO = 22094;
|
||||
|
||||
private FrozenLabyrinth()
|
||||
{
|
||||
super(FrozenLabyrinth.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(PRONGHORN, FROST_BUFFALO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
|
||||
{
|
||||
if (npc.isScriptValue(0) && (skill != null) && !skill.isMagic())
|
||||
{
|
||||
final int spawnId = (npc.getId() == PRONGHORN) ? PRONGHORN_SPIRIT : LOST_BUFFALO;
|
||||
int diff = 0;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
final int x = diff < 60 ? npc.getX() + diff : npc.getX();
|
||||
final int y = diff >= 60 ? npc.getY() + (diff - 40) : npc.getY();
|
||||
|
||||
final L2Npc monster = addSpawn(spawnId, x, y, npc.getZ(), npc.getHeading(), false, 0);
|
||||
addAttackPlayerDesire(monster, attacker);
|
||||
diff += 20;
|
||||
}
|
||||
npc.setScriptValue(1);
|
||||
npc.deleteMe();
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon, skill);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new FrozenLabyrinth();
|
||||
}
|
||||
}
|
114
trunk/dist/game/data_classic/scripts/ai/group_template/GiantsCave.java
vendored
Normal file
114
trunk/dist/game/data_classic/scripts/ai/group_template/GiantsCave.java
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.actor.L2Character;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
|
||||
/**
|
||||
* Giant's Cave AI.
|
||||
* @author Gnacik, St3eT
|
||||
*/
|
||||
public final class GiantsCave extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int[] SCOUTS =
|
||||
{
|
||||
22668, // Gamlin (Scout)
|
||||
22669, // Leogul (Scout)
|
||||
};
|
||||
|
||||
private GiantsCave()
|
||||
{
|
||||
super(GiantsCave.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(SCOUTS);
|
||||
addAggroRangeEnterId(SCOUTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equals("ATTACK") && (player != null) && (npc != null) && !npc.isDead())
|
||||
{
|
||||
if (npc.getId() == SCOUTS[0]) // Gamlin
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_SHOUT, NpcStringId.INTRUDER_DETECTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_SHOUT, NpcStringId.OH_GIANTS_AN_INTRUDER_HAS_BEEN_DISCOVERED);
|
||||
}
|
||||
|
||||
for (L2Character characters : npc.getKnownList().getKnownCharactersInRadius(450))
|
||||
{
|
||||
if ((characters != null) && (characters.isAttackable()) && (getRandomBoolean()))
|
||||
{
|
||||
addAttackPlayerDesire((L2Npc) characters, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equals("CLEAR") && (npc != null) && !npc.isDead())
|
||||
{
|
||||
npc.setScriptValue(0);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
startQuestTimer("ATTACK", 6000, npc, attacker);
|
||||
startQuestTimer("CLEAR", 120000, npc, null);
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
if (getRandomBoolean())
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.YOU_GUYS_ARE_DETECTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.WHAT_KIND_OF_CREATURES_ARE_YOU);
|
||||
}
|
||||
startQuestTimer("ATTACK", 6000, npc, player);
|
||||
startQuestTimer("CLEAR", 120000, npc, null);
|
||||
}
|
||||
return super.onAggroRangeEnter(npc, player, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new GiantsCave();
|
||||
}
|
||||
}
|
109
trunk/dist/game/data_classic/scripts/ai/group_template/HotSprings.java
vendored
Normal file
109
trunk/dist/game/data_classic/scripts/ai/group_template/HotSprings.java
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.datatables.SkillData;
|
||||
import com.l2jserver.gameserver.model.actor.L2Character;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.skills.BuffInfo;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
|
||||
/**
|
||||
* Hot Springs AI.
|
||||
* @author Pandragon
|
||||
*/
|
||||
public final class HotSprings extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int BANDERSNATCHLING = 21314;
|
||||
private static final int FLAVA = 21316;
|
||||
private static final int ATROXSPAWN = 21317;
|
||||
private static final int NEPENTHES = 21319;
|
||||
private static final int ATROX = 21321;
|
||||
private static final int BANDERSNATCH = 21322;
|
||||
// Skills
|
||||
private static final int RHEUMATISM = 4551;
|
||||
private static final int CHOLERA = 4552;
|
||||
private static final int FLU = 4553;
|
||||
private static final int MALARIA = 4554;
|
||||
// Misc
|
||||
private static final int DISEASE_CHANCE = 10;
|
||||
|
||||
private HotSprings()
|
||||
{
|
||||
super(HotSprings.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(BANDERSNATCHLING, FLAVA, ATROXSPAWN, NEPENTHES, ATROX, BANDERSNATCH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (getRandom(100) < DISEASE_CHANCE)
|
||||
{
|
||||
tryToInfect(npc, attacker, MALARIA);
|
||||
}
|
||||
|
||||
if (getRandom(100) < DISEASE_CHANCE)
|
||||
{
|
||||
switch (npc.getId())
|
||||
{
|
||||
case BANDERSNATCHLING:
|
||||
case ATROX:
|
||||
{
|
||||
tryToInfect(npc, attacker, RHEUMATISM);
|
||||
break;
|
||||
}
|
||||
case FLAVA:
|
||||
case NEPENTHES:
|
||||
{
|
||||
tryToInfect(npc, attacker, CHOLERA);
|
||||
break;
|
||||
}
|
||||
case ATROXSPAWN:
|
||||
case BANDERSNATCH:
|
||||
{
|
||||
tryToInfect(npc, attacker, FLU);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
private void tryToInfect(L2Npc npc, L2Character player, int diseaseId)
|
||||
{
|
||||
final BuffInfo info = player.getEffectList().getBuffInfoBySkillId(diseaseId);
|
||||
final int skillLevel = (info == null) ? 1 : (info.getSkill().getLevel() < 10) ? info.getSkill().getLevel() + 1 : 10;
|
||||
final Skill skill = SkillData.getInstance().getSkill(diseaseId, skillLevel);
|
||||
|
||||
if ((skill != null) && !npc.isCastingNow() && npc.checkDoCastConditions(skill))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(skill);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new HotSprings();
|
||||
}
|
||||
}
|
455
trunk/dist/game/data_classic/scripts/ai/group_template/MinionSpawnManager.java
vendored
Normal file
455
trunk/dist/game/data_classic/scripts/ai/group_template/MinionSpawnManager.java
vendored
Normal file
@@ -0,0 +1,455 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.MinionHolder;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
|
||||
/**
|
||||
* Minion Spawn Manager.
|
||||
* @author Zealar
|
||||
*/
|
||||
public final class MinionSpawnManager extends AbstractNpcAI
|
||||
{
|
||||
private static final Set<Integer> NPC = new HashSet<>(354);
|
||||
|
||||
static
|
||||
{
|
||||
NPC.add(18344); // Ancient Egg
|
||||
NPC.add(18352); // Kamael Guard
|
||||
NPC.add(18353); // Guardian of Records
|
||||
NPC.add(18354); // Guardian of Observation
|
||||
NPC.add(18355); // Spicula's Guard
|
||||
NPC.add(18356); // Harkilgamed's Gatekeeper
|
||||
NPC.add(18357); // Rodenpicula's Gatekeeper
|
||||
NPC.add(18359); // Arviterre's Guardian
|
||||
NPC.add(18360); // Katenar's Gatekeeper
|
||||
NPC.add(18361); // Guardian of Prediction
|
||||
NPC.add(18484); // Naia Failan
|
||||
NPC.add(18491); // Lock
|
||||
NPC.add(18547); // Ancient Experiment
|
||||
NPC.add(18551); // Cruma Phantom
|
||||
NPC.add(35375); // Bloody Lord Nurka
|
||||
NPC.add(20376); // Varikan Brigand Leader
|
||||
NPC.add(20398); // Vrykolakas
|
||||
NPC.add(20520); // Pirate Captain Uthanka
|
||||
NPC.add(20522); // White Fang
|
||||
NPC.add(20738); // Kobold Looter Bepook
|
||||
NPC.add(20745); // Gigantiops
|
||||
NPC.add(20747); // Roxide
|
||||
NPC.add(20749); // Death Fire
|
||||
NPC.add(20751); // Snipe
|
||||
NPC.add(20753); // Dark Lord
|
||||
NPC.add(20755); // Talakin
|
||||
NPC.add(20758); // Dragon Bearer Chief
|
||||
NPC.add(20761); // Pytan
|
||||
NPC.add(20767); // Timak Orc Troop Leader
|
||||
NPC.add(20773); // Conjurer Bat Lord
|
||||
NPC.add(20939); // Tanor Silenos Warrior
|
||||
NPC.add(20941); // Tanor Silenos Chieftain
|
||||
NPC.add(20944); // Nightmare Lord
|
||||
NPC.add(20956); // Past Knight
|
||||
NPC.add(20959); // Dark Guard
|
||||
NPC.add(20963); // Bloody Lord
|
||||
NPC.add(20974); // Spiteful Soul Leader
|
||||
NPC.add(20977); // Elmoradan's Lady
|
||||
NPC.add(20980); // Hallate's Follower Mul
|
||||
NPC.add(20983); // Binder
|
||||
NPC.add(20986); // Sairon
|
||||
NPC.add(20991); // Swamp Tribe
|
||||
NPC.add(20994); // Garden Guard Leader
|
||||
NPC.add(21075); // Slaughter Bathin
|
||||
NPC.add(21078); // Magus Valac
|
||||
NPC.add(21081); // Power Angel Amon
|
||||
NPC.add(21090); // Bloody Guardian
|
||||
NPC.add(21312); // Eye of Ruler
|
||||
NPC.add(21343); // Ketra Commander
|
||||
NPC.add(21345); // Ketra's Head Shaman
|
||||
NPC.add(21347); // Ketra Prophet
|
||||
NPC.add(21369); // Varka's Commander
|
||||
NPC.add(21371); // Varka's Head Magus
|
||||
NPC.add(21373); // Varka's Prophet
|
||||
NPC.add(21432); // Chakram Beetle
|
||||
NPC.add(21434); // Seer of Blood
|
||||
NPC.add(21512); // Splinter Stakato Drone
|
||||
NPC.add(21517); // Needle Stakato Drone
|
||||
NPC.add(21541); // Pilgrim of Splendor
|
||||
NPC.add(21544); // Judge of Splendor
|
||||
NPC.add(21596); // Requiem Lord
|
||||
NPC.add(21599); // Requiem Priest
|
||||
NPC.add(21652); // Scarlet Stakato Noble
|
||||
NPC.add(21653); // Assassin Beetle
|
||||
NPC.add(21654); // Necromancer of Destruction
|
||||
NPC.add(21655); // Arimanes of Destruction
|
||||
NPC.add(21656); // Ashuras of Destruction
|
||||
NPC.add(21657); // Magma Drake
|
||||
NPC.add(22028); // Vagabond of the Ruins
|
||||
NPC.add(22080); // Massive Lost Bandersnatch
|
||||
NPC.add(22084); // Panthera
|
||||
NPC.add(22092); // Frost Iron Golem
|
||||
NPC.add(22096); // Ursus
|
||||
NPC.add(22100); // Freya's Gardener
|
||||
NPC.add(22102); // Freya's Servant
|
||||
NPC.add(22104); // Freya's Dog
|
||||
NPC.add(22155); // Triol's High Priest
|
||||
NPC.add(22159); // Triol's High Priest
|
||||
NPC.add(22163); // Triol's High Priest
|
||||
NPC.add(22167); // Triol's High Priest
|
||||
NPC.add(22171); // Triol's High Priest
|
||||
NPC.add(22188); // Andreas' Captain of the Royal Guard
|
||||
NPC.add(22196); // Velociraptor
|
||||
NPC.add(22198); // Velociraptor
|
||||
NPC.add(22202); // Ornithomimus
|
||||
NPC.add(22205); // Deinonychus
|
||||
NPC.add(22210); // Pachycephalosaurus
|
||||
NPC.add(22213); // Wild Strider
|
||||
NPC.add(22223); // Velociraptor
|
||||
NPC.add(22224); // Ornithomimus
|
||||
NPC.add(22225); // Deinonychus
|
||||
NPC.add(22275); // Gatekeeper Lohan
|
||||
NPC.add(22277); // Gatekeeper Provo
|
||||
NPC.add(22305); // Kechi's Captain
|
||||
NPC.add(22306); // Kechi's Captain
|
||||
NPC.add(22307); // Kechi's Captain
|
||||
NPC.add(22320); // Junior Watchman
|
||||
NPC.add(22321); // Junior Summoner
|
||||
NPC.add(22346); // Quarry Foreman
|
||||
NPC.add(22363); // Body Destroyer
|
||||
NPC.add(22370); // Passageway Captain
|
||||
NPC.add(22377); // Master Zelos
|
||||
NPC.add(22390); // Foundry Foreman
|
||||
NPC.add(22416); // Kechi's Captain
|
||||
NPC.add(22423); // Original Sin Warden
|
||||
NPC.add(22431); // Original Sin Warden
|
||||
NPC.add(22448); // Leodas
|
||||
NPC.add(22449); // Amaskari
|
||||
NPC.add(22621); // Male Spiked Stakato
|
||||
NPC.add(22625); // Cannibalistic Stakato Leader
|
||||
NPC.add(22630); // Spiked Stakato Nurse
|
||||
NPC.add(22666); // Barif
|
||||
NPC.add(22670); // Cursed Lord
|
||||
NPC.add(22742); // Ornithomimus
|
||||
NPC.add(22743); // Deinonychus
|
||||
NPC.add(25001); // Greyclaw Kutus
|
||||
NPC.add(25004); // Turek Mercenary Captain
|
||||
NPC.add(25007); // Retreat Spider Cletu
|
||||
NPC.add(25010); // Furious Thieles
|
||||
NPC.add(25013); // Ghost of Peasant Leader
|
||||
NPC.add(25016); // The 3rd Underwater Guardian
|
||||
NPC.add(25020); // Breka Warlock Pastu
|
||||
NPC.add(25023); // Stakato Queen Zyrnna
|
||||
NPC.add(25026); // Ketra Commander Atis
|
||||
NPC.add(25029); // Atraiban
|
||||
NPC.add(25032); // Eva's Guardian Millenu
|
||||
NPC.add(25035); // Shilen's Messenger Cabrio
|
||||
NPC.add(25038); // Tirak
|
||||
NPC.add(25041); // Remmel
|
||||
NPC.add(25044); // Barion
|
||||
NPC.add(25047); // Karte
|
||||
NPC.add(25051); // Rahha
|
||||
NPC.add(25054); // Kernon
|
||||
NPC.add(25057); // Beacon of Blue Sky
|
||||
NPC.add(25060); // Unrequited Kael
|
||||
NPC.add(25064); // Wizard of Storm Teruk
|
||||
NPC.add(25067); // Captain of Red Flag Shaka
|
||||
NPC.add(25070); // Enchanted Forest Watcher Ruell
|
||||
NPC.add(25073); // Bloody Priest Rudelto
|
||||
NPC.add(25076); // Princess Molrang
|
||||
NPC.add(25079); // Cat's Eye Bandit
|
||||
NPC.add(25082); // Leader of Cat Gang
|
||||
NPC.add(25085); // Timak Orc Chief Ranger
|
||||
NPC.add(25089); // Soulless Wild Boar
|
||||
NPC.add(25092); // Korim
|
||||
NPC.add(25095); // Elf Renoa
|
||||
NPC.add(25099); // Rotting Tree Repiro
|
||||
NPC.add(25103); // Sorcerer Isirr
|
||||
NPC.add(25106); // Ghost of the Well Lidia
|
||||
NPC.add(25109); // Antharas Priest Cloe
|
||||
NPC.add(25112); // Beleth's Agent, Meana
|
||||
NPC.add(25115); // Icarus Sample 1
|
||||
NPC.add(25119); // Messenger of Fairy Queen Berun
|
||||
NPC.add(25122); // Refugee Applicant Leo
|
||||
NPC.add(25128); // Vuku Grand Seer Gharmash
|
||||
NPC.add(25131); // Carnage Lord Gato
|
||||
NPC.add(25134); // Leto Chief Talkin
|
||||
NPC.add(25137); // Beleth's Seer, Sephia
|
||||
NPC.add(25140); // Hekaton Prime
|
||||
NPC.add(25143); // Fire of Wrath Shuriel
|
||||
NPC.add(25146); // Serpent Demon Bifrons
|
||||
NPC.add(25149); // Zombie Lord Crowl
|
||||
NPC.add(25152); // Flame Lord Shadar
|
||||
NPC.add(25155); // Shaman King Selu
|
||||
NPC.add(25159); // Paniel the Unicorn
|
||||
NPC.add(25166); // Ikuntai
|
||||
NPC.add(25170); // Lizardmen Leader Hellion
|
||||
NPC.add(25173); // Tiger King Karuta
|
||||
NPC.add(25176); // Black Lily
|
||||
NPC.add(25179); // Guardian of the Statue of Giant Karum
|
||||
NPC.add(25182); // Demon Kuri
|
||||
NPC.add(25185); // Tasaba Patriarch Hellena
|
||||
NPC.add(25189); // Cronos's Servitor Mumu
|
||||
NPC.add(25192); // Earth Protector Panathen
|
||||
NPC.add(25199); // Water Dragon Seer Sheshark
|
||||
NPC.add(25202); // Krokian Padisha Sobekk
|
||||
NPC.add(25205); // Ocean Flame Ashakiel
|
||||
NPC.add(25208); // Water Couatle Ateka
|
||||
NPC.add(25211); // Sebek
|
||||
NPC.add(25214); // Fafurion's Page Sika
|
||||
NPC.add(25217); // Cursed Clara
|
||||
NPC.add(25220); // Death Lord Hallate
|
||||
NPC.add(25223); // Soul Collector Acheron
|
||||
NPC.add(25226); // Roaring Lord Kastor
|
||||
NPC.add(25230); // Timak Seer Ragoth
|
||||
NPC.add(25235); // Vanor Chief Kandra
|
||||
NPC.add(25238); // Abyss Brukunt
|
||||
NPC.add(25241); // Harit Hero Tamash
|
||||
NPC.add(25245); // Last Lesser Giant Glaki
|
||||
NPC.add(25249); // Menacing Palatanos
|
||||
NPC.add(25252); // Palibati Queen Themis
|
||||
NPC.add(25256); // Taik High Prefect Arak
|
||||
NPC.add(25260); // Iron Giant Totem
|
||||
NPC.add(25263); // Kernon's Faithful Servant Kelone
|
||||
NPC.add(25266); // Bloody Empress Decarbia
|
||||
NPC.add(25269); // Beast Lord Behemoth
|
||||
NPC.add(25273); // Carnamakos
|
||||
NPC.add(25277); // Lilith's Witch Marilion
|
||||
NPC.add(25283); // Lilith
|
||||
NPC.add(25286); // Anakim
|
||||
NPC.add(25290); // Daimon the White-Eyed
|
||||
NPC.add(25293); // Hesti Guardian Deity of the Hot Springs
|
||||
NPC.add(25296); // Icicle Emperor Bumbalump
|
||||
NPC.add(25299); // Ketra's Hero Hekaton
|
||||
NPC.add(25302); // Ketra's Commander Tayr
|
||||
NPC.add(25306); // Soul of Fire Nastron
|
||||
NPC.add(25309); // Varka's Hero Shadith
|
||||
NPC.add(25312); // Varka's Commander Mos
|
||||
NPC.add(25316); // Soul of Water Ashutar
|
||||
NPC.add(25319); // Ember
|
||||
NPC.add(25322); // Demon's Agent Falston
|
||||
NPC.add(25325); // Flame of Splendor Barakiel
|
||||
NPC.add(25328); // Eilhalder von Hellmann
|
||||
NPC.add(25352); // Giant Wasteland Basilisk
|
||||
NPC.add(25354); // Gargoyle Lord Sirocco
|
||||
NPC.add(25357); // Sukar Wererat Chief
|
||||
NPC.add(25360); // Tiger Hornet
|
||||
NPC.add(25362); // Tracker Leader Sharuk
|
||||
NPC.add(25366); // Kuroboros' Priest
|
||||
NPC.add(25369); // Soul Scavenger
|
||||
NPC.add(25373); // Malex Herald of Dagoniel
|
||||
NPC.add(25375); // Zombie Lord Ferkel
|
||||
NPC.add(25378); // Madness Beast
|
||||
NPC.add(25380); // Kaysha Herald of Icarus
|
||||
NPC.add(25383); // Revenant of Sir Calibus
|
||||
NPC.add(25385); // Evil Spirit Tempest
|
||||
NPC.add(25388); // Red Eye Captain Trakia
|
||||
NPC.add(25392); // Captain of Queen's Royal Guards
|
||||
NPC.add(25395); // Archon Suscepter
|
||||
NPC.add(25398); // Beleth's Eye
|
||||
NPC.add(25401); // Skyla
|
||||
NPC.add(25404); // Corsair Captain Kylon
|
||||
NPC.add(25407); // Lord Ishka
|
||||
NPC.add(25410); // Road Scavenger Leader
|
||||
NPC.add(25412); // Necrosentinel Royal Guard
|
||||
NPC.add(25415); // Nakondas
|
||||
NPC.add(25418); // Dread Avenger Kraven
|
||||
NPC.add(25420); // Orfen's Handmaiden
|
||||
NPC.add(25423); // Fairy Queen Timiniel
|
||||
NPC.add(25426); // Betrayer of Urutu Freki
|
||||
NPC.add(25429); // Mammon Collector Talos
|
||||
NPC.add(25431); // Flamestone Golem
|
||||
NPC.add(25434); // Bandit Leader Barda
|
||||
NPC.add(25438); // Thief Kelbar
|
||||
NPC.add(25441); // Evil Spirit Cyrion
|
||||
NPC.add(25444); // Enmity Ghost Ramdal
|
||||
NPC.add(25447); // Immortal Savior Mardil
|
||||
NPC.add(25450); // Cherub Galaxia
|
||||
NPC.add(25453); // Meanas Anor
|
||||
NPC.add(25456); // Mirror of Oblivion
|
||||
NPC.add(25460); // Deadman Ereve
|
||||
NPC.add(25463); // Harit Guardian Garangky
|
||||
NPC.add(25467); // Gorgolos
|
||||
NPC.add(25470); // Last Titan Utenus
|
||||
NPC.add(25473); // Grave Robber Kim
|
||||
NPC.add(25475); // Ghost Knight Kabed
|
||||
NPC.add(25478); // Shilen's Priest Hisilrome
|
||||
NPC.add(25481); // Magus Kenishee
|
||||
NPC.add(25484); // Zaken's Chief Mate Tillion
|
||||
NPC.add(25487); // Water Spirit Lian
|
||||
NPC.add(25490); // Gwindorr
|
||||
NPC.add(25493); // Eva's Spirit Niniel
|
||||
NPC.add(25496); // Fafurion's Envoy Pingolpin
|
||||
NPC.add(25498); // Fafurion's Henchman Istary
|
||||
NPC.add(25501); // Boss Akata
|
||||
NPC.add(25504); // Nellis' Vengeful Spirit
|
||||
NPC.add(25506); // Rayito the Looter
|
||||
NPC.add(25509); // Dark Shaman Varangka
|
||||
NPC.add(25514); // Queen Shyeed
|
||||
NPC.add(25524); // Flamestone Giant
|
||||
NPC.add(25528); // Tiberias
|
||||
NPC.add(25536); // Hannibal
|
||||
NPC.add(25546); // Rhianna the Traitor
|
||||
NPC.add(25549); // Tesla the Deceiver
|
||||
NPC.add(25554); // Brutus the Obstinate
|
||||
NPC.add(25557); // Ranger Karankawa
|
||||
NPC.add(25560); // Sargon the Mad
|
||||
NPC.add(25563); // Beautiful Atrielle
|
||||
NPC.add(25566); // Nagen the Tomboy
|
||||
NPC.add(25569); // Jax the Destroyer
|
||||
NPC.add(25572); // Hager the Outlaw
|
||||
NPC.add(25575); // All-Seeing Rango
|
||||
NPC.add(25579); // Helsing
|
||||
NPC.add(25582); // Gillien
|
||||
NPC.add(25585); // Medici
|
||||
NPC.add(25589); // Brand the Exile
|
||||
NPC.add(25593); // Gerg the Hunter
|
||||
NPC.add(25600); // Temenir
|
||||
NPC.add(25601); // Draksius
|
||||
NPC.add(25602); // Kiretcenah
|
||||
NPC.add(25671); // Queen Shyeed
|
||||
NPC.add(25674); // Gwindorr
|
||||
NPC.add(25677); // Water Spirit Lian
|
||||
NPC.add(25681); // Gorgolos
|
||||
NPC.add(25684); // Last Titan Utenus
|
||||
NPC.add(25687); // Hekaton Prime
|
||||
NPC.add(25703); // Gigantic Golem
|
||||
NPC.add(25710); // Lost Captain
|
||||
NPC.add(25735); // Greyclaw Kutus
|
||||
NPC.add(25738); // Lead Tracker Sharuk
|
||||
NPC.add(25741); // Sukar Wererat Chief
|
||||
NPC.add(25744); // Ikuntai
|
||||
NPC.add(25747); // Zombie Lord Crowl
|
||||
NPC.add(25750); // Zombie Lord Ferkel
|
||||
NPC.add(25754); // Fire Lord Shadar
|
||||
NPC.add(25757); // Soul Collector Acheron
|
||||
NPC.add(25760); // Lord Ishka
|
||||
NPC.add(25763); // Demon Kuri
|
||||
NPC.add(25767); // Carnage Lord Gato
|
||||
NPC.add(25770); // Ketra Commander Atis
|
||||
NPC.add(25773); // Beacon of Blue Sky
|
||||
NPC.add(25776); // Earth Protector Panathen
|
||||
NPC.add(25779); // Betrayer of Urutu Freki
|
||||
NPC.add(25782); // Nellis' Vengeful Spirit
|
||||
NPC.add(25784); // Rayito the Looter
|
||||
NPC.add(25787); // Ketra's Hero Hekaton
|
||||
NPC.add(25790); // Varka's Hero Shadith
|
||||
NPC.add(25794); // Kernon
|
||||
NPC.add(25797); // Meanas Anor
|
||||
NPC.add(25800); // Mammon Collector Talos
|
||||
NPC.add(27036); // Calpico
|
||||
NPC.add(27041); // Varangka's Messenger
|
||||
NPC.add(27062); // Tanukia
|
||||
NPC.add(27065); // Roko
|
||||
NPC.add(27068); // Murtika
|
||||
NPC.add(27093); // Delu Chief Kalkis
|
||||
NPC.add(27108); // Stenoa Gorgon Queen
|
||||
NPC.add(27110); // Shyslassys
|
||||
NPC.add(27112); // Gorr
|
||||
NPC.add(27113); // Baraham
|
||||
NPC.add(27114); // Succubus Queen
|
||||
NPC.add(27185); // Fairy Tree of Wind
|
||||
NPC.add(27186); // Fairy Tree of Star
|
||||
NPC.add(27187); // Fairy Tree of Twilight
|
||||
NPC.add(27188); // Fairy Tree of Abyss
|
||||
NPC.add(27259); // Archangel Iconoclasis
|
||||
NPC.add(27260); // Archangel Iconoclasis
|
||||
NPC.add(27266); // Fallen Angel Haures
|
||||
NPC.add(27267); // Fallen Angel Haures
|
||||
NPC.add(27290); // White Wing Commander
|
||||
NPC.add(29030); // Fenril Hound Kerinne
|
||||
NPC.add(29033); // Fenril Hound Freki
|
||||
NPC.add(29037); // Fenril Hound Kinaz
|
||||
NPC.add(29040); // Wings of Flame, Ixion
|
||||
NPC.add(29056); // Ice Fairy Sirra
|
||||
NPC.add(29062); // Andreas Van Halter
|
||||
NPC.add(29096); // Anais
|
||||
NPC.add(29129); // Lost Captain
|
||||
NPC.add(29132); // Lost Captain
|
||||
NPC.add(29135); // Lost Captain
|
||||
NPC.add(29138); // Lost Captain
|
||||
NPC.add(29141); // Lost Captain
|
||||
NPC.add(29144); // Lost Captain
|
||||
NPC.add(29147); // Lost Captain
|
||||
}
|
||||
|
||||
private static final NpcStringId[] ON_ATTACK_MSG =
|
||||
{
|
||||
NpcStringId.COME_OUT_YOU_CHILDREN_OF_DARKNESS,
|
||||
NpcStringId.SHOW_YOURSELVES,
|
||||
NpcStringId.DESTROY_THE_ENEMY_MY_BROTHERS,
|
||||
NpcStringId.FORCES_OF_DARKNESS_FOLLOW_ME
|
||||
};
|
||||
|
||||
private static final int[] ON_ATTACK_NPC =
|
||||
{
|
||||
20767, // Timak Orc Troop Leader
|
||||
};
|
||||
|
||||
private MinionSpawnManager()
|
||||
{
|
||||
super(MinionSpawnManager.class.getSimpleName(), "ai/group_template");
|
||||
|
||||
addSpawnId(NPC);
|
||||
addAttackId(ON_ATTACK_NPC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
if (npc.getTemplate().getParameters().getSet().get("SummonPrivateRate") == null)
|
||||
{
|
||||
((L2MonsterInstance) npc).getMinionList().spawnMinions(npc.getTemplate().getParameters().getMinionList("Privates"));
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.isMonster())
|
||||
{
|
||||
final L2MonsterInstance monster = (L2MonsterInstance) npc;
|
||||
if (!monster.isTeleporting())
|
||||
{
|
||||
if (getRandom(1, 100) <= npc.getTemplate().getParameters().getInt("SummonPrivateRate", 0))
|
||||
{
|
||||
for (MinionHolder is : npc.getTemplate().getParameters().getMinionList("Privates"))
|
||||
{
|
||||
addMinion((L2MonsterInstance) npc, is.getId());
|
||||
}
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, ON_ATTACK_MSG[getRandom(ON_ATTACK_MSG.length)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new MinionSpawnManager();
|
||||
}
|
||||
}
|
296
trunk/dist/game/data_classic/scripts/ai/group_template/MonasteryOfSilence.java
vendored
Normal file
296
trunk/dist/game/data_classic/scripts/ai/group_template/MonasteryOfSilence.java
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.ai.CtrlIntention;
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.L2Object;
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Character;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.effects.L2EffectType;
|
||||
import com.l2jserver.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
|
||||
/**
|
||||
* Monastery of Silence AI.
|
||||
* @author Kerberos, nonom
|
||||
*/
|
||||
public final class MonasteryOfSilence extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int CAPTAIN = 18910; // Solina Knight Captain
|
||||
private static final int KNIGHT = 18909; // Solina Knights
|
||||
private static final int SCARECROW = 18912; // Scarecrow
|
||||
private static final int GUIDE = 22789; // Guide Solina
|
||||
private static final int SEEKER = 22790; // Seeker Solina
|
||||
private static final int SAVIOR = 22791; // Savior Solina
|
||||
private static final int ASCETIC = 22793; // Ascetic Solina
|
||||
private static final int[] DIVINITY_CLAN =
|
||||
{
|
||||
22794, // Divinity Judge
|
||||
22795, // Divinity Manager
|
||||
};
|
||||
// Skills
|
||||
private static final SkillHolder ORDEAL_STRIKE = new SkillHolder(6303, 1); // Trial of the Coup
|
||||
private static final SkillHolder LEADER_STRIKE = new SkillHolder(6304, 1); // Shock
|
||||
private static final SkillHolder SAVER_STRIKE = new SkillHolder(6305, 1); // Sacred Gnosis
|
||||
private static final SkillHolder SAVER_BLEED = new SkillHolder(6306, 1); // Solina Strike
|
||||
private static final SkillHolder LEARNING_MAGIC = new SkillHolder(6308, 1); // Opus of the Wave
|
||||
private static final SkillHolder STUDENT_CANCEL = new SkillHolder(6310, 1); // Loss of Quest
|
||||
private static final SkillHolder WARRIOR_THRUSTING = new SkillHolder(6311, 1); // Solina Thrust
|
||||
private static final SkillHolder KNIGHT_BLESS = new SkillHolder(6313, 1); // Solina Bless
|
||||
// Misc
|
||||
private static final NpcStringId[] DIVINITY_MSG =
|
||||
{
|
||||
NpcStringId.S1_WHY_WOULD_YOU_CHOOSE_THE_PATH_OF_DARKNESS,
|
||||
NpcStringId.S1_HOW_DARE_YOU_DEFY_THE_WILL_OF_EINHASAD
|
||||
};
|
||||
private static final NpcStringId[] SOLINA_KNIGHTS_MSG =
|
||||
{
|
||||
NpcStringId.PUNISH_ALL_THOSE_WHO_TREAD_FOOTSTEPS_IN_THIS_PLACE,
|
||||
NpcStringId.WE_ARE_THE_SWORD_OF_TRUTH_THE_SWORD_OF_SOLINA,
|
||||
NpcStringId.WE_RAISE_OUR_BLADES_FOR_THE_GLORY_OF_SOLINA
|
||||
};
|
||||
|
||||
private MonasteryOfSilence()
|
||||
{
|
||||
super(MonasteryOfSilence.class.getSimpleName(), "ai/group_template");
|
||||
addSkillSeeId(DIVINITY_CLAN);
|
||||
addAttackId(KNIGHT, CAPTAIN, GUIDE, SEEKER, ASCETIC);
|
||||
addNpcHateId(GUIDE, SEEKER, SAVIOR, ASCETIC);
|
||||
addAggroRangeEnterId(GUIDE, SEEKER, SAVIOR, ASCETIC);
|
||||
addSpawnId(SCARECROW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "TRAINING":
|
||||
{
|
||||
for (L2Character character : npc.getKnownList().getKnownCharactersInRadius(400))
|
||||
{
|
||||
if ((getRandom(100) < 30) && character.isNpc() && !character.isDead() && !character.isInCombat())
|
||||
{
|
||||
if ((character.getId() == CAPTAIN) && (getRandom(100) < 10) && npc.isScriptValue(0))
|
||||
{
|
||||
final L2Npc captain = (L2Npc) character;
|
||||
broadcastNpcSay(captain, ChatType.NPC_GENERAL, SOLINA_KNIGHTS_MSG[getRandom(SOLINA_KNIGHTS_MSG.length)]);
|
||||
captain.setScriptValue(1);
|
||||
startQuestTimer("TIMER", 10000, captain, null);
|
||||
}
|
||||
else if (character.getId() == KNIGHT)
|
||||
{
|
||||
character.setRunning();
|
||||
((L2Attackable) character).addDamageHate(npc, 0, 100);
|
||||
character.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, npc, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "DO_CAST":
|
||||
{
|
||||
if ((npc != null) && (player != null) && (getRandom(100) < 3))
|
||||
{
|
||||
if (npc.checkDoCastConditions(STUDENT_CANCEL.getSkill()))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(STUDENT_CANCEL.getSkill());
|
||||
}
|
||||
npc.setScriptValue(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "TIMER":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
npc.setScriptValue(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon)
|
||||
{
|
||||
final L2Attackable mob = (L2Attackable) npc;
|
||||
|
||||
switch (npc.getId())
|
||||
{
|
||||
case KNIGHT:
|
||||
{
|
||||
if ((getRandom(100) < 10) && (mob.getMostHated() == player) && mob.checkDoCastConditions(WARRIOR_THRUSTING.getSkill()))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(WARRIOR_THRUSTING.getSkill());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CAPTAIN:
|
||||
{
|
||||
if ((getRandom(100) < 20) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.5)) && npc.isScriptValue(0))
|
||||
{
|
||||
if (npc.checkDoCastConditions(KNIGHT_BLESS.getSkill()))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(KNIGHT_BLESS.getSkill());
|
||||
}
|
||||
npc.setScriptValue(1);
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.FOR_THE_GLORY_OF_SOLINA);
|
||||
addAttackPlayerDesire(addSpawn(KNIGHT, npc), player);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GUIDE:
|
||||
{
|
||||
if ((getRandom(100) < 3) && (mob.getMostHated() == player) && npc.checkDoCastConditions(ORDEAL_STRIKE.getSkill()))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(ORDEAL_STRIKE.getSkill());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SEEKER:
|
||||
{
|
||||
if ((getRandom(100) < 33) && (mob.getMostHated() == player) && npc.checkDoCastConditions(SAVER_STRIKE.getSkill()))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(SAVER_STRIKE.getSkill());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ASCETIC:
|
||||
{
|
||||
if ((mob.getMostHated() == player) && npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
startQuestTimer("DO_CAST", 20000, npc, player);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, player, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onNpcHate(L2Attackable mob, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
return player.getActiveWeaponInstance() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
if (player.getActiveWeaponInstance() != null)
|
||||
{
|
||||
SkillHolder skill = null;
|
||||
switch (npc.getId())
|
||||
{
|
||||
case GUIDE:
|
||||
{
|
||||
if (getRandom(100) < 3)
|
||||
{
|
||||
skill = LEADER_STRIKE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SEEKER:
|
||||
{
|
||||
skill = SAVER_BLEED;
|
||||
break;
|
||||
}
|
||||
case SAVIOR:
|
||||
{
|
||||
skill = LEARNING_MAGIC;
|
||||
break;
|
||||
}
|
||||
case ASCETIC:
|
||||
{
|
||||
if (getRandom(100) < 3)
|
||||
{
|
||||
skill = STUDENT_CANCEL;
|
||||
}
|
||||
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
startQuestTimer("DO_CAST", 20000, npc, player);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((skill != null) && npc.checkDoCastConditions(skill.getSkill()))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(skill.getSkill());
|
||||
}
|
||||
|
||||
if (!npc.isInCombat())
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.YOU_CANNOT_CARRY_A_WEAPON_WITHOUT_AUTHORIZATION);
|
||||
}
|
||||
|
||||
addAttackPlayerDesire(npc, player);
|
||||
}
|
||||
return super.onAggroRangeEnter(npc, player, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
|
||||
{
|
||||
if (skill.hasEffectType(L2EffectType.AGGRESSION) && (targets.length != 0))
|
||||
{
|
||||
for (L2Object obj : targets)
|
||||
{
|
||||
if (obj.equals(npc))
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, DIVINITY_MSG[getRandom(DIVINITY_MSG.length)], caster.getName());
|
||||
addAttackPlayerDesire(npc, caster);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
npc.setIsInvul(true);
|
||||
npc.disableCoreAI(true);
|
||||
startQuestTimer("TRAINING", 30000, npc, null, true);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new MonasteryOfSilence();
|
||||
}
|
||||
}
|
52
trunk/dist/game/data_classic/scripts/ai/group_template/NonLethalableNpcs.java
vendored
Normal file
52
trunk/dist/game/data_classic/scripts/ai/group_template/NonLethalableNpcs.java
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
|
||||
/**
|
||||
* @author UnAfraid
|
||||
*/
|
||||
public final class NonLethalableNpcs extends AbstractNpcAI
|
||||
{
|
||||
private static final int[] NPCS =
|
||||
{
|
||||
35062, // Headquarters
|
||||
};
|
||||
|
||||
public NonLethalableNpcs()
|
||||
{
|
||||
super(NonLethalableNpcs.class.getSimpleName(), "ai/group_template");
|
||||
addSpawnId(NPCS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
npc.setLethalable(false);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new NonLethalableNpcs();
|
||||
}
|
||||
}
|
51
trunk/dist/game/data_classic/scripts/ai/group_template/PaganTemple.java
vendored
Normal file
51
trunk/dist/game/data_classic/scripts/ai/group_template/PaganTemple.java
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
|
||||
/**
|
||||
* Pagan Temple AI.
|
||||
* @author Mobius
|
||||
*/
|
||||
public class PaganTemple extends AbstractNpcAI
|
||||
{
|
||||
// Npc
|
||||
private static final int CHAPEL_GATEKEEPER = 22138;
|
||||
|
||||
public PaganTemple()
|
||||
{
|
||||
super(PaganTemple.class.getSimpleName(), "ai/group_template");
|
||||
addSpawnId(CHAPEL_GATEKEEPER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
npc.setIsNoRndWalk(true);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PaganTemple();
|
||||
}
|
||||
}
|
62
trunk/dist/game/data_classic/scripts/ai/group_template/PavelArchaic.java
vendored
Normal file
62
trunk/dist/game/data_classic/scripts/ai/group_template/PavelArchaic.java
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
/**
|
||||
* Pavel Archaic AI.
|
||||
* @author Gnacik, St3eT
|
||||
*/
|
||||
public final class PavelArchaic extends AbstractNpcAI
|
||||
{
|
||||
private static final int SAFETY_DEVICE = 18917; // Pavel Safety Device
|
||||
private static final int PINCER_GOLEM = 22801; // Cruel Pincer Golem
|
||||
private static final int PINCER_GOLEM2 = 22802; // Cruel Pincer Golem
|
||||
private static final int PINCER_GOLEM3 = 22803; // Cruel Pincer Golem
|
||||
private static final int JACKHAMMER_GOLEM = 22804; // Horrifying Jackhammer Golem
|
||||
|
||||
private PavelArchaic()
|
||||
{
|
||||
super(PavelArchaic.class.getSimpleName(), "ai/group_template");
|
||||
addKillId(SAFETY_DEVICE, PINCER_GOLEM, JACKHAMMER_GOLEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (getRandom(100) < 70)
|
||||
{
|
||||
final L2Npc golem1 = addSpawn(PINCER_GOLEM2, npc.getX(), npc.getY(), npc.getZ() + 10, npc.getHeading(), false, 0, false);
|
||||
addAttackPlayerDesire(golem1, killer);
|
||||
|
||||
final L2Npc golem2 = addSpawn(PINCER_GOLEM3, npc.getX(), npc.getY(), npc.getZ() + 10, npc.getHeading(), false, 0, false);
|
||||
addAttackPlayerDesire(golem2, killer);
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PavelArchaic();
|
||||
}
|
||||
}
|
99
trunk/dist/game/data_classic/scripts/ai/group_template/PlainsOfDion.java
vendored
Normal file
99
trunk/dist/game/data_classic/scripts/ai/group_template/PlainsOfDion.java
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.GeoData;
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.actor.L2Character;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
import com.l2jserver.gameserver.util.Util;
|
||||
|
||||
/**
|
||||
* AI for mobs in Plains of Dion (near Floran Village).
|
||||
* @author Gladicek
|
||||
*/
|
||||
public final class PlainsOfDion extends AbstractNpcAI
|
||||
{
|
||||
private static final int DELU_LIZARDMEN[] =
|
||||
{
|
||||
21104, // Delu Lizardman Supplier
|
||||
21105, // Delu Lizardman Special Agent
|
||||
21107, // Delu Lizardman Commander
|
||||
};
|
||||
|
||||
private static final NpcStringId[] MONSTERS_MSG =
|
||||
{
|
||||
NpcStringId.S1_HOW_DARE_YOU_INTERRUPT_OUR_FIGHT_HEY_GUYS_HELP,
|
||||
NpcStringId.S1_HEY_WE_RE_HAVING_A_DUEL_HERE,
|
||||
NpcStringId.THE_DUEL_IS_OVER_ATTACK,
|
||||
NpcStringId.FOUL_KILL_THE_COWARD,
|
||||
NpcStringId.HOW_DARE_YOU_INTERRUPT_A_SACRED_DUEL_YOU_MUST_BE_TAUGHT_A_LESSON
|
||||
};
|
||||
|
||||
private static final NpcStringId[] MONSTERS_ASSIST_MSG =
|
||||
{
|
||||
NpcStringId.DIE_YOU_COWARD,
|
||||
NpcStringId.KILL_THE_COWARD,
|
||||
NpcStringId.WHAT_ARE_YOU_LOOKING_AT
|
||||
};
|
||||
|
||||
private PlainsOfDion()
|
||||
{
|
||||
super(PlainsOfDion.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(DELU_LIZARDMEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
final int i = getRandom(5);
|
||||
if (i < 2)
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, MONSTERS_MSG[i], player.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, MONSTERS_MSG[i]);
|
||||
}
|
||||
|
||||
for (L2Character obj : npc.getKnownList().getKnownCharactersInRadius(npc.getTemplate().getClanHelpRange()))
|
||||
{
|
||||
if (obj.isMonster() && Util.contains(DELU_LIZARDMEN, obj.getId()) && !obj.isAttackingNow() && !obj.isDead() && GeoData.getInstance().canSeeTarget(npc, obj))
|
||||
{
|
||||
final L2Npc monster = (L2Npc) obj;
|
||||
addAttackPlayerDesire(monster, player);
|
||||
broadcastNpcSay(monster, ChatType.NPC_GENERAL, MONSTERS_ASSIST_MSG[getRandom(3)]);
|
||||
}
|
||||
}
|
||||
npc.setScriptValue(1);
|
||||
}
|
||||
return super.onAttack(npc, player, damage, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PlainsOfDion();
|
||||
}
|
||||
}
|
244
trunk/dist/game/data_classic/scripts/ai/group_template/PlainsOfLizardman.java
vendored
Normal file
244
trunk/dist/game/data_classic/scripts/ai/group_template/PlainsOfLizardman.java
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.ai.CtrlIntention;
|
||||
import com.l2jserver.gameserver.model.Location;
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Character;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.L2Playable;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.SkillHolder;
|
||||
|
||||
/**
|
||||
* Plains of Lizardmen AI.
|
||||
* @author Gnacik, malyelfik
|
||||
*/
|
||||
public final class PlainsOfLizardman extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int INVISIBLE_NPC = 18919;
|
||||
private static final int TANTA_GUARD = 18862;
|
||||
private static final int FANTASY_MUSHROOM = 18864;
|
||||
private static final int STICKY_MUSHROOM = 18865;
|
||||
private static final int RAINBOW_FROG = 18866;
|
||||
private static final int ENERGY_PLANT = 18868;
|
||||
private static final int TANTA_SCOUT = 22768;
|
||||
private static final int TANTA_MAGICIAN = 22773;
|
||||
private static final int TANTA_SUMMONER = 22774;
|
||||
private static final int[] TANTA_LIZARDMEN =
|
||||
{
|
||||
22768, // Tanta Lizardman Scout
|
||||
22769, // Tanta Lizardman Warrior
|
||||
22770, // Tanta Lizardman Soldier
|
||||
22771, // Tanta Lizardman Berserker
|
||||
22772, // Tanta Lizardman Archer
|
||||
22773, // Tanta Lizardman Magician
|
||||
22774, // Tanta Lizardman Summoner
|
||||
};
|
||||
// Skills
|
||||
private static final SkillHolder STUN_EFFECT = new SkillHolder(6622, 1);
|
||||
private static final SkillHolder DEMOTIVATION_HEX = new SkillHolder(6425, 1);
|
||||
private static final SkillHolder FANTASY_MUSHROOM_SKILL = new SkillHolder(6427, 1);
|
||||
private static final SkillHolder RAINBOW_FROG_SKILL = new SkillHolder(6429, 1);
|
||||
private static final SkillHolder STICKY_MUSHROOM_SKILL = new SkillHolder(6428, 1);
|
||||
private static final SkillHolder ENERGY_PLANT_SKILL = new SkillHolder(6430, 1);
|
||||
// Buffs
|
||||
private static final SkillHolder[] BUFFS =
|
||||
{
|
||||
new SkillHolder(6625, 1), // Energy of Life
|
||||
new SkillHolder(6626, 2), // Energy of Life's Power
|
||||
new SkillHolder(6627, 3), // Energy of Life's Highest Power
|
||||
new SkillHolder(6628, 1), // Energy of Mana
|
||||
new SkillHolder(6629, 2), // Energy of Mana's Power
|
||||
new SkillHolder(6630, 3), // Energy of Mana's Highest Power
|
||||
new SkillHolder(6631, 1), // Energy of Power
|
||||
new SkillHolder(6633, 1), // Energy of Attack Speed
|
||||
new SkillHolder(6635, 1), // Energy of Crt Rate
|
||||
new SkillHolder(6636, 1), // Energy of Moving Speed
|
||||
new SkillHolder(6638, 1), // Aura of Mystery
|
||||
new SkillHolder(6639, 1), // Bane of Auras - Damage
|
||||
new SkillHolder(6640, 1), // Energizing Aura
|
||||
new SkillHolder(6674, 1), // Energy of Range Increment
|
||||
};
|
||||
// Misc
|
||||
// @formatter:off
|
||||
private static final int[] BUFF_LIST =
|
||||
{
|
||||
6, 7, 8, 11, 13
|
||||
};
|
||||
// @formatter:on
|
||||
|
||||
private PlainsOfLizardman()
|
||||
{
|
||||
super(PlainsOfLizardman.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(FANTASY_MUSHROOM, RAINBOW_FROG, STICKY_MUSHROOM, ENERGY_PLANT, TANTA_SUMMONER);
|
||||
addKillId(TANTA_LIZARDMEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equals("fantasy_mushroom") && (npc != null) && (player != null))
|
||||
{
|
||||
npc.doCast(FANTASY_MUSHROOM_SKILL.getSkill());
|
||||
for (L2Character target : npc.getKnownList().getKnownCharactersInRadius(200))
|
||||
{
|
||||
if ((target != null) && target.isAttackable())
|
||||
{
|
||||
final L2Npc monster = (L2Npc) target;
|
||||
npc.setTarget(monster);
|
||||
npc.doCast(STUN_EFFECT.getSkill());
|
||||
addAttackPlayerDesire(monster, player);
|
||||
}
|
||||
}
|
||||
npc.doDie(player);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
switch (npc.getId())
|
||||
{
|
||||
case TANTA_SUMMONER:
|
||||
if (!npc.isAffectedBySkill(DEMOTIVATION_HEX.getSkillId()))
|
||||
{
|
||||
npc.doCast(DEMOTIVATION_HEX.getSkill());
|
||||
}
|
||||
break;
|
||||
case RAINBOW_FROG:
|
||||
castSkill(npc, attacker, RAINBOW_FROG_SKILL);
|
||||
break;
|
||||
case ENERGY_PLANT:
|
||||
castSkill(npc, attacker, ENERGY_PLANT_SKILL);
|
||||
break;
|
||||
case STICKY_MUSHROOM:
|
||||
castSkill(npc, attacker, STICKY_MUSHROOM_SKILL);
|
||||
break;
|
||||
case FANTASY_MUSHROOM:
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
npc.setIsInvul(true);
|
||||
for (L2Character target : npc.getKnownList().getKnownCharactersInRadius(1000))
|
||||
{
|
||||
if ((target != null) && target.isAttackable())
|
||||
{
|
||||
final L2Attackable monster = (L2Attackable) target;
|
||||
if ((monster.getId() == TANTA_MAGICIAN) || (monster.getId() == TANTA_SCOUT))
|
||||
{
|
||||
target.setIsRunning(true);
|
||||
target.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(npc.getX(), npc.getY(), npc.getZ(), 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
startQuestTimer("fantasy_mushroom", 4000, npc, attacker);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
// Tanta Guard
|
||||
if (getRandom(1000) == 0)
|
||||
{
|
||||
addAttackPlayerDesire(addSpawn(TANTA_GUARD, npc), killer);
|
||||
}
|
||||
|
||||
// Invisible buff npc
|
||||
final int random = getRandom(100);
|
||||
final L2Npc buffer = addSpawn(INVISIBLE_NPC, npc.getLocation(), false, 6000);
|
||||
buffer.setTarget(killer);
|
||||
|
||||
if (random <= 42)
|
||||
{
|
||||
castRandomBuff(buffer, 7, 45, BUFFS[0], BUFFS[1], BUFFS[2]);
|
||||
}
|
||||
if (random <= 11)
|
||||
{
|
||||
castRandomBuff(buffer, 8, 60, BUFFS[3], BUFFS[4], BUFFS[5]);
|
||||
castRandomBuff(buffer, 3, 6, BUFFS[9], BUFFS[10], BUFFS[12]);
|
||||
}
|
||||
if (random <= 25)
|
||||
{
|
||||
buffer.doCast(BUFFS[BUFF_LIST[getRandom(BUFF_LIST.length)]].getSkill());
|
||||
}
|
||||
if (random <= 10)
|
||||
{
|
||||
buffer.doCast(BUFFS[13].getSkill());
|
||||
}
|
||||
if (random <= 1)
|
||||
{
|
||||
final int i = getRandom(100);
|
||||
if (i <= 34)
|
||||
{
|
||||
buffer.doCast(BUFFS[6].getSkill());
|
||||
buffer.doCast(BUFFS[7].getSkill());
|
||||
buffer.doCast(BUFFS[8].getSkill());
|
||||
}
|
||||
else if (i < 67)
|
||||
{
|
||||
buffer.doCast(BUFFS[13].getSkill());
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.doCast(BUFFS[2].getSkill());
|
||||
buffer.doCast(BUFFS[5].getSkill());
|
||||
}
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
private void castRandomBuff(L2Npc npc, int chance1, int chance2, SkillHolder... buffs)
|
||||
{
|
||||
final int rand = getRandom(100);
|
||||
if (rand <= chance1)
|
||||
{
|
||||
npc.doCast(buffs[2].getSkill());
|
||||
}
|
||||
else if (rand <= chance2)
|
||||
{
|
||||
npc.doCast(buffs[1].getSkill());
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.doCast(buffs[0].getSkill());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void castSkill(L2Npc npc, L2Playable target, SkillHolder skill)
|
||||
{
|
||||
npc.doDie(target);
|
||||
super.castSkill(addSpawn(INVISIBLE_NPC, npc, false, 6000), target, skill);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PlainsOfLizardman();
|
||||
}
|
||||
}
|
63
trunk/dist/game/data_classic/scripts/ai/group_template/PolymorphingAngel.java
vendored
Normal file
63
trunk/dist/game/data_classic/scripts/ai/group_template/PolymorphingAngel.java
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
/**
|
||||
* Angel spawns...when one of the angels in the keys dies, the other angel will spawn.
|
||||
*/
|
||||
public final class PolymorphingAngel extends AbstractNpcAI
|
||||
{
|
||||
private static final Map<Integer, Integer> ANGELSPAWNS = new HashMap<>();
|
||||
static
|
||||
{
|
||||
ANGELSPAWNS.put(20830, 20859);
|
||||
ANGELSPAWNS.put(21067, 21068);
|
||||
ANGELSPAWNS.put(21062, 21063);
|
||||
ANGELSPAWNS.put(20831, 20860);
|
||||
ANGELSPAWNS.put(21070, 21071);
|
||||
}
|
||||
|
||||
private PolymorphingAngel()
|
||||
{
|
||||
super(PolymorphingAngel.class.getSimpleName(), "ai/group_template");
|
||||
addKillId(ANGELSPAWNS.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
final L2Attackable newNpc = (L2Attackable) addSpawn(ANGELSPAWNS.get(npc.getId()), npc);
|
||||
newNpc.setRunning();
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PolymorphingAngel();
|
||||
}
|
||||
}
|
120
trunk/dist/game/data_classic/scripts/ai/group_template/PolymorphingOnAttack.java
vendored
Normal file
120
trunk/dist/game/data_classic/scripts/ai/group_template/PolymorphingOnAttack.java
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.ai.CtrlIntention;
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Character;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
import com.l2jserver.gameserver.network.serverpackets.CreatureSay;
|
||||
|
||||
/**
|
||||
* Polymorphing on attack monsters AI.
|
||||
* @author Slyce
|
||||
*/
|
||||
public final class PolymorphingOnAttack extends AbstractNpcAI
|
||||
{
|
||||
private static final Map<Integer, List<Integer>> MOBSPAWNS = new HashMap<>();
|
||||
static
|
||||
{
|
||||
MOBSPAWNS.put(21258, Arrays.asList(21259, 100, 100, -1)); // Fallen Orc Shaman -> Sharp Talon Tiger (always polymorphs)
|
||||
MOBSPAWNS.put(21261, Arrays.asList(21262, 100, 20, 0)); // Ol Mahum Transcender 1st stage
|
||||
MOBSPAWNS.put(21262, Arrays.asList(21263, 100, 10, 1)); // Ol Mahum Transcender 2nd stage
|
||||
MOBSPAWNS.put(21263, Arrays.asList(21264, 100, 5, 2)); // Ol Mahum Transcender 3rd stage
|
||||
MOBSPAWNS.put(21265, Arrays.asList(21271, 100, 33, 0)); // Cave Ant Larva -> Cave Ant
|
||||
MOBSPAWNS.put(21266, Arrays.asList(21269, 100, 100, -1)); // Cave Ant Larva -> Cave Ant (always polymorphs)
|
||||
MOBSPAWNS.put(21267, Arrays.asList(21270, 100, 100, -1)); // Cave Ant Larva -> Cave Ant Soldier (always polymorphs)
|
||||
MOBSPAWNS.put(21271, Arrays.asList(21272, 66, 10, 1)); // Cave Ant -> Cave Ant Soldier
|
||||
MOBSPAWNS.put(21272, Arrays.asList(21273, 33, 5, 2)); // Cave Ant Soldier -> Cave Noble Ant
|
||||
MOBSPAWNS.put(21521, Arrays.asList(21522, 100, 30, -1)); // Claws of Splendor
|
||||
MOBSPAWNS.put(21527, Arrays.asList(21528, 100, 30, -1)); // Anger of Splendor
|
||||
MOBSPAWNS.put(21533, Arrays.asList(21534, 100, 30, -1)); // Alliance of Splendor
|
||||
MOBSPAWNS.put(21537, Arrays.asList(21538, 100, 30, -1)); // Fang of Splendor
|
||||
}
|
||||
protected static final NpcStringId[][] MOBTEXTS =
|
||||
{
|
||||
new NpcStringId[]
|
||||
{
|
||||
NpcStringId.ENOUGH_FOOLING_AROUND_GET_READY_TO_DIE,
|
||||
NpcStringId.YOU_IDIOT_I_VE_JUST_BEEN_TOYING_WITH_YOU,
|
||||
NpcStringId.NOW_THE_FUN_STARTS
|
||||
},
|
||||
new NpcStringId[]
|
||||
{
|
||||
NpcStringId.I_MUST_ADMIT_NO_ONE_MAKES_MY_BLOOD_BOIL_QUITE_LIKE_YOU_DO,
|
||||
NpcStringId.NOW_THE_BATTLE_BEGINS,
|
||||
NpcStringId.WITNESS_MY_TRUE_POWER
|
||||
},
|
||||
new NpcStringId[]
|
||||
{
|
||||
NpcStringId.PREPARE_TO_DIE,
|
||||
NpcStringId.I_LL_DOUBLE_MY_STRENGTH,
|
||||
NpcStringId.YOU_HAVE_MORE_SKILL_THAN_I_THOUGHT
|
||||
}
|
||||
};
|
||||
|
||||
private PolymorphingOnAttack()
|
||||
{
|
||||
super(PolymorphingOnAttack.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(MOBSPAWNS.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.isVisible() && !npc.isDead())
|
||||
{
|
||||
final List<Integer> tmp = MOBSPAWNS.get(npc.getId());
|
||||
if (tmp != null)
|
||||
{
|
||||
if ((npc.getCurrentHp() <= ((npc.getMaxHp() * tmp.get(1)) / 100.0)) && (getRandom(100) < tmp.get(2)))
|
||||
{
|
||||
if (tmp.get(3) >= 0)
|
||||
{
|
||||
NpcStringId npcString = MOBTEXTS[tmp.get(3)][getRandom(MOBTEXTS[tmp.get(3)].length)];
|
||||
npc.broadcastPacket(new CreatureSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getName(), npcString));
|
||||
|
||||
}
|
||||
npc.deleteMe();
|
||||
final L2Attackable newNpc = (L2Attackable) addSpawn(tmp.get(0), npc.getX(), npc.getY(), npc.getZ() + 10, npc.getHeading(), false, 0, true);
|
||||
final L2Character originalAttacker = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : attacker;
|
||||
newNpc.setRunning();
|
||||
newNpc.addDamageHate(originalAttacker, 0, 500);
|
||||
newNpc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, originalAttacker);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PolymorphingOnAttack();
|
||||
}
|
||||
}
|
161
trunk/dist/game/data_classic/scripts/ai/group_template/PrisonGuards.java
vendored
Normal file
161
trunk/dist/game/data_classic/scripts/ai/group_template/PrisonGuards.java
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.L2Object;
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
|
||||
/**
|
||||
* Prison Guards AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
public final class PrisonGuards extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int GUARD_HEAD = 18367; // Prison Guard
|
||||
private static final int GUARD = 18368; // Prison Guard
|
||||
// Item
|
||||
private static final int STAMP = 10013; // Race Stamp
|
||||
// Skills
|
||||
private static final int TIMER = 5239; // Event Timer
|
||||
private static final SkillHolder STONE = new SkillHolder(4578, 1); // Petrification
|
||||
private static final SkillHolder SILENCE = new SkillHolder(4098, 9); // Silence
|
||||
|
||||
private PrisonGuards()
|
||||
{
|
||||
super(PrisonGuards.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(GUARD_HEAD, GUARD);
|
||||
addSpawnId(GUARD_HEAD, GUARD);
|
||||
addNpcHateId(GUARD);
|
||||
addSkillSeeId(GUARD);
|
||||
addSpellFinishedId(GUARD_HEAD, GUARD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equals("CLEAR_STATUS"))
|
||||
{
|
||||
npc.setScriptValue(0);
|
||||
}
|
||||
else if (event.equals("CHECK_HOME"))
|
||||
{
|
||||
if ((npc.calculateDistance(npc.getSpawn().getLocation(), false, false) > 10) && !npc.isInCombat() && !npc.isDead())
|
||||
{
|
||||
npc.teleToLocation(npc.getSpawn().getLocation());
|
||||
}
|
||||
startQuestTimer("CHECK_HOME", 30000, npc, null);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.getId() == GUARD_HEAD)
|
||||
{
|
||||
if (player.isAffectedBySkill(TIMER))
|
||||
{
|
||||
if ((getRandom(100) < 10) && (npc.calculateDistance(player, true, false) < 100))
|
||||
{
|
||||
if ((getQuestItemsCount(player, STAMP) <= 3) && npc.isScriptValue(0))
|
||||
{
|
||||
giveItems(player, STAMP, 1);
|
||||
npc.setScriptValue(1);
|
||||
startQuestTimer("CLEAR_STATUS", 600000, npc, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(STONE.getSkill());
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.IT_S_NOT_EASY_TO_OBTAIN);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!player.isAffectedBySkill(TIMER) && (npc.calculateDistance(npc.getSpawn().getLocation(), false, false) < 2000))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(STONE.getSkill());
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.YOU_RE_OUT_OF_YOUR_MIND_COMING_HERE);
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, player, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
|
||||
{
|
||||
if (!caster.isAffectedBySkill(TIMER))
|
||||
{
|
||||
npc.setTarget(caster);
|
||||
npc.doCast(SILENCE.getSkill());
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
|
||||
{
|
||||
if ((skill == SILENCE.getSkill()) || (skill == STONE.getSkill()))
|
||||
{
|
||||
((L2Attackable) npc).clearAggroList();
|
||||
npc.setTarget(npc);
|
||||
}
|
||||
return super.onSpellFinished(npc, player, skill);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onNpcHate(L2Attackable mob, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
return player.isAffectedBySkill(TIMER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
if (npc.getId() == GUARD_HEAD)
|
||||
{
|
||||
npc.setIsImmobilized(true);
|
||||
npc.setIsInvul(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.setIsNoRndWalk(true);
|
||||
cancelQuestTimer("CHECK_HOME", npc, null);
|
||||
startQuestTimer("CHECK_HOME", 30000, npc, null);
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PrisonGuards();
|
||||
}
|
||||
}
|
123
trunk/dist/game/data_classic/scripts/ai/group_template/RandomSpawn.java
vendored
Normal file
123
trunk/dist/game/data_classic/scripts/ai/group_template/RandomSpawn.java
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.ThreadPoolManager;
|
||||
import com.l2jserver.gameserver.model.Location;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
|
||||
/**
|
||||
* Manages spawn of NPCs having several random spawn points.
|
||||
* @author GKR
|
||||
*/
|
||||
public final class RandomSpawn extends AbstractNpcAI
|
||||
{
|
||||
private static final Map<Integer, Location[]> SPAWN_POINTS = new HashMap<>();
|
||||
static
|
||||
{
|
||||
// Keltas
|
||||
SPAWN_POINTS.put(22341, new Location[]
|
||||
{
|
||||
new Location(-27136, 250938, -3523),
|
||||
new Location(-29658, 252897, -3523),
|
||||
new Location(-27237, 251943, -3527),
|
||||
new Location(-28868, 250113, -3479)
|
||||
});
|
||||
// Keymaster
|
||||
SPAWN_POINTS.put(22361, new Location[]
|
||||
{
|
||||
new Location(14091, 250533, -1940),
|
||||
new Location(15762, 252440, -2015),
|
||||
new Location(19836, 256212, -2090),
|
||||
new Location(21940, 254107, -2010),
|
||||
new Location(17299, 252943, -2015),
|
||||
});
|
||||
// Typhoon
|
||||
SPAWN_POINTS.put(25539, new Location[]
|
||||
{
|
||||
new Location(-20641, 255370, -3235),
|
||||
new Location(-16157, 250993, -3058),
|
||||
new Location(-18269, 250721, -3151),
|
||||
new Location(-16532, 254864, -3223),
|
||||
new Location(-19055, 253489, -3440),
|
||||
new Location(-9684, 254256, -3148),
|
||||
new Location(-6209, 251924, -3189),
|
||||
new Location(-10547, 251359, -2929),
|
||||
new Location(-7254, 254997, -3261),
|
||||
new Location(-4883, 253171, -3322)
|
||||
});
|
||||
// Mutated Elpy
|
||||
SPAWN_POINTS.put(25604, new Location[]
|
||||
{
|
||||
new Location(-46080, 246368, -14183),
|
||||
new Location(-44816, 246368, -14183),
|
||||
new Location(-44224, 247440, -14184),
|
||||
new Location(-44896, 248464, -14183),
|
||||
new Location(-46064, 248544, -14183),
|
||||
new Location(-46720, 247424, -14183)
|
||||
});
|
||||
}
|
||||
|
||||
public RandomSpawn()
|
||||
{
|
||||
super(RandomSpawn.class.getSimpleName(), "ai/group_template");
|
||||
addSpawnId(SPAWN_POINTS.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String onSpawn(L2Npc npc)
|
||||
{
|
||||
final Location[] spawnlist = SPAWN_POINTS.get(npc.getId());
|
||||
final Location loc = spawnlist[getRandom(spawnlist.length)];
|
||||
if (!npc.isInsideRadius(loc, 200, false, false))
|
||||
{
|
||||
npc.getSpawn().setLocation(loc);
|
||||
ThreadPoolManager.getInstance().scheduleGeneral(new Teleport(npc, loc), 100);
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
private static class Teleport implements Runnable
|
||||
{
|
||||
private final L2Npc _npc;
|
||||
private final Location _loc;
|
||||
|
||||
public Teleport(L2Npc npc, Location loc)
|
||||
{
|
||||
_npc = npc;
|
||||
_loc = loc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
_npc.teleToLocation(_loc, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new RandomSpawn();
|
||||
}
|
||||
}
|
63
trunk/dist/game/data_classic/scripts/ai/group_template/SeeThroughSilentMove.java
vendored
Normal file
63
trunk/dist/game/data_classic/scripts/ai/group_template/SeeThroughSilentMove.java
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
|
||||
/**
|
||||
* See Through Silent Move AI.
|
||||
* @author Gigiikun
|
||||
*/
|
||||
public class SeeThroughSilentMove extends AbstractNpcAI
|
||||
{
|
||||
//@formatter:off
|
||||
private static final int[] MONSTERS =
|
||||
{
|
||||
18001, 18002, 22199, 22215, 22216, 22217, 22327, 22746, 22747, 22748,
|
||||
22749, 22750, 22751, 22752, 22753, 22754, 22755, 22756, 22757, 22758,
|
||||
22759, 22760, 22761, 22762, 22763, 22764, 22765, 22794, 22795, 22796,
|
||||
22797, 22798, 22799, 22800, 22843, 22857, 25725, 25726, 25727, 29009,
|
||||
29010, 29011, 29012, 29013
|
||||
};
|
||||
//@formatter:on
|
||||
|
||||
private SeeThroughSilentMove()
|
||||
{
|
||||
super(SeeThroughSilentMove.class.getSimpleName(), "ai/group_template");
|
||||
addSpawnId(MONSTERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
if (npc.isAttackable())
|
||||
{
|
||||
((L2Attackable) npc).setSeeThroughSilentMove(true);
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new SeeThroughSilentMove();
|
||||
}
|
||||
}
|
210
trunk/dist/game/data_classic/scripts/ai/group_template/SilentValley.java
vendored
Normal file
210
trunk/dist/game/data_classic/scripts/ai/group_template/SilentValley.java
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.L2Object;
|
||||
import com.l2jserver.gameserver.model.actor.L2Character;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.L2Summon;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
|
||||
/**
|
||||
* Silent Valley AI
|
||||
* @author malyelfik
|
||||
*/
|
||||
public final class SilentValley extends AbstractNpcAI
|
||||
{
|
||||
// Skills
|
||||
private static final SkillHolder BETRAYAL = new SkillHolder(6033, 1); // Treasure Seeker's Betrayal
|
||||
private static final SkillHolder BLAZE = new SkillHolder(4157, 10); // NPC Blaze - Magic
|
||||
// Item
|
||||
private static final int SACK = 13799; // Treasure Sack of the Ancient Giants
|
||||
// Chance
|
||||
private static final int SPAWN_CHANCE = 2;
|
||||
private static final int CHEST_DIE_CHANCE = 5;
|
||||
// Monsters
|
||||
private static final int CHEST = 18693; // Treasure Chest of the Ancient Giants
|
||||
private static final int GUARD1 = 18694; // Treasure Chest Guard
|
||||
private static final int GUARD2 = 18695; // Treasure Chest Guard
|
||||
private static final int[] MOBS =
|
||||
{
|
||||
20965, // Chimera Piece
|
||||
20966, // Changed Creation
|
||||
20967, // Past Creature
|
||||
20968, // Nonexistent Man
|
||||
20969, // Giant's Shadow
|
||||
20970, // Soldier of Ancient Times
|
||||
20971, // Warrior of Ancient Times
|
||||
20972, // Shaman of Ancient Times
|
||||
20973, // Forgotten Ancient People
|
||||
};
|
||||
|
||||
private SilentValley()
|
||||
{
|
||||
super(SilentValley.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(MOBS);
|
||||
addAttackId(CHEST, GUARD1, GUARD2);
|
||||
addEventReceivedId(GUARD1, GUARD2);
|
||||
addKillId(MOBS);
|
||||
addSeeCreatureId(MOBS);
|
||||
addSeeCreatureId(GUARD1, GUARD2);
|
||||
addSpawnId(CHEST, GUARD2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if ((npc != null) && !npc.isDead())
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "CLEAR":
|
||||
npc.doDie(null);
|
||||
break;
|
||||
case "CLEAR_EVENT":
|
||||
npc.broadcastEvent("CLEAR_ALL_INSTANT", 2000, null);
|
||||
npc.doDie(null);
|
||||
break;
|
||||
case "SPAWN_CHEST":
|
||||
addSpawn(CHEST, npc.getX() - 100, npc.getY(), npc.getZ() - 100, 0, false, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon)
|
||||
{
|
||||
switch (npc.getId())
|
||||
{
|
||||
case CHEST:
|
||||
{
|
||||
if (!isSummon && npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.YOU_WILL_BE_CURSED_FOR_SEEKING_THE_TREASURE);
|
||||
npc.setTarget(player);
|
||||
npc.doCast(BETRAYAL.getSkill());
|
||||
}
|
||||
else if (isSummon || (getRandom(100) < CHEST_DIE_CHANCE))
|
||||
{
|
||||
npc.dropItem(player, SACK, 1);
|
||||
npc.broadcastEvent("CLEAR_ALL", 2000, null);
|
||||
npc.doDie(null);
|
||||
cancelQuestTimer("CLEAR_EVENT", npc, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GUARD1:
|
||||
case GUARD2:
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(BLAZE.getSkill());
|
||||
addAttackPlayerDesire(npc, player);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (isSummon)
|
||||
{
|
||||
addAttackPlayerDesire(npc, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, player, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (getRandom(1000) < SPAWN_CHANCE)
|
||||
{
|
||||
final int newZ = npc.getZ() + 100;
|
||||
addSpawn(GUARD2, npc.getX() + 100, npc.getY(), newZ, 0, false, 0);
|
||||
addSpawn(GUARD1, npc.getX() - 100, npc.getY(), newZ, 0, false, 0);
|
||||
addSpawn(GUARD1, npc.getX(), npc.getY() + 100, newZ, 0, false, 0);
|
||||
addSpawn(GUARD1, npc.getX(), npc.getY() - 100, newZ, 0, false, 0);
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSeeCreature(L2Npc npc, L2Character creature, boolean isSummon)
|
||||
{
|
||||
if (creature.isPlayable())
|
||||
{
|
||||
final L2PcInstance player = (isSummon) ? ((L2Summon) creature).getOwner() : creature.getActingPlayer();
|
||||
if ((npc.getId() == GUARD1) || (npc.getId() == GUARD2))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(BLAZE.getSkill());
|
||||
addAttackPlayerDesire(npc, player);
|
||||
}
|
||||
else if (creature.isAffectedBySkill(BETRAYAL.getSkillId()))
|
||||
{
|
||||
addAttackPlayerDesire(npc, player);
|
||||
}
|
||||
}
|
||||
return super.onSeeCreature(npc, creature, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
if (npc.getId() == CHEST)
|
||||
{
|
||||
npc.setIsInvul(true);
|
||||
startQuestTimer("CLEAR_EVENT", 300000, npc, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
startQuestTimer("SPAWN_CHEST", 10000, npc, null);
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onEventReceived(String eventName, L2Npc sender, L2Npc receiver, L2Object reference)
|
||||
{
|
||||
if ((receiver != null) && !receiver.isDead())
|
||||
{
|
||||
switch (eventName)
|
||||
{
|
||||
case "CLEAR_ALL":
|
||||
startQuestTimer("CLEAR", 60000, receiver, null);
|
||||
break;
|
||||
case "CLEAR_ALL_INSTANT":
|
||||
receiver.doDie(null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onEventReceived(eventName, sender, receiver, reference);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new SilentValley();
|
||||
}
|
||||
}
|
244
trunk/dist/game/data_classic/scripts/ai/group_template/StakatoNest.java
vendored
Normal file
244
trunk/dist/game/data_classic/scripts/ai/group_template/StakatoNest.java
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.datatables.SkillData;
|
||||
import com.l2jserver.gameserver.model.L2Object;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
|
||||
import com.l2jserver.gameserver.util.Broadcast;
|
||||
import com.l2jserver.gameserver.util.Util;
|
||||
|
||||
/**
|
||||
* Stakato Nest AI.
|
||||
* @author Gnacik
|
||||
*/
|
||||
public final class StakatoNest extends AbstractNpcAI
|
||||
{
|
||||
// @formatter:off
|
||||
// List of all mobs just for register
|
||||
private static final int[] STAKATO_MOBS =
|
||||
{
|
||||
18793, 18794, 18795, 18796, 18797, 18798, 22617, 22618, 22619, 22620,
|
||||
22621, 22622, 22623, 22624, 22625, 22626, 22627, 22628, 22629, 22630,
|
||||
22631, 22632, 22633, 25667
|
||||
};
|
||||
// Coocons
|
||||
private static final int[] COCOONS =
|
||||
{
|
||||
18793, 18794, 18795, 18796, 18797, 18798
|
||||
};
|
||||
// @formatter:on
|
||||
// Cannibalistic Stakato Leader
|
||||
private static final int STAKATO_LEADER = 22625;
|
||||
|
||||
// Spike Stakato Nurse
|
||||
private static final int STAKATO_NURSE = 22630;
|
||||
// Spike Stakato Nurse (Changed)
|
||||
private static final int STAKATO_NURSE_2 = 22631;
|
||||
// Spiked Stakato Baby
|
||||
private static final int STAKATO_BABY = 22632;
|
||||
// Spiked Stakato Captain
|
||||
private static final int STAKATO_CAPTAIN = 22629;
|
||||
|
||||
// Female Spiked Stakato
|
||||
private static final int STAKATO_FEMALE = 22620;
|
||||
// Male Spiked Stakato
|
||||
private static final int STAKATO_MALE = 22621;
|
||||
// Male Spiked Stakato (Changed)
|
||||
private static final int STAKATO_MALE_2 = 22622;
|
||||
// Spiked Stakato Guard
|
||||
private static final int STAKATO_GUARD = 22619;
|
||||
|
||||
// Cannibalistic Stakato Chief
|
||||
private static final int STAKATO_CHIEF = 25667;
|
||||
// Growth Accelerator
|
||||
private static final int GROWTH_ACCELERATOR = 2905;
|
||||
// Small Stakato Cocoon
|
||||
private static final int SMALL_COCOON = 14833;
|
||||
// Large Stakato Cocoon
|
||||
private static final int LARGE_COCOON = 14834;
|
||||
|
||||
private StakatoNest()
|
||||
{
|
||||
super(StakatoNest.class.getSimpleName(), "ai/group_template");
|
||||
registerMobs(STAKATO_MOBS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
final L2MonsterInstance mob = (L2MonsterInstance) npc;
|
||||
|
||||
if ((mob.getId() == STAKATO_LEADER) && (getRandom(1000) < 100) && (mob.getCurrentHp() < (mob.getMaxHp() * 0.3)))
|
||||
{
|
||||
final L2MonsterInstance _follower = checkMinion(npc);
|
||||
|
||||
if (_follower != null)
|
||||
{
|
||||
double _hp = _follower.getCurrentHp();
|
||||
|
||||
if (_hp > (_follower.getMaxHp() * 0.3))
|
||||
{
|
||||
mob.abortAttack();
|
||||
mob.abortCast();
|
||||
mob.setHeading(Util.calculateHeadingFrom(mob, _follower));
|
||||
mob.doCast(SkillData.getInstance().getSkill(4484, 1));
|
||||
mob.setCurrentHp(mob.getCurrentHp() + _hp);
|
||||
_follower.doDie(_follower);
|
||||
_follower.deleteMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
final L2MonsterInstance monster;
|
||||
switch (npc.getId())
|
||||
{
|
||||
case STAKATO_NURSE:
|
||||
monster = checkMinion(npc);
|
||||
if (monster != null)
|
||||
{
|
||||
Broadcast.toSelfAndKnownPlayers(npc, new MagicSkillUse(npc, 2046, 1, 1000, 0));
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
L2Npc spawned = addSpawn(STAKATO_CAPTAIN, monster, true);
|
||||
addAttackPlayerDesire(spawned, killer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STAKATO_BABY:
|
||||
monster = ((L2MonsterInstance) npc).getLeader();
|
||||
if ((monster != null) && !monster.isDead())
|
||||
{
|
||||
startQuestTimer("nurse_change", 5000, monster, killer);
|
||||
}
|
||||
break;
|
||||
case STAKATO_MALE:
|
||||
monster = checkMinion(npc);
|
||||
if (monster != null)
|
||||
{
|
||||
Broadcast.toSelfAndKnownPlayers(npc, new MagicSkillUse(npc, 2046, 1, 1000, 0));
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
L2Npc spawned = addSpawn(STAKATO_GUARD, monster, true);
|
||||
addAttackPlayerDesire(spawned, killer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STAKATO_FEMALE:
|
||||
monster = ((L2MonsterInstance) npc).getLeader();
|
||||
if ((monster != null) && !monster.isDead())
|
||||
{
|
||||
startQuestTimer("male_change", 5000, monster, killer);
|
||||
}
|
||||
break;
|
||||
case STAKATO_CHIEF:
|
||||
if (killer.isInParty())
|
||||
{
|
||||
List<L2PcInstance> party = killer.getParty().getMembers();
|
||||
for (L2PcInstance member : party)
|
||||
{
|
||||
giveCocoon(member, npc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
giveCocoon(killer, npc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
|
||||
{
|
||||
if (Util.contains(COCOONS, npc.getId()) && Util.contains(targets, npc) && (skill.getId() == GROWTH_ACCELERATOR))
|
||||
{
|
||||
npc.doDie(caster);
|
||||
final L2Npc spawned = addSpawn(STAKATO_CHIEF, npc.getX(), npc.getY(), npc.getZ(), Util.calculateHeadingFrom(npc, caster), false, 0, true);
|
||||
addAttackPlayerDesire(spawned, caster);
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if ((npc == null) || (player == null) || npc.isDead())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int npcId = 0;
|
||||
switch (event)
|
||||
{
|
||||
case "nurse_change":
|
||||
npcId = STAKATO_NURSE_2;
|
||||
break;
|
||||
case "male_change":
|
||||
npcId = STAKATO_MALE_2;
|
||||
break;
|
||||
}
|
||||
if (npcId > 0)
|
||||
{
|
||||
npc.getSpawn().decreaseCount(npc);
|
||||
npc.deleteMe();
|
||||
final L2Npc spawned = addSpawn(npcId, npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), false, 0, true);
|
||||
addAttackPlayerDesire(spawned, player);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
private static L2MonsterInstance checkMinion(L2Npc npc)
|
||||
{
|
||||
final L2MonsterInstance mob = (L2MonsterInstance) npc;
|
||||
if (mob.hasMinions())
|
||||
{
|
||||
final List<L2MonsterInstance> minion = mob.getMinionList().getSpawnedMinions();
|
||||
if ((minion != null) && !minion.isEmpty() && (minion.get(0) != null) && !minion.get(0).isDead())
|
||||
{
|
||||
return minion.get(0);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void giveCocoon(L2PcInstance player, L2Npc npc)
|
||||
{
|
||||
player.addItem("StakatoCocoon", ((getRandom(100) > 80) ? LARGE_COCOON : SMALL_COCOON), 1, npc, true);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new StakatoNest();
|
||||
}
|
||||
}
|
106
trunk/dist/game/data_classic/scripts/ai/group_template/SummonPc.java
vendored
Normal file
106
trunk/dist/game/data_classic/scripts/ai/group_template/SummonPc.java
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
|
||||
/**
|
||||
* Summon Pc AI.<br>
|
||||
* Summon the player to the NPC on attack.
|
||||
* @author Zoey76
|
||||
*/
|
||||
public final class SummonPc extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int PORTA = 20213;
|
||||
private static final int PERUM = 20221;
|
||||
// Skill
|
||||
private static final SkillHolder SUMMON_PC = new SkillHolder(4161, 1);
|
||||
|
||||
private SummonPc()
|
||||
{
|
||||
super(SummonPc.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(PORTA, PERUM);
|
||||
addSpellFinishedId(PORTA, PERUM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
final int chance = getRandom(100);
|
||||
final boolean attacked = npc.getVariables().getBoolean("attacked", false);
|
||||
if ((npc.calculateDistance(attacker, true, false) > 300) && !attacked)
|
||||
{
|
||||
if (chance < 50)
|
||||
{
|
||||
if ((SUMMON_PC.getSkill().getMpConsume() < npc.getCurrentMp()) && (SUMMON_PC.getSkill().getHpConsume() < npc.getCurrentHp()) && !npc.isSkillDisabled(SUMMON_PC.getSkill()))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SUMMON_PC.getSkill());
|
||||
}
|
||||
|
||||
if ((SUMMON_PC.getSkill().getMpConsume() < npc.getCurrentMp()) && (SUMMON_PC.getSkill().getHpConsume() < npc.getCurrentHp()) && !npc.isSkillDisabled(SUMMON_PC.getSkill()))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SUMMON_PC.getSkill());
|
||||
npc.getVariables().set("attacked", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((npc.calculateDistance(attacker, true, false) > 100) && !attacked)
|
||||
{
|
||||
final L2Attackable monster = (L2Attackable) npc;
|
||||
if (monster.getMostHated() != null)
|
||||
{
|
||||
if (((monster.getMostHated() == attacker) && (chance < 50)) || (chance < 10))
|
||||
{
|
||||
if ((SUMMON_PC.getSkill().getMpConsume() < npc.getCurrentMp()) && (SUMMON_PC.getSkill().getHpConsume() < npc.getCurrentHp()) && !npc.isSkillDisabled(SUMMON_PC.getSkill()))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SUMMON_PC.getSkill());
|
||||
npc.getVariables().set("attacked", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
|
||||
{
|
||||
if ((skill.getId() == SUMMON_PC.getSkillId()) && !npc.isDead() && npc.getVariables().getBoolean("attacked", false))
|
||||
{
|
||||
player.teleToLocation(npc);
|
||||
npc.getVariables().set("attacked", false);
|
||||
}
|
||||
return super.onSpellFinished(npc, player, skill);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new SummonPc();
|
||||
}
|
||||
}
|
139
trunk/dist/game/data_classic/scripts/ai/group_template/TurekOrcs.java
vendored
Normal file
139
trunk/dist/game/data_classic/scripts/ai/group_template/TurekOrcs.java
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.ai.CtrlIntention;
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.L2Object;
|
||||
import com.l2jserver.gameserver.model.L2World;
|
||||
import com.l2jserver.gameserver.model.Location;
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
|
||||
/**
|
||||
* Turek Orcs AI - flee and return with assistance
|
||||
* @author GKR
|
||||
*/
|
||||
|
||||
public final class TurekOrcs extends AbstractNpcAI
|
||||
{
|
||||
// NPC's
|
||||
private static final int[] MOBS =
|
||||
{
|
||||
20494, // Turek War Hound
|
||||
20495, // Turek Orc Warlord
|
||||
20497, // Turek Orc Skirmisher
|
||||
20498, // Turek Orc Supplier
|
||||
20499, // Turek Orc Footman
|
||||
20500, // Turek Orc Sentinel
|
||||
};
|
||||
|
||||
private TurekOrcs()
|
||||
{
|
||||
super(TurekOrcs.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(MOBS);
|
||||
addEventReceivedId(MOBS);
|
||||
addMoveFinishedId(MOBS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("checkState") && !npc.isDead() && (npc.getAI().getIntention() != CtrlIntention.AI_INTENTION_ATTACK))
|
||||
{
|
||||
if ((npc.getCurrentHp() > (npc.getMaxHp() * 0.7)) && (npc.getVariables().getInt("state") == 2))
|
||||
{
|
||||
npc.getVariables().set("state", 3);
|
||||
((L2Attackable) npc).returnHome();
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.getVariables().remove("state");
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (!npc.getVariables().hasVariable("isHit"))
|
||||
{
|
||||
npc.getVariables().set("isHit", 1);
|
||||
}
|
||||
else if ((npc.getCurrentHp() < (npc.getMaxHp() * 0.5)) && (npc.getCurrentHp() > (npc.getMaxHp() * 0.3)) && (attacker.getCurrentHp() > (attacker.getMaxHp() * 0.25)) && npc.hasAIValue("fleeX") && npc.hasAIValue("fleeY") && npc.hasAIValue("fleeZ") && (npc.getVariables().getInt("state") == 0) && (getRandom(100) < 10))
|
||||
{
|
||||
// Say and flee
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.getNpcStringId(getRandom(1000007, 1000027)));
|
||||
npc.disableCoreAI(true); // to avoid attacking behaviour, while flee
|
||||
npc.setIsRunning(true);
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(npc.getAIValue("fleeX"), npc.getAIValue("fleeY"), npc.getAIValue("fleeZ")));
|
||||
npc.getVariables().set("state", 1);
|
||||
npc.getVariables().set("attacker", attacker.getObjectId());
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onEventReceived(String eventName, L2Npc sender, L2Npc receiver, L2Object reference)
|
||||
{
|
||||
if (eventName.equals("WARNING") && !receiver.isDead() && (receiver.getAI().getIntention() != CtrlIntention.AI_INTENTION_ATTACK) && (reference != null) && (reference.getActingPlayer() != null) && !reference.getActingPlayer().isDead())
|
||||
{
|
||||
receiver.getVariables().set("state", 3);
|
||||
receiver.setIsRunning(true);
|
||||
((L2Attackable) receiver).addDamageHate(reference.getActingPlayer(), 0, 99999);
|
||||
receiver.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, reference.getActingPlayer());
|
||||
}
|
||||
return super.onEventReceived(eventName, sender, receiver, reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMoveFinished(L2Npc npc)
|
||||
{
|
||||
// NPC reaches flee point
|
||||
if (npc.getVariables().getInt("state") == 1)
|
||||
{
|
||||
if ((npc.getX() == npc.getAIValue("fleeX")) && (npc.getY() == npc.getAIValue("fleeY")))
|
||||
{
|
||||
npc.disableCoreAI(false);
|
||||
startQuestTimer("checkState", 15000, npc, null);
|
||||
npc.getVariables().set("state", 2);
|
||||
npc.broadcastEvent("WARNING", 400, L2World.getInstance().getPlayer(npc.getVariables().getInt("attacker")));
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(npc.getAIValue("fleeX"), npc.getAIValue("fleeY"), npc.getAIValue("fleeZ")));
|
||||
}
|
||||
}
|
||||
else if ((npc.getVariables().getInt("state") == 3) && npc.staysInSpawnLoc())
|
||||
{
|
||||
npc.disableCoreAI(false);
|
||||
npc.getVariables().remove("state");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new TurekOrcs();
|
||||
}
|
||||
}
|
142
trunk/dist/game/data_classic/scripts/ai/group_template/WarriorFishingBlock.java
vendored
Normal file
142
trunk/dist/game/data_classic/scripts/ai/group_template/WarriorFishingBlock.java
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.ai.CtrlEvent;
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.L2Object;
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
|
||||
/**
|
||||
* Warrior Fishing Block AI.
|
||||
* @author Zoey76
|
||||
*/
|
||||
public final class WarriorFishingBlock extends AbstractNpcAI
|
||||
{
|
||||
// Monsters
|
||||
private static final int[] MONSTERS =
|
||||
{
|
||||
18319, // Caught Frog
|
||||
18320, // Caught Undine
|
||||
18321, // Caught Rakul
|
||||
18322, // Caught Sea Giant
|
||||
18323, // Caught Sea Horse Soldier
|
||||
18324, // Caught Homunculus
|
||||
18325, // Caught Flava
|
||||
18326, // Caught Gigantic Eye
|
||||
};
|
||||
// NPC Strings
|
||||
private static final NpcStringId[] NPC_STRINGS_ON_SPAWN =
|
||||
{
|
||||
NpcStringId.CROAK_CROAK_FOOD_LIKE_S1_IN_THIS_PLACE,
|
||||
NpcStringId.S1_HOW_LUCKY_I_AM,
|
||||
NpcStringId.PRAY_THAT_YOU_CAUGHT_A_WRONG_FISH_S1
|
||||
};
|
||||
private static final NpcStringId[] NPC_STRINGS_ON_ATTACK =
|
||||
{
|
||||
NpcStringId.DO_YOU_KNOW_WHAT_A_FROG_TASTES_LIKE,
|
||||
NpcStringId.I_WILL_SHOW_YOU_THE_POWER_OF_A_FROG,
|
||||
NpcStringId.I_WILL_SWALLOW_AT_A_MOUTHFUL
|
||||
};
|
||||
private static final NpcStringId[] NPC_STRINGS_ON_KILL =
|
||||
{
|
||||
NpcStringId.UGH_NO_CHANCE_HOW_COULD_THIS_ELDER_PASS_AWAY_LIKE_THIS,
|
||||
NpcStringId.CROAK_CROAK_A_FROG_IS_DYING,
|
||||
NpcStringId.A_FROG_TASTES_BAD_YUCK
|
||||
};
|
||||
// Misc
|
||||
private static final int CHANCE_TO_SHOUT_ON_ATTACK = 33;
|
||||
private static final int DESPAWN_TIME = 50; // 50 seconds to despawn
|
||||
|
||||
public WarriorFishingBlock()
|
||||
{
|
||||
super(WarriorFishingBlock.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(MONSTERS);
|
||||
addKillId(MONSTERS);
|
||||
addSpawnId(MONSTERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "SPAWN":
|
||||
{
|
||||
final L2Object obj = npc.getTarget();
|
||||
if ((obj == null) || !obj.isPlayer())
|
||||
{
|
||||
npc.decayMe();
|
||||
}
|
||||
else
|
||||
{
|
||||
final L2PcInstance target = obj.getActingPlayer();
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NPC_STRINGS_ON_SPAWN[getRandom(NPC_STRINGS_ON_SPAWN.length)], target.getName());
|
||||
((L2Attackable) npc).addDamageHate(target, 0, 2000);
|
||||
npc.getAI().notifyEvent(CtrlEvent.EVT_ATTACKED, target);
|
||||
npc.addAttackerToAttackByList(target);
|
||||
|
||||
startQuestTimer("DESPAWN", DESPAWN_TIME * 1000, npc, target);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "DESPAWN":
|
||||
{
|
||||
npc.decayMe();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (getRandom(100) < CHANCE_TO_SHOUT_ON_ATTACK)
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NPC_STRINGS_ON_ATTACK[getRandom(NPC_STRINGS_ON_ATTACK.length)]);
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NPC_STRINGS_ON_KILL[getRandom(NPC_STRINGS_ON_KILL.length)]);
|
||||
cancelQuestTimer("DESPAWN", npc, killer);
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
startQuestTimer("SPAWN", 2000, npc, null);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new WarriorFishingBlock();
|
||||
}
|
||||
}
|
12
trunk/dist/game/data_classic/scripts/ai/group_template/documentation.txt
vendored
Normal file
12
trunk/dist/game/data_classic/scripts/ai/group_template/documentation.txt
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
Group Template AI:
|
||||
This folder contains AI scripts for group templates. That is, if many different mobs share the same behaviour,
|
||||
a group AI script can be created for all of them. Such group templates ought to be here.
|
||||
|
||||
Group templates can be subclassed. In other words, a group may inherit from another group. For example,
|
||||
one group template might define mobs that cast spells. Another template may then define the AI for mobs
|
||||
that cast spells AND use shots. In that case, instead of rewriting all the attack and spell-use AI, we can
|
||||
inherit from the first group template, then add the new behaviours, and split up the NPC registrations appropriately.
|
||||
|
||||
"NPC registrations" refers to the addition of NPCs in the various events of the scripts, such as onAttack, onKill, etc
|
||||
Those are done by using keywords such as "addKillId" etc. For more details on registrations, see
|
||||
"scripts/quests/documentation.txt"
|
37
trunk/dist/game/data_classic/scripts/ai/group_template/package-info.java
vendored
Normal file
37
trunk/dist/game/data_classic/scripts/ai/group_template/package-info.java
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Group Template AI:<br>
|
||||
* This folder contains AI scripts for group templates.<br>
|
||||
* That is, if many different mobs share the same behavior, a group AI script can be created for all of them.<br>
|
||||
* Such group templates ought to be here.<br>
|
||||
* <br>
|
||||
* Group templates can be sub-classed.<br>
|
||||
* In other words, a group may inherit from another group.<br>
|
||||
* For example, one group template might define mobs that cast spells.<br>
|
||||
* Another template may then define the AI for mobs that cast spells AND use shots.<br>
|
||||
* In that case, instead of rewriting all the attack and spell-use AI, we can inherit from the first group template, then add the new behaviors, and split up the NPC registrations appropriately.<br>
|
||||
* <br>
|
||||
* "NPC registrations" refers to the addition of NPCs in the various events of the scripts, such as onAttack, onKill, etc.<br>
|
||||
* Those are done by using methods such as addKillId(..) etc.<br>
|
||||
* @see quests
|
||||
* @author Fulminus, Zoey76
|
||||
*/
|
||||
package ai.group_template;
|
107
trunk/dist/game/data_classic/scripts/ai/individual/CrimsonHatuOtis.java
vendored
Normal file
107
trunk/dist/game/data_classic/scripts/ai/individual/CrimsonHatuOtis.java
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
|
||||
/**
|
||||
* AI for Kamaloka (33) - Crimson Hatu Otis
|
||||
* @author Gladicek
|
||||
*/
|
||||
public final class CrimsonHatuOtis extends AbstractNpcAI
|
||||
{
|
||||
// Npc
|
||||
private static final int CRIMSON_HATU_OTIS = 18558;
|
||||
// Skills
|
||||
private static SkillHolder BOSS_SPINING_SLASH = new SkillHolder(4737, 1);
|
||||
private static SkillHolder BOSS_HASTE = new SkillHolder(4175, 1);
|
||||
|
||||
private CrimsonHatuOtis()
|
||||
{
|
||||
super(CrimsonHatuOtis.class.getSimpleName(), "ai/individual");
|
||||
addAttackId(CRIMSON_HATU_OTIS);
|
||||
addKillId(CRIMSON_HATU_OTIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "SKILL":
|
||||
{
|
||||
if (npc.isDead())
|
||||
{
|
||||
cancelQuestTimer("SKILL", npc, null);
|
||||
return null;
|
||||
}
|
||||
npc.setTarget(player);
|
||||
npc.doCast(BOSS_SPINING_SLASH.getSkill());
|
||||
startQuestTimer("SKILL", 60000, npc, null);
|
||||
break;
|
||||
}
|
||||
case "BUFF":
|
||||
{
|
||||
if (npc.isScriptValue(2))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(BOSS_HASTE.getSkill());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
startQuestTimer("SKILL", 5000, npc, null);
|
||||
}
|
||||
else if (npc.isScriptValue(1) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.3)))
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.I_VE_HAD_IT_UP_TO_HERE_WITH_YOU_I_LL_TAKE_CARE_OF_YOU);
|
||||
npc.setScriptValue(2);
|
||||
startQuestTimer("BUFF", 1000, npc, null);
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
cancelQuestTimer("SKILL", npc, null);
|
||||
cancelQuestTimer("BUFF", npc, null);
|
||||
return super.onKill(npc, player, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new CrimsonHatuOtis();
|
||||
}
|
||||
}
|
247
trunk/dist/game/data_classic/scripts/ai/individual/DarkWaterDragon.java
vendored
Normal file
247
trunk/dist/game/data_classic/scripts/ai/individual/DarkWaterDragon.java
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.ai.CtrlIntention;
|
||||
import com.l2jserver.gameserver.data.xml.impl.NpcData;
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Character;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
/**
|
||||
* Dark Water Dragon's AI.
|
||||
*/
|
||||
public final class DarkWaterDragon extends AbstractNpcAI
|
||||
{
|
||||
private static final int DRAGON = 22267;
|
||||
private static final int SHADE1 = 22268;
|
||||
private static final int SHADE2 = 22269;
|
||||
private static final int FAFURION = 18482;
|
||||
private static final int DETRACTOR1 = 22270;
|
||||
private static final int DETRACTOR2 = 22271;
|
||||
private static final Set<Integer> SECOND_SPAWN = ConcurrentHashMap.newKeySet(); // Used to track if second Shades were already spawned
|
||||
private static Set<Integer> MY_TRACKING_SET = ConcurrentHashMap.newKeySet(); // Used to track instances of npcs
|
||||
private static Map<Integer, L2PcInstance> ID_MAP = new ConcurrentHashMap<>(); // Used to track instances of npcs
|
||||
|
||||
private DarkWaterDragon()
|
||||
{
|
||||
super(DarkWaterDragon.class.getSimpleName(), "ai/individual");
|
||||
int[] mobs =
|
||||
{
|
||||
DRAGON,
|
||||
SHADE1,
|
||||
SHADE2,
|
||||
FAFURION,
|
||||
DETRACTOR1,
|
||||
DETRACTOR2
|
||||
};
|
||||
addKillId(mobs);
|
||||
addAttackId(mobs);
|
||||
addSpawnId(mobs);
|
||||
MY_TRACKING_SET.clear();
|
||||
SECOND_SPAWN.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
if (event.equalsIgnoreCase("first_spawn")) // timer to start timer "1"
|
||||
{
|
||||
startQuestTimer("1", 40000, npc, null, true); // spawns detractor every 40 seconds
|
||||
}
|
||||
else if (event.equalsIgnoreCase("second_spawn")) // timer to start timer "2"
|
||||
{
|
||||
startQuestTimer("2", 40000, npc, null, true); // spawns detractor every 40 seconds
|
||||
}
|
||||
else if (event.equalsIgnoreCase("third_spawn")) // timer to start timer "3"
|
||||
{
|
||||
startQuestTimer("3", 40000, npc, null, true); // spawns detractor every 40 seconds
|
||||
}
|
||||
else if (event.equalsIgnoreCase("fourth_spawn")) // timer to start timer "4"
|
||||
{
|
||||
startQuestTimer("4", 40000, npc, null, true); // spawns detractor every 40 seconds
|
||||
}
|
||||
else if (event.equalsIgnoreCase("1")) // spawns a detractor
|
||||
{
|
||||
addSpawn(DETRACTOR1, (npc.getX() + 100), (npc.getY() + 100), npc.getZ(), 0, false, 40000);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("2")) // spawns a detractor
|
||||
{
|
||||
addSpawn(DETRACTOR2, (npc.getX() + 100), (npc.getY() - 100), npc.getZ(), 0, false, 40000);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("3")) // spawns a detractor
|
||||
{
|
||||
addSpawn(DETRACTOR1, (npc.getX() - 100), (npc.getY() + 100), npc.getZ(), 0, false, 40000);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("4")) // spawns a detractor
|
||||
{
|
||||
addSpawn(DETRACTOR2, (npc.getX() - 100), (npc.getY() - 100), npc.getZ(), 0, false, 40000);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("fafurion_despawn")) // Fafurion Kindred disappears and drops reward
|
||||
{
|
||||
cancelQuestTimer("fafurion_poison", npc, null);
|
||||
cancelQuestTimer("1", npc, null);
|
||||
cancelQuestTimer("2", npc, null);
|
||||
cancelQuestTimer("3", npc, null);
|
||||
cancelQuestTimer("4", npc, null);
|
||||
|
||||
MY_TRACKING_SET.remove(npc.getObjectId());
|
||||
player = ID_MAP.remove(npc.getObjectId());
|
||||
if (player != null)
|
||||
{
|
||||
((L2Attackable) npc).doItemDrop(NpcData.getInstance().getTemplate(18485), player);
|
||||
}
|
||||
|
||||
npc.deleteMe();
|
||||
}
|
||||
else if (event.equalsIgnoreCase("fafurion_poison")) // Reduces Fafurions hp like it is poisoned
|
||||
{
|
||||
if (npc.getCurrentHp() <= 500)
|
||||
{
|
||||
cancelQuestTimer("fafurion_despawn", npc, null);
|
||||
cancelQuestTimer("first_spawn", npc, null);
|
||||
cancelQuestTimer("second_spawn", npc, null);
|
||||
cancelQuestTimer("third_spawn", npc, null);
|
||||
cancelQuestTimer("fourth_spawn", npc, null);
|
||||
cancelQuestTimer("1", npc, null);
|
||||
cancelQuestTimer("2", npc, null);
|
||||
cancelQuestTimer("3", npc, null);
|
||||
cancelQuestTimer("4", npc, null);
|
||||
MY_TRACKING_SET.remove(npc.getObjectId());
|
||||
ID_MAP.remove(npc.getObjectId());
|
||||
}
|
||||
npc.reduceCurrentHp(500, npc, null); // poison kills Fafurion if he is not healed
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
int npcId = npc.getId();
|
||||
int npcObjId = npc.getObjectId();
|
||||
if (npcId == DRAGON)
|
||||
{
|
||||
if (!MY_TRACKING_SET.contains(npcObjId)) // this allows to handle multiple instances of npc
|
||||
{
|
||||
MY_TRACKING_SET.add(npcObjId);
|
||||
// Spawn first 5 shades on first attack on Dark Water Dragon
|
||||
L2Character originalAttacker = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : attacker;
|
||||
spawnShade(originalAttacker, SHADE1, npc.getX() + 100, npc.getY() + 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE2, npc.getX() + 100, npc.getY() - 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE1, npc.getX() - 100, npc.getY() + 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE2, npc.getX() - 100, npc.getY() - 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE1, npc.getX() - 150, npc.getY() + 150, npc.getZ());
|
||||
}
|
||||
else if ((npc.getCurrentHp() < (npc.getMaxHp() / 2.0)) && !(SECOND_SPAWN.contains(npcObjId)))
|
||||
{
|
||||
SECOND_SPAWN.add(npcObjId);
|
||||
// Spawn second 5 shades on half hp of on Dark Water Dragon
|
||||
L2Character originalAttacker = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : attacker;
|
||||
spawnShade(originalAttacker, SHADE2, npc.getX() + 100, npc.getY() + 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE1, npc.getX() + 100, npc.getY() - 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE2, npc.getX() - 100, npc.getY() + 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE1, npc.getX() - 100, npc.getY() - 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE2, npc.getX() - 150, npc.getY() + 150, npc.getZ());
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
int npcId = npc.getId();
|
||||
int npcObjId = npc.getObjectId();
|
||||
if (npcId == DRAGON)
|
||||
{
|
||||
MY_TRACKING_SET.remove(npcObjId);
|
||||
SECOND_SPAWN.remove(npcObjId);
|
||||
L2Attackable faf = (L2Attackable) addSpawn(FAFURION, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0); // spawns Fafurion Kindred when Dard Water Dragon is dead
|
||||
ID_MAP.put(faf.getObjectId(), killer);
|
||||
}
|
||||
else if (npcId == FAFURION)
|
||||
{
|
||||
cancelQuestTimer("fafurion_poison", npc, null);
|
||||
cancelQuestTimer("fafurion_despawn", npc, null);
|
||||
cancelQuestTimer("first_spawn", npc, null);
|
||||
cancelQuestTimer("second_spawn", npc, null);
|
||||
cancelQuestTimer("third_spawn", npc, null);
|
||||
cancelQuestTimer("fourth_spawn", npc, null);
|
||||
cancelQuestTimer("1", npc, null);
|
||||
cancelQuestTimer("2", npc, null);
|
||||
cancelQuestTimer("3", npc, null);
|
||||
cancelQuestTimer("4", npc, null);
|
||||
MY_TRACKING_SET.remove(npcObjId);
|
||||
ID_MAP.remove(npcObjId);
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
int npcId = npc.getId();
|
||||
int npcObjId = npc.getObjectId();
|
||||
if (npcId == FAFURION)
|
||||
{
|
||||
if (!MY_TRACKING_SET.contains(npcObjId))
|
||||
{
|
||||
MY_TRACKING_SET.add(npcObjId);
|
||||
// Spawn 4 Detractors on spawn of Fafurion
|
||||
int x = npc.getX();
|
||||
int y = npc.getY();
|
||||
addSpawn(DETRACTOR2, x + 100, y + 100, npc.getZ(), 0, false, 40000);
|
||||
addSpawn(DETRACTOR1, x + 100, y - 100, npc.getZ(), 0, false, 40000);
|
||||
addSpawn(DETRACTOR2, x - 100, y + 100, npc.getZ(), 0, false, 40000);
|
||||
addSpawn(DETRACTOR1, x - 100, y - 100, npc.getZ(), 0, false, 40000);
|
||||
startQuestTimer("first_spawn", 2000, npc, null); // timer to delay timer "1"
|
||||
startQuestTimer("second_spawn", 4000, npc, null); // timer to delay timer "2"
|
||||
startQuestTimer("third_spawn", 8000, npc, null); // timer to delay timer "3"
|
||||
startQuestTimer("fourth_spawn", 10000, npc, null); // timer to delay timer "4"
|
||||
startQuestTimer("fafurion_poison", 3000, npc, null, true); // Every three seconds reduces Fafurions hp like it is poisoned
|
||||
startQuestTimer("fafurion_despawn", 120000, npc, null); // Fafurion Kindred disappears after two minutes
|
||||
}
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public void spawnShade(L2Character attacker, int npcId, int x, int y, int z)
|
||||
{
|
||||
final L2Npc shade = addSpawn(npcId, x, y, z, 0, false, 0);
|
||||
shade.setRunning();
|
||||
((L2Attackable) shade).addDamageHate(attacker, 0, 999);
|
||||
shade.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new DarkWaterDragon();
|
||||
}
|
||||
}
|
69
trunk/dist/game/data_classic/scripts/ai/individual/DivineBeast.java
vendored
Normal file
69
trunk/dist/game/data_classic/scripts/ai/individual/DivineBeast.java
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.L2Summon;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
/**
|
||||
* Simple AI that manages special conditions for Divine Beast summon.
|
||||
* @author UnAfraid
|
||||
*/
|
||||
public final class DivineBeast extends AbstractNpcAI
|
||||
{
|
||||
private static final int DIVINE_BEAST = 14870;
|
||||
private static final int TRANSFORMATION_ID = 258;
|
||||
private static final int CHECK_TIME = 2 * 1000;
|
||||
|
||||
private DivineBeast()
|
||||
{
|
||||
super(DivineBeast.class.getSimpleName(), "ai");
|
||||
addSummonSpawnId(DIVINE_BEAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSummonSpawn(L2Summon summon)
|
||||
{
|
||||
startQuestTimer("VALIDATE_TRANSFORMATION", CHECK_TIME, null, summon.getActingPlayer(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if ((player == null) || !player.hasServitors())
|
||||
{
|
||||
cancelQuestTimer(event, npc, player);
|
||||
}
|
||||
else if (player.getTransformationId() != TRANSFORMATION_ID)
|
||||
{
|
||||
cancelQuestTimer(event, npc, player);
|
||||
player.getServitors().values().forEach(summon -> summon.unSummon(player));
|
||||
}
|
||||
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new DivineBeast();
|
||||
}
|
||||
}
|
329
trunk/dist/game/data_classic/scripts/ai/individual/DrChaos.java
vendored
Normal file
329
trunk/dist/game/data_classic/scripts/ai/individual/DrChaos.java
vendored
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.ai.CtrlIntention;
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jserver.gameserver.model.Location;
|
||||
import com.l2jserver.gameserver.model.StatsSet;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
|
||||
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
|
||||
import com.l2jserver.gameserver.network.serverpackets.SpecialCamera;
|
||||
import com.l2jserver.util.Rnd;
|
||||
|
||||
/**
|
||||
* Dr. Chaos is a boss @ Pavel's Ruins. Some things to know :
|
||||
* <ul>
|
||||
* <li>As a mad scientist, he thinks all are spies, and for so if you stand too much longer near him you're considered as an "assassin from Black Anvil Guild".</li>
|
||||
* <li>You can chat with him, but if you try too much he will become angry.</li>
|
||||
* <li>That adaptation sends a decent cinematic made with the different social actions too.</li>
|
||||
* <li>The status of the RB is saved under GBs table, in order to retrieve the state if server restarts.</li>
|
||||
* <li>The spawn of the different NPCs (Dr. Chaos / War golem) is handled by that script aswell.</li>
|
||||
* </ul>
|
||||
* @author Kerberos, Tryskell.
|
||||
*/
|
||||
public class DrChaos extends AbstractNpcAI
|
||||
{
|
||||
private static final int DOCTOR_CHAOS = 32033;
|
||||
private static final int CHAOS_GOLEM = 25512;
|
||||
|
||||
private static final byte NORMAL = 0; // Dr. Chaos is in NPC form.
|
||||
private static final byte CRAZY = 1; // Dr. Chaos entered on golem form.
|
||||
private static final byte DEAD = 2; // Dr. Chaos has been killed and has not yet spawned.
|
||||
|
||||
private long _lastAttackVsGolem = 0;
|
||||
private int _pissedOffTimer;
|
||||
|
||||
public DrChaos()
|
||||
{
|
||||
super(DrChaos.class.getSimpleName(), "ai");
|
||||
|
||||
addFirstTalkId(DOCTOR_CHAOS); // Different HTMs following actual humor.
|
||||
addSpawnId(DOCTOR_CHAOS); // Timer activation at 30sec + paranoia activity.
|
||||
|
||||
addKillId(CHAOS_GOLEM); // Message + despawn.
|
||||
addAttackId(CHAOS_GOLEM); // Random messages when he attacks.
|
||||
|
||||
StatsSet info = GrandBossManager.getInstance().getStatsSet(CHAOS_GOLEM);
|
||||
int status = GrandBossManager.getInstance().getBossStatus(CHAOS_GOLEM);
|
||||
|
||||
// Load the reset date and time for Dr. Chaos from DB.
|
||||
if (status == DEAD)
|
||||
{
|
||||
long temp = (info.getLong("respawn_time") - System.currentTimeMillis());
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("reset_drchaos", temp, null, null, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The time has already expired while the server was offline. Delete the saved time and
|
||||
// immediately spawn Dr. Chaos. Also the state need to be changed for NORMAL
|
||||
addSpawn(DOCTOR_CHAOS, 96320, -110912, -3328, 8191, false, 0, false);
|
||||
GrandBossManager.getInstance().setBossStatus(CHAOS_GOLEM, NORMAL);
|
||||
}
|
||||
}
|
||||
// Spawn the war golem.
|
||||
else if (status == CRAZY)
|
||||
{
|
||||
int loc_x = info.getInt("loc_x");
|
||||
int loc_y = info.getInt("loc_y");
|
||||
int loc_z = info.getInt("loc_z");
|
||||
int heading = info.getInt("heading");
|
||||
final int hp = info.getInt("currentHP");
|
||||
final int mp = info.getInt("currentMP");
|
||||
|
||||
L2GrandBossInstance golem = (L2GrandBossInstance) addSpawn(CHAOS_GOLEM, loc_x, loc_y, loc_z, heading, false, 0, false);
|
||||
GrandBossManager.getInstance().addBoss(golem);
|
||||
|
||||
final L2Npc _golem = golem;
|
||||
|
||||
_golem.setCurrentHpMp(hp, mp);
|
||||
_golem.setRunning();
|
||||
|
||||
// start monitoring Dr. Chaos's inactivity
|
||||
_lastAttackVsGolem = System.currentTimeMillis();
|
||||
startQuestTimer("golem_despawn", 60000, _golem, null, true);
|
||||
}
|
||||
// Spawn the regular NPC.
|
||||
else
|
||||
{
|
||||
addSpawn(DOCTOR_CHAOS, 96320, -110912, -3328, 8191, false, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("reset_drchaos"))
|
||||
{
|
||||
GrandBossManager.getInstance().setBossStatus(CHAOS_GOLEM, NORMAL);
|
||||
addSpawn(DOCTOR_CHAOS, 96320, -110912, -3328, 8191, false, 0, false);
|
||||
}
|
||||
// despawn the live Dr. Chaos after 30 minutes of inactivity
|
||||
else if (event.equalsIgnoreCase("golem_despawn") && (npc != null))
|
||||
{
|
||||
if (npc.getId() == CHAOS_GOLEM)
|
||||
{
|
||||
if ((_lastAttackVsGolem + 1800000) < System.currentTimeMillis())
|
||||
{
|
||||
// Despawn the war golem.
|
||||
npc.deleteMe();
|
||||
|
||||
addSpawn(DOCTOR_CHAOS, 96320, -110912, -3328, 8191, false, 0, false); // spawn Dr. Chaos
|
||||
GrandBossManager.getInstance().setBossStatus(CHAOS_GOLEM, NORMAL); // mark Dr. Chaos is not crazy any more
|
||||
cancelQuestTimer("golem_despawn", npc, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("1"))
|
||||
{
|
||||
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 2));
|
||||
npc.broadcastPacket(new SpecialCamera(npc, 1, -200, 15, 5500, 1000, 13500, 0, 0, 0, 0, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("2"))
|
||||
{
|
||||
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 3));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("3"))
|
||||
{
|
||||
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 1));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("4"))
|
||||
{
|
||||
npc.broadcastPacket(new SpecialCamera(npc, 1, -150, 10, 3500, 1000, 5000, 0, 0, 0, 0, 0));
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(95928, -110671, -3340, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("5"))
|
||||
{
|
||||
// Delete Dr. Chaos && spawn the war golem.
|
||||
npc.deleteMe();
|
||||
L2GrandBossInstance golem = (L2GrandBossInstance) addSpawn(CHAOS_GOLEM, 96080, -110822, -3343, 0, false, 0, false);
|
||||
GrandBossManager.getInstance().addBoss(golem);
|
||||
|
||||
// The "npc" variable attribution is now for the golem.
|
||||
npc = golem;
|
||||
npc.broadcastPacket(new SpecialCamera(npc, 30, 200, 20, 6000, 700, 8000, 0, 0, 0, 0, 0));
|
||||
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 1));
|
||||
npc.broadcastPacket(new PlaySound(1, "Rm03_A", 0, 0, 0, 0, 0));
|
||||
|
||||
// start monitoring Dr. Chaos's inactivity
|
||||
_lastAttackVsGolem = System.currentTimeMillis();
|
||||
startQuestTimer("golem_despawn", 60000, npc, null, true);
|
||||
}
|
||||
// Check every sec if someone is in range, if found, launch one task to decrease the timer.
|
||||
else if (event.equalsIgnoreCase("paranoia_activity"))
|
||||
{
|
||||
if (GrandBossManager.getInstance().getBossStatus(CHAOS_GOLEM) == NORMAL)
|
||||
{
|
||||
for (L2PcInstance obj : npc.getKnownList().getKnownPlayersInRadius(500))
|
||||
{
|
||||
if (obj.isDead())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_pissedOffTimer -= 1;
|
||||
|
||||
// Make him speak.
|
||||
if (_pissedOffTimer == 15)
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, "How dare you trespass into my territory! Have you no fear?");
|
||||
}
|
||||
|
||||
// That was "too much" for that time.
|
||||
if (_pissedOffTimer <= 0)
|
||||
{
|
||||
crazyMidgetBecomesAngry(npc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFirstTalk(L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
String htmltext = "";
|
||||
|
||||
if (GrandBossManager.getInstance().getBossStatus(CHAOS_GOLEM) == NORMAL)
|
||||
{
|
||||
_pissedOffTimer -= 1 + Rnd.get(5); // remove 1-5 secs.
|
||||
|
||||
if ((_pissedOffTimer > 20) && (_pissedOffTimer <= 30))
|
||||
{
|
||||
htmltext = "<html><body>Doctor Chaos:<br>What?! Who are you? How did you come here?<br>You really look suspicious... Aren't those filthy members of Black Anvil guild send you? No? Mhhhhh... I don't trust you!</body></html>";
|
||||
}
|
||||
else if ((_pissedOffTimer > 10) && (_pissedOffTimer <= 20))
|
||||
{
|
||||
htmltext = "<html><body>Doctor Chaos:<br>Why are you standing here? Don't you see it's a private propertie? Don't look at him with those eyes... Did you smile?! Don't make fun of me! He will ... destroy ... you ... if you continue!</body></html>";
|
||||
}
|
||||
else if ((_pissedOffTimer > 0) && (_pissedOffTimer <= 10))
|
||||
{
|
||||
htmltext = "<html><body>Doctor Chaos:<br>I know why you are here, traitor! He discovered your plans! You are assassin ... sent by the Black Anvil guild! But you won't kill the Emperor of Evil!</body></html>";
|
||||
}
|
||||
else if (_pissedOffTimer <= 0)
|
||||
{
|
||||
crazyMidgetBecomesAngry(npc);
|
||||
}
|
||||
}
|
||||
|
||||
return htmltext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
// 30 seconds timer at initialization.
|
||||
_pissedOffTimer = 30;
|
||||
|
||||
// Initialization of the paranoia.
|
||||
startQuestTimer("paranoia_activity", 1000, npc, null, true);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance player, boolean isPet)
|
||||
{
|
||||
cancelQuestTimer("golem_despawn", npc, null);
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, "Urggh! You will pay dearly for this insult.");
|
||||
|
||||
// "lock" Dr. Chaos for regular RB time (36H fixed +- 24H random)
|
||||
long respawnTime = (36 + Rnd.get(-24, 24)) * 3600000;
|
||||
|
||||
GrandBossManager.getInstance().setBossStatus(CHAOS_GOLEM, DEAD);
|
||||
startQuestTimer("reset_drchaos", respawnTime, null, null, false);
|
||||
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
StatsSet info = GrandBossManager.getInstance().getStatsSet(CHAOS_GOLEM);
|
||||
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(CHAOS_GOLEM, info);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance victim, int damage, boolean isPet)
|
||||
{
|
||||
int chance = Rnd.get(300);
|
||||
|
||||
// Choose a message from 3 choices (1/100)
|
||||
if (chance < 3)
|
||||
{
|
||||
String message = "";
|
||||
switch (chance)
|
||||
{
|
||||
case 0:
|
||||
message = "Bwah-ha-ha! Your doom is at hand! Behold the Ultra Secret Super Weapon!";
|
||||
break;
|
||||
case 1:
|
||||
message = "Foolish, insignificant creatures! How dare you challenge me!";
|
||||
break;
|
||||
default:
|
||||
message = "I see that none will challenge me now!";
|
||||
break;
|
||||
}
|
||||
|
||||
// Make him speak.
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, message);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the complete animation.
|
||||
* @param npc the midget.
|
||||
*/
|
||||
private void crazyMidgetBecomesAngry(L2Npc npc)
|
||||
{
|
||||
if (GrandBossManager.getInstance().getBossStatus(CHAOS_GOLEM) == NORMAL)
|
||||
{
|
||||
// Set the status to "crazy".
|
||||
GrandBossManager.getInstance().setBossStatus(CHAOS_GOLEM, CRAZY);
|
||||
|
||||
// Cancels the paranoia timer.
|
||||
cancelQuestTimer("paranoia_activity", npc, null);
|
||||
|
||||
// Makes the NPC moves near the Strange Box speaking.
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(96323, -110914, -3328, 0));
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, "Fools! Why haven't you fled yet? Prepare to learn a lesson!");
|
||||
|
||||
// Delayed animation timers.
|
||||
startQuestTimer("1", 2000, npc, null, false); // 2 secs, time to launch dr.C anim 2. Cam 1 on.
|
||||
startQuestTimer("2", 4000, npc, null, false); // 2,5 secs, time to launch dr.C anim 3.
|
||||
startQuestTimer("3", 6500, npc, null, false); // 6 secs, time to launch dr.C anim 1.
|
||||
startQuestTimer("4", 12500, npc, null, false); // 4,5 secs to make the NPC moves to the grotto. Cam 2 on.
|
||||
startQuestTimer("5", 17000, npc, null, false); // 4 secs for golem spawn, and golem anim. Cam 3 on.
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new DrChaos();
|
||||
}
|
||||
}
|
77
trunk/dist/game/data_classic/scripts/ai/individual/EvasGiftBox.java
vendored
Normal file
77
trunk/dist/game/data_classic/scripts/ai/individual/EvasGiftBox.java
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.ItemHolder;
|
||||
|
||||
/**
|
||||
* Eva's Gift Box AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
public final class EvasGiftBox extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int BOX = 32342; // Eva's Gift Box
|
||||
// Skill
|
||||
private static final int BUFF = 1073; // Kiss of Eva
|
||||
// Items
|
||||
private static final ItemHolder CORAL = new ItemHolder(9692, 1); // Red Coral
|
||||
private static final ItemHolder CRYSTAL = new ItemHolder(9693, 1); // Crystal Fragment
|
||||
|
||||
private EvasGiftBox()
|
||||
{
|
||||
super(EvasGiftBox.class.getSimpleName(), "ai/individual");
|
||||
addKillId(BOX);
|
||||
addSpawnId(BOX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (killer.isAffectedBySkill(BUFF))
|
||||
{
|
||||
if (getRandomBoolean())
|
||||
{
|
||||
npc.dropItem(killer, CRYSTAL);
|
||||
}
|
||||
|
||||
if (getRandom(100) < 33)
|
||||
{
|
||||
npc.dropItem(killer, CORAL);
|
||||
}
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
npc.setIsNoRndWalk(true);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new EvasGiftBox();
|
||||
}
|
||||
}
|
149
trunk/dist/game/data_classic/scripts/ai/individual/FrightenedRagnaOrc.java
vendored
Normal file
149
trunk/dist/game/data_classic/scripts/ai/individual/FrightenedRagnaOrc.java
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.ai.CtrlIntention;
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.Location;
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jserver.gameserver.model.itemcontainer.Inventory;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
|
||||
/**
|
||||
* Frightened Ragna Orc AI.
|
||||
* @author Gladicek, malyelfik
|
||||
*/
|
||||
public final class FrightenedRagnaOrc extends AbstractNpcAI
|
||||
{
|
||||
// NPC ID
|
||||
private static final int MOB_ID = 18807;
|
||||
// Chances
|
||||
private static final int ADENA = 10000;
|
||||
private static final int CHANCE = 1000;
|
||||
private static final int ADENA2 = 1000000;
|
||||
private static final int CHANCE2 = 10;
|
||||
// Skill
|
||||
private static final SkillHolder SKILL = new SkillHolder(6234, 1);
|
||||
|
||||
private FrightenedRagnaOrc()
|
||||
{
|
||||
super(FrightenedRagnaOrc.class.getSimpleName(), "ai/individual");
|
||||
addAttackId(MOB_ID);
|
||||
addKillId(MOB_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
startQuestTimer("say", (getRandom(5) + 3) * 1000, npc, null, true);
|
||||
}
|
||||
else if ((npc.getCurrentHp() < (npc.getMaxHp() * 0.2)) && npc.isScriptValue(1))
|
||||
{
|
||||
startQuestTimer("reward", 10000, npc, attacker);
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.WAIT_WAIT_STOP_SAVE_ME_AND_I_LL_GIVE_YOU_10_000_000_ADENA);
|
||||
npc.setScriptValue(2);
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
final NpcStringId msg = getRandomBoolean() ? NpcStringId.UGH_A_CURSE_UPON_YOU : NpcStringId.I_REALLY_DIDN_T_WANT_TO_FIGHT;
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, msg);
|
||||
cancelQuestTimer("say", npc, null);
|
||||
cancelQuestTimer("reward", npc, player);
|
||||
return super.onKill(npc, player, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "say":
|
||||
{
|
||||
if (npc.isDead() || !npc.isScriptValue(1))
|
||||
{
|
||||
cancelQuestTimer("say", npc, null);
|
||||
return null;
|
||||
}
|
||||
final NpcStringId msg = getRandomBoolean() ? NpcStringId.I_DON_T_WANT_TO_FIGHT : NpcStringId.IS_THIS_REALLY_NECESSARY;
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, msg);
|
||||
break;
|
||||
}
|
||||
case "reward":
|
||||
{
|
||||
if (!npc.isDead() && npc.isScriptValue(2))
|
||||
{
|
||||
if (getRandom(100000) < CHANCE2)
|
||||
{
|
||||
final NpcStringId msg = getRandomBoolean() ? NpcStringId.TH_THANKS_I_COULD_HAVE_BECOME_GOOD_FRIENDS_WITH_YOU : NpcStringId.I_LL_GIVE_YOU_10_000_000_ADENA_LIKE_I_PROMISED_I_MIGHT_BE_AN_ORC_WHO_KEEPS_MY_PROMISES;
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, msg);
|
||||
npc.setScriptValue(3);
|
||||
npc.doCast(SKILL.getSkill());
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
npc.dropItem(player, Inventory.ADENA_ID, ADENA2);
|
||||
}
|
||||
}
|
||||
else if (getRandom(100000) < CHANCE)
|
||||
{
|
||||
final NpcStringId msg = getRandomBoolean() ? NpcStringId.TH_THANKS_I_COULD_HAVE_BECOME_GOOD_FRIENDS_WITH_YOU : NpcStringId.SORRY_BUT_THIS_IS_ALL_I_HAVE_GIVE_ME_A_BREAK;
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, msg);
|
||||
npc.setScriptValue(3);
|
||||
npc.doCast(SKILL.getSkill());
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
((L2Attackable) npc).dropItem(player, Inventory.ADENA_ID, ADENA);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final NpcStringId msg = getRandomBoolean() ? NpcStringId.THANKS_BUT_THAT_THING_ABOUT_10_000_000_ADENA_WAS_A_LIE_SEE_YA : NpcStringId.YOU_RE_PRETTY_DUMB_TO_BELIEVE_ME;
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, msg);
|
||||
}
|
||||
startQuestTimer("despawn", 1000, npc, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "despawn":
|
||||
{
|
||||
npc.setRunning();
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location((npc.getX() + getRandom(-800, 800)), (npc.getY() + getRandom(-800, 800)), npc.getZ(), npc.getHeading()));
|
||||
npc.deleteMe();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new FrightenedRagnaOrc();
|
||||
}
|
||||
}
|
55
trunk/dist/game/data_classic/scripts/ai/individual/GraveRobbers.java
vendored
Normal file
55
trunk/dist/game/data_classic/scripts/ai/individual/GraveRobbers.java
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
|
||||
/**
|
||||
* Grove Robber's AI.<br>
|
||||
* <ul>
|
||||
* <li>Grove Robber Summoner</li>
|
||||
* <li>Grove Robber Megician</li>
|
||||
* </ul>
|
||||
* @author Zealar
|
||||
*/
|
||||
public final class GraveRobbers extends AbstractNpcAI
|
||||
{
|
||||
private static final int GRAVE_ROBBER_SUMMONER = 22678;
|
||||
private static final int GRAVE_ROBBER_MEGICIAN = 22679;
|
||||
|
||||
private GraveRobbers()
|
||||
{
|
||||
super(GraveRobbers.class.getSimpleName(), "ai/individual");
|
||||
addSpawnId(GRAVE_ROBBER_SUMMONER, GRAVE_ROBBER_MEGICIAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
spawnMinions(npc, "Privates" + getRandom(1, 2));
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new GraveRobbers();
|
||||
}
|
||||
}
|
357
trunk/dist/game/data_classic/scripts/ai/individual/Orfen.java
vendored
Normal file
357
trunk/dist/game/data_classic/scripts/ai/individual/Orfen.java
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.gameserver.ai.CtrlIntention;
|
||||
import com.l2jserver.gameserver.datatables.SkillData;
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jserver.gameserver.model.L2Object;
|
||||
import com.l2jserver.gameserver.model.L2Spawn;
|
||||
import com.l2jserver.gameserver.model.Location;
|
||||
import com.l2jserver.gameserver.model.StatsSet;
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Character;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
import com.l2jserver.gameserver.model.zone.type.L2BossZone;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
|
||||
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
|
||||
|
||||
/**
|
||||
* Orfen's AI
|
||||
* @author Emperorc
|
||||
*/
|
||||
public final class Orfen extends AbstractNpcAI
|
||||
{
|
||||
private static final Location[] POS =
|
||||
{
|
||||
new Location(43728, 17220, -4342),
|
||||
new Location(55024, 17368, -5412),
|
||||
new Location(53504, 21248, -5486),
|
||||
new Location(53248, 24576, -5262)
|
||||
};
|
||||
|
||||
private static final NpcStringId[] TEXT =
|
||||
{
|
||||
NpcStringId.S1_STOP_KIDDING_YOURSELF_ABOUT_YOUR_OWN_POWERLESSNESS,
|
||||
NpcStringId.S1_I_LL_MAKE_YOU_FEEL_WHAT_TRUE_FEAR_IS,
|
||||
NpcStringId.YOU_RE_REALLY_STUPID_TO_HAVE_CHALLENGED_ME_S1_GET_READY,
|
||||
NpcStringId.S1_DO_YOU_THINK_THAT_S_GOING_TO_WORK
|
||||
};
|
||||
|
||||
private static final int ORFEN = 29014;
|
||||
// private static final int RAIKEL = 29015;
|
||||
private static final int RAIKEL_LEOS = 29016;
|
||||
// private static final int RIBA = 29017;
|
||||
private static final int RIBA_IREN = 29018;
|
||||
|
||||
private static boolean _IsTeleported;
|
||||
private static final List<L2Attackable> MINIONS = new CopyOnWriteArrayList<>();
|
||||
private static L2BossZone ZONE;
|
||||
|
||||
private static final byte ALIVE = 0;
|
||||
private static final byte DEAD = 1;
|
||||
|
||||
private Orfen()
|
||||
{
|
||||
super(Orfen.class.getSimpleName(), "ai/individual");
|
||||
int[] mobs =
|
||||
{
|
||||
ORFEN,
|
||||
RAIKEL_LEOS,
|
||||
RIBA_IREN
|
||||
};
|
||||
registerMobs(mobs);
|
||||
_IsTeleported = false;
|
||||
ZONE = GrandBossManager.getInstance().getZone(POS[0]);
|
||||
StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN);
|
||||
int status = GrandBossManager.getInstance().getBossStatus(ORFEN);
|
||||
if (status == DEAD)
|
||||
{
|
||||
// load the unlock date and time for Orfen from DB
|
||||
long temp = info.getLong("respawn_time") - System.currentTimeMillis();
|
||||
// if Orfen is locked until a certain time, mark it so and start the unlock timer
|
||||
// the unlock time has not yet expired.
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("orfen_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the time has already expired while the server was offline. Immediately spawn Orfen.
|
||||
int i = getRandom(10);
|
||||
Location loc;
|
||||
if (i < 4)
|
||||
{
|
||||
loc = POS[1];
|
||||
}
|
||||
else if (i < 7)
|
||||
{
|
||||
loc = POS[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
loc = POS[3];
|
||||
}
|
||||
L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE);
|
||||
spawnBoss(orfen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int loc_x = info.getInt("loc_x");
|
||||
int loc_y = info.getInt("loc_y");
|
||||
int loc_z = info.getInt("loc_z");
|
||||
int heading = info.getInt("heading");
|
||||
int hp = info.getInt("currentHP");
|
||||
int mp = info.getInt("currentMP");
|
||||
L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
orfen.setCurrentHpMp(hp, mp);
|
||||
spawnBoss(orfen);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSpawnPoint(L2Npc npc, int index)
|
||||
{
|
||||
((L2Attackable) npc).clearAggroList();
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
L2Spawn spawn = npc.getSpawn();
|
||||
spawn.setLocation(POS[index]);
|
||||
npc.teleToLocation(POS[index], false);
|
||||
}
|
||||
|
||||
public void spawnBoss(L2GrandBossInstance npc)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
startQuestTimer("check_orfen_pos", 10000, npc, null, true);
|
||||
// Spawn minions
|
||||
int x = npc.getX();
|
||||
int y = npc.getY();
|
||||
L2Attackable mob;
|
||||
mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x + 100, y + 100, npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
MINIONS.add(mob);
|
||||
mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x + 100, y - 100, npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
MINIONS.add(mob);
|
||||
mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x - 100, y + 100, npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
MINIONS.add(mob);
|
||||
mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x - 100, y - 100, npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
MINIONS.add(mob);
|
||||
startQuestTimer("check_minion_loc", 10000, npc, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("orfen_unlock"))
|
||||
{
|
||||
int i = getRandom(10);
|
||||
Location loc;
|
||||
if (i < 4)
|
||||
{
|
||||
loc = POS[1];
|
||||
}
|
||||
else if (i < 7)
|
||||
{
|
||||
loc = POS[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
loc = POS[3];
|
||||
}
|
||||
L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE);
|
||||
spawnBoss(orfen);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("check_orfen_pos"))
|
||||
{
|
||||
if ((_IsTeleported && (npc.getCurrentHp() > (npc.getMaxHp() * 0.95))) || (!ZONE.isInsideZone(npc) && !_IsTeleported))
|
||||
{
|
||||
setSpawnPoint(npc, getRandom(3) + 1);
|
||||
_IsTeleported = false;
|
||||
}
|
||||
else if (_IsTeleported && !ZONE.isInsideZone(npc))
|
||||
{
|
||||
setSpawnPoint(npc, 0);
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("check_minion_loc"))
|
||||
{
|
||||
for (int i = 0; i < MINIONS.size(); i++)
|
||||
{
|
||||
L2Attackable mob = MINIONS.get(i);
|
||||
if (!npc.isInsideRadius(mob, 3000, false, false))
|
||||
{
|
||||
mob.teleToLocation(npc.getLocation());
|
||||
((L2Attackable) npc).clearAggroList();
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("despawn_minions"))
|
||||
{
|
||||
for (int i = 0; i < MINIONS.size(); i++)
|
||||
{
|
||||
L2Attackable mob = MINIONS.get(i);
|
||||
if (mob != null)
|
||||
{
|
||||
mob.decayMe();
|
||||
}
|
||||
}
|
||||
MINIONS.clear();
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_minion"))
|
||||
{
|
||||
L2Attackable mob = (L2Attackable) addSpawn(RAIKEL_LEOS, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
MINIONS.add(mob);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
|
||||
{
|
||||
if (npc.getId() == ORFEN)
|
||||
{
|
||||
L2Character originalCaster = isSummon ? caster.getServitors().values().stream().findFirst().orElse(caster.getPet()) : caster;
|
||||
if ((skill.getEffectPoint() > 0) && (getRandom(5) == 0) && npc.isInsideRadius(originalCaster, 1000, false, false))
|
||||
{
|
||||
NpcSay packet = new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), TEXT[getRandom(4)]);
|
||||
packet.addStringParameter(caster.getName().toString());
|
||||
npc.broadcastPacket(packet);
|
||||
originalCaster.teleToLocation(npc.getLocation());
|
||||
npc.setTarget(originalCaster);
|
||||
npc.doCast(SkillData.getInstance().getSkill(4064, 1));
|
||||
}
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFactionCall(L2Npc npc, L2Npc caller, L2PcInstance attacker, boolean isSummon)
|
||||
{
|
||||
if ((caller == null) || (npc == null) || npc.isCastingNow())
|
||||
{
|
||||
return super.onFactionCall(npc, caller, attacker, isSummon);
|
||||
}
|
||||
int npcId = npc.getId();
|
||||
int callerId = caller.getId();
|
||||
if ((npcId == RAIKEL_LEOS) && (getRandom(20) == 0))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SkillData.getInstance().getSkill(4067, 4));
|
||||
}
|
||||
else if (npcId == RIBA_IREN)
|
||||
{
|
||||
int chance = 1;
|
||||
if (callerId == ORFEN)
|
||||
{
|
||||
chance = 9;
|
||||
}
|
||||
if ((callerId != RIBA_IREN) && (caller.getCurrentHp() < (caller.getMaxHp() / 2.0)) && (getRandom(10) < chance))
|
||||
{
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
npc.setTarget(caller);
|
||||
npc.doCast(SkillData.getInstance().getSkill(4516, 1));
|
||||
}
|
||||
}
|
||||
return super.onFactionCall(npc, caller, attacker, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
int npcId = npc.getId();
|
||||
if (npcId == ORFEN)
|
||||
{
|
||||
if (!_IsTeleported && ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2)))
|
||||
{
|
||||
_IsTeleported = true;
|
||||
setSpawnPoint(npc, 0);
|
||||
}
|
||||
else if (npc.isInsideRadius(attacker, 1000, false, false) && !npc.isInsideRadius(attacker, 300, false, false) && (getRandom(10) == 0))
|
||||
{
|
||||
NpcSay packet = new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npcId, TEXT[getRandom(3)]);
|
||||
packet.addStringParameter(attacker.getName().toString());
|
||||
npc.broadcastPacket(packet);
|
||||
attacker.teleToLocation(npc.getLocation());
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SkillData.getInstance().getSkill(4064, 1));
|
||||
}
|
||||
}
|
||||
else if (npcId == RIBA_IREN)
|
||||
{
|
||||
if (!npc.isCastingNow() && ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2.0)))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SkillData.getInstance().getSkill(4516, 1));
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (npc.getId() == ORFEN)
|
||||
{
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
GrandBossManager.getInstance().setBossStatus(ORFEN, DEAD);
|
||||
// Calculate Min and Max respawn times randomly.
|
||||
long respawnTime = Config.ORFEN_SPAWN_INTERVAL + getRandom(-Config.ORFEN_SPAWN_RANDOM, Config.ORFEN_SPAWN_RANDOM);
|
||||
respawnTime *= 3600000;
|
||||
startQuestTimer("orfen_unlock", respawnTime, null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN);
|
||||
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(ORFEN, info);
|
||||
cancelQuestTimer("check_minion_loc", npc, null);
|
||||
cancelQuestTimer("check_orfen_pos", npc, null);
|
||||
startQuestTimer("despawn_minions", 20000, null, null);
|
||||
cancelQuestTimers("spawn_minion");
|
||||
}
|
||||
else if ((GrandBossManager.getInstance().getBossStatus(ORFEN) == ALIVE) && (npc.getId() == RAIKEL_LEOS))
|
||||
{
|
||||
MINIONS.remove(npc);
|
||||
startQuestTimer("spawn_minion", 360000, npc, null);
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Orfen();
|
||||
}
|
||||
}
|
410
trunk/dist/game/data_classic/scripts/ai/individual/QueenAnt.java
vendored
Normal file
410
trunk/dist/game/data_classic/scripts/ai/individual/QueenAnt.java
vendored
Normal file
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.Config;
|
||||
import com.l2jserver.gameserver.ThreadPoolManager;
|
||||
import com.l2jserver.gameserver.ai.CtrlIntention;
|
||||
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jserver.gameserver.model.Location;
|
||||
import com.l2jserver.gameserver.model.StatsSet;
|
||||
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.L2Playable;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jserver.gameserver.model.skills.CommonSkill;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
import com.l2jserver.gameserver.model.zone.type.L2BossZone;
|
||||
import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
|
||||
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
|
||||
|
||||
/**
|
||||
* Queen Ant's AI
|
||||
* @author Emperorc
|
||||
*/
|
||||
public final class QueenAnt extends AbstractNpcAI
|
||||
{
|
||||
private static final int QUEEN = 29001;
|
||||
private static final int LARVA = 29002;
|
||||
private static final int NURSE = 29003;
|
||||
private static final int GUARD = 29004;
|
||||
private static final int ROYAL = 29005;
|
||||
|
||||
private static final int[] MOBS =
|
||||
{
|
||||
QUEEN,
|
||||
LARVA,
|
||||
NURSE,
|
||||
GUARD,
|
||||
ROYAL
|
||||
};
|
||||
|
||||
private static final Location OUST_LOC_1 = new Location(-19480, 187344, -5600);
|
||||
private static final Location OUST_LOC_2 = new Location(-17928, 180912, -5520);
|
||||
private static final Location OUST_LOC_3 = new Location(-23808, 182368, -5600);
|
||||
|
||||
private static final int QUEEN_X = -21610;
|
||||
private static final int QUEEN_Y = 181594;
|
||||
private static final int QUEEN_Z = -5734;
|
||||
|
||||
// QUEEN Status Tracking :
|
||||
private static final byte ALIVE = 0; // Queen Ant is spawned.
|
||||
private static final byte DEAD = 1; // Queen Ant has been killed.
|
||||
|
||||
private static L2BossZone _zone;
|
||||
|
||||
private static SkillHolder HEAL1 = new SkillHolder(4020, 1);
|
||||
private static SkillHolder HEAL2 = new SkillHolder(4024, 1);
|
||||
|
||||
L2MonsterInstance _queen = null;
|
||||
private L2MonsterInstance _larva = null;
|
||||
private final List<L2MonsterInstance> _nurses = new CopyOnWriteArrayList<>();
|
||||
ScheduledFuture<?> _task = null;
|
||||
|
||||
private QueenAnt()
|
||||
{
|
||||
super(QueenAnt.class.getSimpleName(), "ai/individual");
|
||||
addSpawnId(MOBS);
|
||||
addKillId(MOBS);
|
||||
addAggroRangeEnterId(MOBS);
|
||||
addFactionCallId(NURSE);
|
||||
|
||||
_zone = GrandBossManager.getInstance().getZone(QUEEN_X, QUEEN_Y, QUEEN_Z);
|
||||
StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
|
||||
int status = GrandBossManager.getInstance().getBossStatus(QUEEN);
|
||||
if (status == DEAD)
|
||||
{
|
||||
// load the unlock date and time for queen ant from DB
|
||||
long temp = info.getLong("respawn_time") - System.currentTimeMillis();
|
||||
// if queen ant is locked until a certain time, mark it so and start the unlock timer
|
||||
// the unlock time has not yet expired.
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("queen_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the time has already expired while the server was offline. Immediately spawn queen ant.
|
||||
L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN, QUEEN_X, QUEEN_Y, QUEEN_Z, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(QUEEN, ALIVE);
|
||||
spawnBoss(queen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int loc_x = QUEEN_X;
|
||||
int loc_y = QUEEN_Y;
|
||||
int loc_z = QUEEN_Z;
|
||||
int heading = info.getInt("heading");
|
||||
int hp = info.getInt("currentHP");
|
||||
int mp = info.getInt("currentMP");
|
||||
|
||||
L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
queen.setCurrentHpMp(hp, mp);
|
||||
spawnBoss(queen);
|
||||
}
|
||||
}
|
||||
|
||||
private void spawnBoss(L2GrandBossInstance npc)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
if (getRandom(100) < 33)
|
||||
{
|
||||
_zone.movePlayersTo(OUST_LOC_1);
|
||||
}
|
||||
else if (getRandom(100) < 50)
|
||||
{
|
||||
_zone.movePlayersTo(OUST_LOC_2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_zone.movePlayersTo(OUST_LOC_3);
|
||||
}
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
startQuestTimer("action", 10000, npc, null, true);
|
||||
startQuestTimer("heal", 1000, null, null, true);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
_queen = npc;
|
||||
_larva = (L2MonsterInstance) addSpawn(LARVA, -21600, 179482, -5846, getRandom(360), false, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("heal"))
|
||||
{
|
||||
boolean notCasting;
|
||||
final boolean larvaNeedHeal = (_larva != null) && (_larva.getCurrentHp() < _larva.getMaxHp());
|
||||
final boolean queenNeedHeal = (_queen != null) && (_queen.getCurrentHp() < _queen.getMaxHp());
|
||||
for (L2MonsterInstance nurse : _nurses)
|
||||
{
|
||||
if ((nurse == null) || nurse.isDead() || nurse.isCastingNow())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
notCasting = nurse.getAI().getIntention() != CtrlIntention.AI_INTENTION_CAST;
|
||||
if (larvaNeedHeal)
|
||||
{
|
||||
if ((nurse.getTarget() != _larva) || notCasting)
|
||||
{
|
||||
nurse.setTarget(_larva);
|
||||
nurse.useMagic(getRandomBoolean() ? HEAL1.getSkill() : HEAL2.getSkill());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (queenNeedHeal)
|
||||
{
|
||||
if (nurse.getLeader() == _larva)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((nurse.getTarget() != _queen) || notCasting)
|
||||
{
|
||||
nurse.setTarget(_queen);
|
||||
nurse.useMagic(HEAL1.getSkill());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// if nurse not casting - remove target
|
||||
if (notCasting && (nurse.getTarget() != null))
|
||||
{
|
||||
nurse.setTarget(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("action") && (npc != null))
|
||||
{
|
||||
if (getRandom(3) == 0)
|
||||
{
|
||||
if (getRandom(2) == 0)
|
||||
{
|
||||
npc.broadcastSocialAction(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.broadcastSocialAction(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("queen_unlock"))
|
||||
{
|
||||
L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN, QUEEN_X, QUEEN_Y, QUEEN_Z, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(QUEEN, ALIVE);
|
||||
spawnBoss(queen);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
final L2MonsterInstance mob = (L2MonsterInstance) npc;
|
||||
switch (npc.getId())
|
||||
{
|
||||
case LARVA:
|
||||
mob.setIsImmobilized(true);
|
||||
mob.setIsMortal(false);
|
||||
mob.setIsRaidMinion(true);
|
||||
break;
|
||||
case NURSE:
|
||||
mob.disableCoreAI(true);
|
||||
mob.setIsRaidMinion(true);
|
||||
_nurses.add(mob);
|
||||
break;
|
||||
case ROYAL:
|
||||
case GUARD:
|
||||
mob.setIsRaidMinion(true);
|
||||
break;
|
||||
case QUEEN:
|
||||
_task = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new QueenAntTask(), 5 * 1000, 5 * 1000);
|
||||
break;
|
||||
}
|
||||
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFactionCall(L2Npc npc, L2Npc caller, L2PcInstance attacker, boolean isSummon)
|
||||
{
|
||||
if ((caller == null) || (npc == null))
|
||||
{
|
||||
return super.onFactionCall(npc, caller, attacker, isSummon);
|
||||
}
|
||||
|
||||
if (!npc.isCastingNow() && (npc.getAI().getIntention() != CtrlIntention.AI_INTENTION_CAST))
|
||||
{
|
||||
if (caller.getCurrentHp() < caller.getMaxHp())
|
||||
{
|
||||
npc.setTarget(caller);
|
||||
((L2Attackable) npc).useMagic(HEAL1.getSkill());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
if ((npc == null) || (player.isGM() && player.isInvisible()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final boolean isMage;
|
||||
final L2Playable character;
|
||||
if (isSummon)
|
||||
{
|
||||
isMage = false;
|
||||
character = player.getServitors().values().stream().findFirst().orElse(player.getPet());
|
||||
}
|
||||
else
|
||||
{
|
||||
isMage = player.isMageClass();
|
||||
character = player;
|
||||
}
|
||||
|
||||
if (character == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!Config.RAID_DISABLE_CURSE && ((character.getLevel() - npc.getLevel()) > 8))
|
||||
{
|
||||
Skill curse = null;
|
||||
if (isMage)
|
||||
{
|
||||
if (!character.isMuted() && (getRandom(4) == 0))
|
||||
{
|
||||
curse = CommonSkill.RAID_CURSE.getSkill();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!character.isParalyzed() && (getRandom(4) == 0))
|
||||
{
|
||||
curse = CommonSkill.RAID_CURSE2.getSkill();
|
||||
}
|
||||
}
|
||||
|
||||
if (curse != null)
|
||||
{
|
||||
npc.broadcastPacket(new MagicSkillUse(npc, character, curse.getId(), curse.getLevel(), 300, 0));
|
||||
curse.applyEffects(npc, character);
|
||||
}
|
||||
|
||||
((L2Attackable) npc).stopHating(character); // for calling again
|
||||
return null;
|
||||
}
|
||||
|
||||
return super.onAggroRangeEnter(npc, player, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
int npcId = npc.getId();
|
||||
if (npcId == QUEEN)
|
||||
{
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
GrandBossManager.getInstance().setBossStatus(QUEEN, DEAD);
|
||||
// Calculate Min and Max respawn times randomly.
|
||||
long respawnTime = Config.QUEEN_ANT_SPAWN_INTERVAL + getRandom(-Config.QUEEN_ANT_SPAWN_RANDOM, Config.QUEEN_ANT_SPAWN_RANDOM);
|
||||
respawnTime *= 3600000;
|
||||
startQuestTimer("queen_unlock", respawnTime, null, null);
|
||||
cancelQuestTimer("action", npc, null);
|
||||
cancelQuestTimer("heal", null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
|
||||
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(QUEEN, info);
|
||||
_nurses.clear();
|
||||
_larva.deleteMe();
|
||||
_larva = null;
|
||||
_queen = null;
|
||||
if (_task != null)
|
||||
{
|
||||
_task.cancel(false);
|
||||
_task = null;
|
||||
}
|
||||
}
|
||||
else if ((_queen != null) && !_queen.isAlikeDead())
|
||||
{
|
||||
if (npcId == ROYAL)
|
||||
{
|
||||
L2MonsterInstance mob = (L2MonsterInstance) npc;
|
||||
if (mob.getLeader() != null)
|
||||
{
|
||||
mob.getLeader().getMinionList().onMinionDie(mob, (280 + getRandom(40)) * 1000);
|
||||
}
|
||||
}
|
||||
else if (npcId == NURSE)
|
||||
{
|
||||
L2MonsterInstance mob = (L2MonsterInstance) npc;
|
||||
_nurses.remove(mob);
|
||||
if (mob.getLeader() != null)
|
||||
{
|
||||
mob.getLeader().getMinionList().onMinionDie(mob, 10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
private class QueenAntTask implements Runnable
|
||||
{
|
||||
public QueenAntTask()
|
||||
{
|
||||
// Constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if ((_queen == null) || _queen.isDead())
|
||||
{
|
||||
_task.cancel(false);
|
||||
_task = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_queen.calculateDistance(QUEEN_X, QUEEN_Y, QUEEN_Z, false, false) > 2000.)
|
||||
{
|
||||
_queen.clearAggroList();
|
||||
_queen.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(QUEEN_X, QUEEN_Y, QUEEN_Z, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new QueenAnt();
|
||||
}
|
||||
}
|
51
trunk/dist/game/data_classic/scripts/ai/individual/RagnaOrcCommander.java
vendored
Normal file
51
trunk/dist/game/data_classic/scripts/ai/individual/RagnaOrcCommander.java
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
|
||||
/**
|
||||
* Ragna Orc Commander AI.
|
||||
* @author Zealar
|
||||
*/
|
||||
public final class RagnaOrcCommander extends AbstractNpcAI
|
||||
{
|
||||
private static final int RAGNA_ORC_COMMANDER = 22694;
|
||||
|
||||
private RagnaOrcCommander()
|
||||
{
|
||||
super(RagnaOrcCommander.class.getSimpleName(), "ai/individual");
|
||||
addSpawnId(RAGNA_ORC_COMMANDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
spawnMinions(npc, "Privates1");
|
||||
spawnMinions(npc, getRandomBoolean() ? "Privates2" : "Privates3");
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new RagnaOrcCommander();
|
||||
}
|
||||
}
|
50
trunk/dist/game/data_classic/scripts/ai/individual/RagnaOrcHero.java
vendored
Normal file
50
trunk/dist/game/data_classic/scripts/ai/individual/RagnaOrcHero.java
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
|
||||
/**
|
||||
* Ragna Orc Hero AI.
|
||||
* @author Zealar
|
||||
*/
|
||||
public final class RagnaOrcHero extends AbstractNpcAI
|
||||
{
|
||||
private static final int RAGNA_ORC_HERO = 22693;
|
||||
|
||||
private RagnaOrcHero()
|
||||
{
|
||||
super(RagnaOrcHero.class.getSimpleName(), "ai/individual");
|
||||
addSpawnId(RAGNA_ORC_HERO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
spawnMinions(npc, getRandom(100) < 70 ? "Privates1" : "Privates2");
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new RagnaOrcHero();
|
||||
}
|
||||
}
|
50
trunk/dist/game/data_classic/scripts/ai/individual/RagnaOrcSeer.java
vendored
Normal file
50
trunk/dist/game/data_classic/scripts/ai/individual/RagnaOrcSeer.java
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
|
||||
/**
|
||||
* Ragna Orc Seer AI.
|
||||
* @author Zealar
|
||||
*/
|
||||
public final class RagnaOrcSeer extends AbstractNpcAI
|
||||
{
|
||||
private static final int RAGNA_ORC_SEER = 22697;
|
||||
|
||||
private RagnaOrcSeer()
|
||||
{
|
||||
super(RagnaOrcSeer.class.getSimpleName(), "ai/individual");
|
||||
addSpawnId(RAGNA_ORC_SEER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
spawnMinions(npc, "Privates" + getRandom(1, 2));
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new RagnaOrcSeer();
|
||||
}
|
||||
}
|
178
trunk/dist/game/data_classic/scripts/ai/individual/SinEater.java
vendored
Normal file
178
trunk/dist/game/data_classic/scripts/ai/individual/SinEater.java
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.L2Summon;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.events.EventType;
|
||||
import com.l2jserver.gameserver.model.events.ListenerRegisterType;
|
||||
import com.l2jserver.gameserver.model.events.annotations.Id;
|
||||
import com.l2jserver.gameserver.model.events.annotations.RegisterEvent;
|
||||
import com.l2jserver.gameserver.model.events.annotations.RegisterType;
|
||||
import com.l2jserver.gameserver.model.events.impl.character.OnCreatureAttacked;
|
||||
import com.l2jserver.gameserver.model.events.impl.character.OnCreatureKill;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
|
||||
|
||||
/**
|
||||
* Sin Eater AI.
|
||||
* @author St3eT.
|
||||
*/
|
||||
public final class SinEater extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int SIN_EATER = 12564;
|
||||
|
||||
private SinEater()
|
||||
{
|
||||
super(SinEater.class.getSimpleName(), "ai/individual");
|
||||
addSummonSpawnId(SIN_EATER);
|
||||
addSummonTalkId(SIN_EATER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equals("TALK") && (player != null) && (player.getPet() != null))
|
||||
{
|
||||
if (getRandom(100) < 30)
|
||||
{
|
||||
final int random = getRandom(100);
|
||||
final L2Summon summon = player.getPet();
|
||||
|
||||
if (random < 20)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.YAWWWWN_IT_S_SO_BORING_HERE_WE_SHOULD_GO_AND_FIND_SOME_ACTION);
|
||||
}
|
||||
else if (random < 40)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.HEY_IF_YOU_CONTINUE_TO_WASTE_TIME_YOU_WILL_NEVER_FINISH_YOUR_PENANCE);
|
||||
}
|
||||
else if (random < 60)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.I_KNOW_YOU_DON_T_LIKE_ME_THE_FEELING_IS_MUTUAL);
|
||||
}
|
||||
else if (random < 80)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.I_NEED_A_DRINK);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.OH_THIS_IS_DRAGGING_ON_TOO_LONG_AT_THIS_RATE_I_WON_T_MAKE_IT_HOME_BEFORE_THE_SEVEN_SEALS_ARE_BROKEN);
|
||||
}
|
||||
}
|
||||
startQuestTimer("TALK", 60000, null, player);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@RegisterEvent(EventType.ON_CREATURE_KILL)
|
||||
@RegisterType(ListenerRegisterType.NPC)
|
||||
@Id(SIN_EATER)
|
||||
public void onCreatureKill(OnCreatureKill event)
|
||||
{
|
||||
final int random = getRandom(100);
|
||||
final L2Summon summon = (L2Summon) event.getTarget();
|
||||
|
||||
if (random < 30)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.OH_THIS_IS_JUST_GREAT_WHAT_ARE_YOU_GOING_TO_DO_NOW);
|
||||
}
|
||||
else if (random < 70)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.YOU_INCONSIDERATE_MORON_CAN_T_YOU_EVEN_TAKE_CARE_OF_LITTLE_OLD_ME);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.OH_NO_THE_MAN_WHO_EATS_ONE_S_SINS_HAS_DIED_PENITENCE_IS_FURTHER_AWAY);
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterEvent(EventType.ON_CREATURE_ATTACKED)
|
||||
@RegisterType(ListenerRegisterType.NPC)
|
||||
@Id(SIN_EATER)
|
||||
public void onCreatureAttacked(OnCreatureAttacked event)
|
||||
{
|
||||
if (getRandom(100) < 30)
|
||||
{
|
||||
final int random = getRandom(100);
|
||||
final L2Summon summon = (L2Summon) event.getTarget();
|
||||
|
||||
if (random < 35)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.OH_THAT_SMARTS);
|
||||
}
|
||||
else if (random < 70)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.HEY_MASTER_PAY_ATTENTION_I_M_DYING_OVER_HERE);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.WHAT_HAVE_I_DONE_TO_DESERVE_THIS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSummonSpawn(L2Summon summon)
|
||||
{
|
||||
broadcastSummonSay(summon, getRandomBoolean() ? NpcStringId.HEY_IT_SEEMS_LIKE_YOU_NEED_MY_HELP_DOESN_T_IT : NpcStringId.ALMOST_GOT_IT_OUCH_STOP_DAMN_THESE_BLOODY_MANACLES);
|
||||
startQuestTimer("TALK", 60000, null, summon.getOwner());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSummonTalk(L2Summon summon)
|
||||
{
|
||||
if (getRandom(100) < 10)
|
||||
{
|
||||
final int random = getRandom(100);
|
||||
|
||||
if (random < 25)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.USING_A_SPECIAL_SKILL_HERE_COULD_TRIGGER_A_BLOODBATH);
|
||||
}
|
||||
else if (random < 50)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.HEY_WHAT_DO_YOU_EXPECT_OF_ME);
|
||||
}
|
||||
else if (random < 75)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.UGGGGGH_PUSH_IT_S_NOT_COMING_OUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.AH_I_MISSED_THE_MARK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcastSummonSay(L2Summon summon, NpcStringId npcstringId)
|
||||
{
|
||||
summon.broadcastPacket(new NpcSay(summon.getObjectId(), ChatType.NPC_GENERAL, summon.getId(), npcstringId));
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new SinEater();
|
||||
}
|
||||
}
|
95
trunk/dist/game/data_classic/scripts/ai/individual/SinWardens.java
vendored
Normal file
95
trunk/dist/game/data_classic/scripts/ai/individual/SinWardens.java
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
|
||||
|
||||
/**
|
||||
* Manages Sin Wardens disappearing and chat.
|
||||
* @author GKR
|
||||
*/
|
||||
public final class SinWardens extends AbstractNpcAI
|
||||
{
|
||||
private static final int[] SIN_WARDEN_MINIONS =
|
||||
{
|
||||
22424,
|
||||
22425,
|
||||
22426,
|
||||
22427,
|
||||
22428,
|
||||
22429,
|
||||
22430,
|
||||
22432,
|
||||
22433,
|
||||
22434,
|
||||
22435,
|
||||
22436,
|
||||
22437,
|
||||
22438
|
||||
};
|
||||
|
||||
private final Map<Integer, Integer> killedMinionsCount = new ConcurrentHashMap<>();
|
||||
|
||||
private SinWardens()
|
||||
{
|
||||
super(SinWardens.class.getSimpleName(), "ai/individual");
|
||||
addKillId(SIN_WARDEN_MINIONS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (npc.isMinion())
|
||||
{
|
||||
final L2MonsterInstance master = ((L2MonsterInstance) npc).getLeader();
|
||||
if ((master != null) && !master.isDead())
|
||||
{
|
||||
int killedCount = killedMinionsCount.containsKey(master.getObjectId()) ? killedMinionsCount.get(master.getObjectId()) : 0;
|
||||
killedCount++;
|
||||
|
||||
if ((killedCount) == 5)
|
||||
{
|
||||
master.broadcastPacket(new NpcSay(master.getObjectId(), ChatType.NPC_GENERAL, master.getId(), NpcStringId.WE_MIGHT_NEED_NEW_SLAVES_I_LL_BE_BACK_SOON_SO_WAIT));
|
||||
master.doDie(killer);
|
||||
killedMinionsCount.remove(master.getObjectId());
|
||||
}
|
||||
else
|
||||
{
|
||||
killedMinionsCount.put(master.getObjectId(), killedCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new SinWardens();
|
||||
}
|
||||
}
|
13
trunk/dist/game/data_classic/scripts/ai/individual/documentation.txt
vendored
Normal file
13
trunk/dist/game/data_classic/scripts/ai/individual/documentation.txt
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
Individual AI:
|
||||
This folder contains AI scripts for single npc templates (one npc ID, but possibly many instances).
|
||||
That is, if a particular NPC/mob has a unique AI or something slightly different from all other generic NPCs,
|
||||
an individual AI script can be created for all occurences of that npc/mob. Such individual scripts ought to be here.
|
||||
|
||||
Individual AI scripts can be subclassed. In other words, an individual may inherit from a group or other individual.
|
||||
For example, one group template might define mobs that cast spells. A particular mob may cast spells but may also
|
||||
talk whenever it gets attacked. In that case, instead of writing all the AI for attacking and casting spells, it may
|
||||
inherit from a group template that defines AI for ALL mobs that cast spells, then add behaviours for talking onAttack.
|
||||
|
||||
"NPC registrations" refers to the addition of NPCs in the various events of the scripts, such as onAttack, onKill, etc
|
||||
Those are done by using keywords such as "addKillId" etc. For more details on registrations, see
|
||||
"scripts/quests/documentation.txt"
|
171
trunk/dist/game/data_classic/scripts/ai/npc/AbstractNpcAI.java
vendored
Normal file
171
trunk/dist/game/data_classic/scripts/ai/npc/AbstractNpcAI.java
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.npc;
|
||||
|
||||
import com.l2jserver.gameserver.enums.ChatType;
|
||||
import com.l2jserver.gameserver.model.actor.L2Character;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.MinionHolder;
|
||||
import com.l2jserver.gameserver.model.quest.Quest;
|
||||
import com.l2jserver.gameserver.network.NpcStringId;
|
||||
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
|
||||
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
|
||||
import com.l2jserver.gameserver.util.Broadcast;
|
||||
|
||||
/**
|
||||
* Abstract NPC AI class for datapack based AIs.
|
||||
* @author UnAfraid, Zoey76
|
||||
*/
|
||||
public abstract class AbstractNpcAI extends Quest
|
||||
{
|
||||
public AbstractNpcAI(String name, String descr)
|
||||
{
|
||||
super(-1, name, descr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple on first talk event handler.
|
||||
*/
|
||||
@Override
|
||||
public String onFirstTalk(L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
return npc.getId() + ".html";
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the following events to the current script:<br>
|
||||
* <ul>
|
||||
* <li>ON_ATTACK</li>
|
||||
* <li>ON_KILL</li>
|
||||
* <li>ON_SPAWN</li>
|
||||
* <li>ON_SPELL_FINISHED</li>
|
||||
* <li>ON_SKILL_SEE</li>
|
||||
* <li>ON_FACTION_CALL</li>
|
||||
* <li>ON_AGGR_RANGE_ENTER</li>
|
||||
* </ul>
|
||||
* @param mobs
|
||||
*/
|
||||
public void registerMobs(int... mobs)
|
||||
{
|
||||
addAttackId(mobs);
|
||||
addKillId(mobs);
|
||||
addSpawnId(mobs);
|
||||
addSpellFinishedId(mobs);
|
||||
addSkillSeeId(mobs);
|
||||
addAggroRangeEnterId(mobs);
|
||||
addFactionCallId(mobs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts NpcSay packet to all known players with custom string.
|
||||
* @param npc
|
||||
* @param type
|
||||
* @param text
|
||||
*/
|
||||
protected void broadcastNpcSay(L2Npc npc, ChatType type, String text)
|
||||
{
|
||||
Broadcast.toKnownPlayers(npc, new NpcSay(npc.getObjectId(), type, npc.getTemplate().getDisplayId(), text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts NpcSay packet to all known players with npc string id.
|
||||
* @param npc
|
||||
* @param type
|
||||
* @param stringId
|
||||
*/
|
||||
protected void broadcastNpcSay(L2Npc npc, ChatType type, NpcStringId stringId)
|
||||
{
|
||||
Broadcast.toKnownPlayers(npc, new NpcSay(npc.getObjectId(), type, npc.getTemplate().getDisplayId(), stringId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts NpcSay packet to all known players with npc string id.
|
||||
* @param npc
|
||||
* @param type
|
||||
* @param stringId
|
||||
* @param parameters
|
||||
*/
|
||||
protected void broadcastNpcSay(L2Npc npc, ChatType type, NpcStringId stringId, String... parameters)
|
||||
{
|
||||
final NpcSay say = new NpcSay(npc.getObjectId(), type, npc.getTemplate().getDisplayId(), stringId);
|
||||
if (parameters != null)
|
||||
{
|
||||
for (String parameter : parameters)
|
||||
{
|
||||
say.addStringParameter(parameter);
|
||||
}
|
||||
}
|
||||
Broadcast.toKnownPlayers(npc, say);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts NpcSay packet to all known players with custom string in specific radius.
|
||||
* @param npc
|
||||
* @param type
|
||||
* @param text
|
||||
* @param radius
|
||||
*/
|
||||
protected void broadcastNpcSay(L2Npc npc, ChatType type, String text, int radius)
|
||||
{
|
||||
Broadcast.toKnownPlayersInRadius(npc, new NpcSay(npc.getObjectId(), type, npc.getTemplate().getDisplayId(), text), radius);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts NpcSay packet to all known players with npc string id in specific radius.
|
||||
* @param npc
|
||||
* @param type
|
||||
* @param stringId
|
||||
* @param radius
|
||||
*/
|
||||
protected void broadcastNpcSay(L2Npc npc, ChatType type, NpcStringId stringId, int radius)
|
||||
{
|
||||
Broadcast.toKnownPlayersInRadius(npc, new NpcSay(npc.getObjectId(), type, npc.getTemplate().getDisplayId(), stringId), radius);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts SocialAction packet to self and known players.
|
||||
* @param character
|
||||
* @param actionId
|
||||
*/
|
||||
protected void broadcastSocialAction(L2Character character, int actionId)
|
||||
{
|
||||
Broadcast.toSelfAndKnownPlayers(character, new SocialAction(character.getObjectId(), actionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts SocialAction packet to self and known players in specific radius.
|
||||
* @param character
|
||||
* @param actionId
|
||||
* @param radius
|
||||
*/
|
||||
protected void broadcastSocialAction(L2Character character, int actionId, int radius)
|
||||
{
|
||||
Broadcast.toSelfAndKnownPlayersInRadius(character, new SocialAction(character.getObjectId(), actionId), radius);
|
||||
}
|
||||
|
||||
public void spawnMinions(final L2Npc npc, final String spawnName)
|
||||
{
|
||||
for (MinionHolder is : npc.getTemplate().getParameters().getMinionList(spawnName))
|
||||
{
|
||||
addMinion((L2MonsterInstance) npc, is.getId());
|
||||
}
|
||||
}
|
||||
}
|
142
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/AdventurersGuide.java
vendored
Normal file
142
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/AdventurersGuide.java
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.npc.AdventurersGuide;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
|
||||
/**
|
||||
* Adventurers Guide AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
public final class AdventurersGuide extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int[] ADVENTURERS_GUIDE =
|
||||
{
|
||||
32327,
|
||||
33454, // Newbie Helper
|
||||
};
|
||||
// Skills
|
||||
private static final SkillHolder BLESS_PROTECTION = new SkillHolder(5182, 1); // Blessing of Protection
|
||||
private static final SkillHolder KNIGHT = new SkillHolder(15648, 1); // Knight's Harmony (Adventurer)
|
||||
private static final SkillHolder WARRIOR = new SkillHolder(15649, 1); // Warrior's Harmony (Adventurer)
|
||||
private static final SkillHolder WIZARD = new SkillHolder(15650, 1); // Wizard's Harmony (Adventurer)
|
||||
private static final SkillHolder[] GROUP_BUFFS =
|
||||
{
|
||||
new SkillHolder(15642, 1), // Horn Melody (Adventurer)
|
||||
new SkillHolder(15643, 1), // Drum Melody (Adventurer)
|
||||
new SkillHolder(15644, 1), // Pipe Organ Melody (Adventurer)
|
||||
new SkillHolder(15645, 1), // Guitar Melody (Adventurer)
|
||||
new SkillHolder(15646, 1), // Harp Melody (Adventurer)
|
||||
new SkillHolder(15647, 1), // Lute Melody (Adventurer)
|
||||
new SkillHolder(15651, 1), // Prevailing Sonata (Adventurer)
|
||||
new SkillHolder(15652, 1), // Daring Sonata (Adventurer)
|
||||
new SkillHolder(15653, 1), // Refreshing Sonata (Adventurer)
|
||||
};
|
||||
|
||||
private AdventurersGuide()
|
||||
{
|
||||
super(AdventurersGuide.class.getSimpleName(), "ai/npc");
|
||||
addStartNpc(ADVENTURERS_GUIDE);
|
||||
addTalkId(ADVENTURERS_GUIDE);
|
||||
addFirstTalkId(ADVENTURERS_GUIDE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
String htmltext = null;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case "guide-01.html":
|
||||
case "guide-02.html":
|
||||
case "guide-03.html":
|
||||
case "guide-04.html":
|
||||
{
|
||||
htmltext = event;
|
||||
break;
|
||||
}
|
||||
case "weakenBreath":
|
||||
{
|
||||
if (player.getShilensBreathDebuffLevel() < 3)
|
||||
{
|
||||
htmltext = "guide-noBreath.html";
|
||||
break;
|
||||
}
|
||||
|
||||
player.setShilensBreathDebuffLevel(2);
|
||||
htmltext = ""; // TODO: Any success html?
|
||||
break;
|
||||
}
|
||||
case "knight":
|
||||
{
|
||||
htmltext = applyBuffs(npc, player, KNIGHT.getSkill());
|
||||
break;
|
||||
}
|
||||
case "warrior":
|
||||
{
|
||||
htmltext = applyBuffs(npc, player, WARRIOR.getSkill());
|
||||
break;
|
||||
}
|
||||
case "wizard":
|
||||
{
|
||||
htmltext = applyBuffs(npc, player, WIZARD.getSkill());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return htmltext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFirstTalk(L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
return "guide.html";
|
||||
}
|
||||
|
||||
private String applyBuffs(L2Npc npc, L2PcInstance player, Skill skill)
|
||||
{
|
||||
if (player.getLevel() > 90)
|
||||
{
|
||||
return "guide-noBuffs.html";
|
||||
}
|
||||
|
||||
for (SkillHolder holder : GROUP_BUFFS)
|
||||
{
|
||||
holder.getSkill().applyEffects(npc, player);
|
||||
}
|
||||
skill.applyEffects(npc, player);
|
||||
|
||||
if ((player.getLevel() < 40) && (player.getClassId().level() <= 1))
|
||||
{
|
||||
BLESS_PROTECTION.getSkill().applyEffects(npc, player);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new AdventurersGuide();
|
||||
}
|
||||
}
|
11
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide-01.html
vendored
Normal file
11
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide-01.html
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<html><body>
|
||||
I can offer you the following buffs, if you're below Lv. 91.<br>
|
||||
Horn Melody / Drum Melody / Pipe Organ Melody<br1>
|
||||
Guitar Melody / Harp Melody / Lute Melody<br1>
|
||||
Prevailing Sonata / Daring Sonata / Refreshing Sonata<br1>
|
||||
You can receive the above buffs as a group.<br>
|
||||
For Knight's Harmony / Warrior's Harmony / Wizard's Harmony, you will have to choose one.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide knight">"I want the Knight's Harmony."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide warrior">"Warrior's Harmony, please."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide wizard">"Wizard's Harmony, of course!"</Button>
|
||||
</body></html>
|
6
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide-02.html
vendored
Normal file
6
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide-02.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Adventurers' Guide:<br>
|
||||
The Steel Door Guild tops all Dwarven guilds in power and prestige. As such, it is our duty to aid adventurers who work to restore peace unto this war-torn land. We will be happy to offer special assistance if you have Steel Door Guild Coins.<br>
|
||||
Well?<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide guide-03.html">"How do I use Steel Door Guild Coins?"</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide guide-04.html">"Here, I have some Steel Door Guild Coins..."</Button>
|
||||
</body></html>
|
5
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide-03.html
vendored
Normal file
5
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide-03.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Adventurers' Guide:<br>
|
||||
You can use Steel Door Guild Coins to purchase <font color="LEVEL">weapons, armor, and accessories of each grade</font>. These items may be restricted in terms of augmentations or attribute options, but they will be more than enough to help you on your journey.<br>
|
||||
Once you outgrow the equipment, <font color="LEVEL">you can trade them back for Steel Door Guild Coins again</font>! You can also invest in the Aden Reconstruction project if it suits your fancy, or even gamble. Don't forget that Steel Weapon Packs and Steel Armor Packs have a chance of yielding Requiem, Apocalypse, or Specter equipment!<br>
|
||||
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h npc_%objectId%_Quest AdventurersGuide guide-02.html">Back</Button>
|
||||
</body></html>
|
14
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide-04.html
vendored
Normal file
14
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide-04.html
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<html><body>Adventurers' Guide:<br>
|
||||
You can use Steel Door Guild Coins to receive equipment, and trade them back for coins again. Just remember, <font color="LEVEL">you cannot bring us junk to exchange for coins!</font><br>
|
||||
So, what would you like to do?<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 893">"I'd like a weapon or a shield / Sigil."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 894">"I want to buy a top."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 895">"I am looking for some pants."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 896">"Do you have any good helmets?"</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 897">"Gloves would be nice."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 898">"Give me the best boots you got."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 899">"Can I take a look at your necklaces?"</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 900">"I'm up for a ring..."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 901">"I want some earrings."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_exc_multisell 903">"I want to return my Steel equipment."</Button>
|
||||
</body></html>
|
4
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide-noBreath.html
vendored
Normal file
4
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide-noBreath.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Adventurers' Guide<br>
|
||||
I can only weaken Shilen's Breath Lv. 3 or above.<br>
|
||||
There is nothing I can do for you.
|
||||
</body></html>
|
3
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide-noBuffs.html
vendored
Normal file
3
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide-noBuffs.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>
|
||||
Characters who are Lv. 91 or above cannot receive Newbie Buffs.
|
||||
</body></html>
|
9
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide.html
vendored
Normal file
9
trunk/dist/game/data_classic/scripts/ai/npc/AdventurersGuide/guide.html
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<html><body>Adventurers' Guide:<br>
|
||||
Greetings, traveler! How may I be of assistance?<br>
|
||||
My job is to offer what little assistance I can as you charge into all this endless evil and intense fighting!<br>
|
||||
Even now, the monster attacks on this village grow stronger each day; it is only due to your tireless efforts that we have remained safe this long.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide guide-01.html"><font color="LEVEL">"Can I see the list of available buffs?"</font></Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide guide-02.html">"Here, I have some Steel Door Guild Coins..."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide weakenBreath">"I heard you could weaken Shilen's Breath Lv.3 or above."</Button>
|
||||
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
|
||||
</body></html>
|
9
trunk/dist/game/data_classic/scripts/ai/npc/Alexandria/30098-02.html
vendored
Normal file
9
trunk/dist/game/data_classic/scripts/ai/npc/Alexandria/30098-02.html
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<html><body>Trader Alexandria:<br><br>
|
||||
Ah, you have excellent taste! This bracelet is truly unique. In fact, it is said that it contains an <font color="LEVEL">Agathion</font>. Quite a find, eh? Wondering if it is for sale? Of course it is -- that's why I'm here!<br>
|
||||
Both this <font color="LEVEL">Little Angel Agathion Bracelet</font> and this <font color="LEVEL">Little Devil Agathion Bracelet</font> were discovered by another group of adventurers while exploring some ancient ruins. I am positive that they contain Agathions! Of course, no one knows for sure the power an Agathion possesses or how long it lasts. I have been reluctant to experiment on them because it's clear that some of the bracelets possess only limited magic power.<br>
|
||||
Others have more, however. What you get depends on your luck, I'm afraid.<br>
|
||||
To get either the angel or devil bracelet, you must bring me <font color="LEVEL">10 Fish Bones</font>, <font color="LEVEL">10 Fish Scales</font>, <font color="LEVEL">10 units of Fish Oil</font>, <font color="LEVEL">10 Fish Fins</font>, <font color="LEVEL">10 Fish Gems</font>, <font color="LEVEL">5 units of Whale Blubber</font>, and <font color="LEVEL">3,000,000 Adena</font>. I wish I could part with them in exchange for crystals as I normally would, but the adventurers who delivered the bracelets here insisted on these other items for payment.<br>
|
||||
Even so, I still believe this is a reasonable price. After all, an Agathion isn't something you run across every day, eh? So, would you like to buy one?<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alexandria littleAngel">Purchase the Little Angel Agathion Bracelet</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alexandria littleDevil">Purchase the Little Devil Agathion Bracelet</Button>
|
||||
</body></html>
|
4
trunk/dist/game/data_classic/scripts/ai/npc/Alexandria/30098-03.html
vendored
Normal file
4
trunk/dist/game/data_classic/scripts/ai/npc/Alexandria/30098-03.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Trader Alexandria:<br>
|
||||
Yes, I've checked the necessary items. Thank you for your hard work.<br>
|
||||
I'm telling you ahead that I don't know for sure what kind of power each bracelet has. I only can tell you that the angel-engraved bracelet has an angel-type Agathion, and the devil-engraved one has a devil-type Agathion. You can find out the capability and magic power of each Agathion on your own.
|
||||
</body></html>
|
6
trunk/dist/game/data_classic/scripts/ai/npc/Alexandria/30098-03a.html
vendored
Normal file
6
trunk/dist/game/data_classic/scripts/ai/npc/Alexandria/30098-03a.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Trader Alexandria:<br>
|
||||
Yes, I checked the necessary items. It must have been difficult to obtain them all!<br>
|
||||
I must warn you that I do not know for sure what kind of power posessed by each bracelet. I only can tell you that the Angel's Bracelet contains an angel-type Agathion, while the Devil's Bracelet contains a devil-type Agathion. You must discover the capability and magic power of each on your own.<br>
|
||||
Here, please take this as an extra token of my appreciation for your business...<br>
|
||||
(I have a strange feeling about that bracelet -- I hope this adventurer will simply take this and leave here immediately.)
|
||||
</body></html>
|
3
trunk/dist/game/data_classic/scripts/ai/npc/Alexandria/30098-04.html
vendored
Normal file
3
trunk/dist/game/data_classic/scripts/ai/npc/Alexandria/30098-04.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Trader Alexandria:<br>
|
||||
Oh, you don't have the items required to buy either the Angel's Bracelet or the Devil's Bracelet. In order to obtain one, you must first bring me <font color="LEVEL">25 Big Red Nimble Fish</font>, <font color="LEVEL">50 Great Codrans</font>, and <font color="LEVEL">4 Memento Moris, 5 Earth Eggs, 5 Nonliving Nuclei, 3 Dragon Hearts</font>, and <font color="LEVEL">7,500,000 Adena</font>.
|
||||
</body></html>
|
9
trunk/dist/game/data_classic/scripts/ai/npc/Alexandria/30098.html
vendored
Normal file
9
trunk/dist/game/data_classic/scripts/ai/npc/Alexandria/30098.html
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<html><body>Trader Alexandria:<br>
|
||||
Welcome! Thank you so much for visiting our boutique. We sell precious and valuable things that you would never find anywhere else. We've also added some luxury accessories this time. Look around see if you can find anything you like.<br>
|
||||
Ah! Now, you can use <font color="LEVEL">Adena</font> to pay for your goods.<br>
|
||||
If you would like to purchase a weapon, please ask my husband.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 300984001">Purchase Armor</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 300984002">Purchase supplies</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alexandria 30098-02.html">Purchase an Agathion Bracelet</Button>
|
||||
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
|
||||
</body></html>
|
147
trunk/dist/game/data_classic/scripts/ai/npc/Alexandria/Alexandria.java
vendored
Normal file
147
trunk/dist/game/data_classic/scripts/ai/npc/Alexandria/Alexandria.java
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.npc.Alexandria;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.ItemHolder;
|
||||
import com.l2jserver.gameserver.model.holders.QuestItemHolder;
|
||||
|
||||
/**
|
||||
* Alexandria (Armor Merchant) AI.
|
||||
* @author xban1x
|
||||
*/
|
||||
public final class Alexandria extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int ALEXANDRIA = 30098;
|
||||
// Items
|
||||
private static final ItemHolder[] REQUIRED_ITEMS = new ItemHolder[]
|
||||
{
|
||||
new ItemHolder(57, 3550000),
|
||||
new ItemHolder(5094, 400),
|
||||
new ItemHolder(6471, 200),
|
||||
new ItemHolder(9814, 40),
|
||||
new ItemHolder(9815, 30),
|
||||
new ItemHolder(9816, 50),
|
||||
new ItemHolder(9817, 50),
|
||||
};
|
||||
// Agathions
|
||||
private static final QuestItemHolder[] LITTLE_DEVILS = new QuestItemHolder[]
|
||||
{
|
||||
new AdditionalQuestItemHolder(10321, 600, 1, 10408),
|
||||
new QuestItemHolder(10322, 10),
|
||||
new QuestItemHolder(10323, 10),
|
||||
new QuestItemHolder(10324, 5),
|
||||
new QuestItemHolder(10325, 5),
|
||||
new QuestItemHolder(10326, 370),
|
||||
};
|
||||
private static final QuestItemHolder[] LITTLE_ANGELS = new QuestItemHolder[]
|
||||
{
|
||||
new AdditionalQuestItemHolder(10315, 600, 1, 10408),
|
||||
new QuestItemHolder(10316, 10),
|
||||
new QuestItemHolder(10317, 10),
|
||||
new QuestItemHolder(10318, 5),
|
||||
new QuestItemHolder(10319, 5),
|
||||
new QuestItemHolder(10320, 370),
|
||||
};
|
||||
private static final Map<String, List<QuestItemHolder>> AGATHIONS = new HashMap<>();
|
||||
static
|
||||
{
|
||||
AGATHIONS.put("littleAngel", Arrays.asList(LITTLE_ANGELS));
|
||||
AGATHIONS.put("littleDevil", Arrays.asList(LITTLE_DEVILS));
|
||||
}
|
||||
|
||||
private Alexandria()
|
||||
{
|
||||
super(Alexandria.class.getSimpleName(), "ai/npc");
|
||||
addStartNpc(ALEXANDRIA);
|
||||
addTalkId(ALEXANDRIA);
|
||||
addFirstTalkId(ALEXANDRIA);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
String htmltext = null;
|
||||
if (event.equals("30098-02.html"))
|
||||
{
|
||||
htmltext = event;
|
||||
}
|
||||
else if (AGATHIONS.containsKey(event))
|
||||
{
|
||||
final int chance = getRandom(1000);
|
||||
int chance2 = 0;
|
||||
int chance3 = 0;
|
||||
for (QuestItemHolder agathion : AGATHIONS.get(event))
|
||||
{
|
||||
chance3 += agathion.getChance();
|
||||
if ((chance >= chance2) && (chance2 < chance3))
|
||||
{
|
||||
if (takeAllItems(player, REQUIRED_ITEMS))
|
||||
{
|
||||
giveItems(player, agathion);
|
||||
htmltext = "30098-03.html";
|
||||
|
||||
if (agathion instanceof AdditionalQuestItemHolder)
|
||||
{
|
||||
giveItems(player, ((AdditionalQuestItemHolder) agathion).getAdditionalId(), 1);
|
||||
htmltext = "30098-03a.html";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
htmltext = "30098-04.html";
|
||||
}
|
||||
break;
|
||||
}
|
||||
chance2 += agathion.getChance();
|
||||
}
|
||||
}
|
||||
return htmltext;
|
||||
}
|
||||
|
||||
public static class AdditionalQuestItemHolder extends QuestItemHolder
|
||||
{
|
||||
private final int _additionalId;
|
||||
|
||||
public AdditionalQuestItemHolder(int id, int chance, long count, int additionalId)
|
||||
{
|
||||
super(id, chance, count);
|
||||
_additionalId = additionalId;
|
||||
}
|
||||
|
||||
public int getAdditionalId()
|
||||
{
|
||||
return _additionalId;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Alexandria();
|
||||
}
|
||||
}
|
10
trunk/dist/game/data_classic/scripts/ai/npc/ArenaManager/31225.html
vendored
Normal file
10
trunk/dist/game/data_classic/scripts/ai/npc/ArenaManager/31225.html
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<html><body>Arena Manager:<br>
|
||||
Way to go! Hooray! Hooray!!!<br>
|
||||
(Be careful! CP/HP will not get recovered inside the fence.)<br><br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest ArenaManager CPrecovery">CP Recovery : 1,000 Adena</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest ArenaManager HPrecovery">HP Recovery : 1,000 Adena</Button><br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest ArenaManager Buff">Buff for Battle Ground : 2,000 Adena</Button><br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_DepositP">Private Warehouse: Deposit an item.</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_WithdrawP">Private Warehouse: Withdraw an item.</Button><br>
|
||||
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
|
||||
</body></html>
|
9
trunk/dist/game/data_classic/scripts/ai/npc/ArenaManager/31226.html
vendored
Normal file
9
trunk/dist/game/data_classic/scripts/ai/npc/ArenaManager/31226.html
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<html><body>Arena Director:<br>
|
||||
Play the game according to the rules! The loser should be silent! What? Unfair? Then, why don't you hold your tongue and give it another try!<br><br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest ArenaManager CPrecovery">CP Recovery : 1,000 Adena</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest ArenaManager HPrecovery">HP Recovery : 1,000 Adena</Button><br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest ArenaManager Buff">Buff for Battle Ground : 2,000 Adena</Button><br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_DepositP">Private Warehouse: Deposit an item.</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_WithdrawP">Private Warehouse: Withdraw an item.</Button><br>
|
||||
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
|
||||
</body></html>
|
141
trunk/dist/game/data_classic/scripts/ai/npc/ArenaManager/ArenaManager.java
vendored
Normal file
141
trunk/dist/game/data_classic/scripts/ai/npc/ArenaManager/ArenaManager.java
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.npc.ArenaManager;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jserver.gameserver.model.itemcontainer.Inventory;
|
||||
import com.l2jserver.gameserver.model.zone.ZoneId;
|
||||
import com.l2jserver.gameserver.network.SystemMessageId;
|
||||
|
||||
/**
|
||||
* Arena Manager AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
public final class ArenaManager extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int[] ARENA_MANAGER =
|
||||
{
|
||||
31226, // Arena Director (MDT)
|
||||
31225, // Arena Manager (Coliseum)
|
||||
};
|
||||
// Skill
|
||||
private static final SkillHolder[] BUFFS =
|
||||
{
|
||||
new SkillHolder(6805, 1), // Arena Empower
|
||||
new SkillHolder(6806, 1), // Arena Acumen
|
||||
new SkillHolder(6807, 1), // Arena Concentration
|
||||
new SkillHolder(6808, 1), // Arena Might
|
||||
new SkillHolder(6804, 1), // Arena Wind Walk
|
||||
new SkillHolder(6812, 1), // Arena Berserker Spirit
|
||||
};
|
||||
private static final SkillHolder CP_RECOVERY = new SkillHolder(4380, 1); // Arena: CP Recovery
|
||||
private static final SkillHolder HP_RECOVERY = new SkillHolder(6817, 1); // Arena HP Recovery
|
||||
// Misc
|
||||
private static final int CP_COST = 1000;
|
||||
private static final int HP_COST = 1000;
|
||||
private static final int BUFF_COST = 2000;
|
||||
|
||||
private ArenaManager()
|
||||
{
|
||||
super(ArenaManager.class.getSimpleName(), "ai/npc");
|
||||
addStartNpc(ARENA_MANAGER);
|
||||
addTalkId(ARENA_MANAGER);
|
||||
addFirstTalkId(ARENA_MANAGER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "CPrecovery":
|
||||
{
|
||||
if (player.getAdena() >= CP_COST)
|
||||
{
|
||||
takeItems(player, Inventory.ADENA_ID, CP_COST);
|
||||
startQuestTimer("CPrecovery_delay", 2000, npc, player);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "CPrecovery_delay":
|
||||
{
|
||||
if ((player != null) && !player.isInsideZone(ZoneId.PVP))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(CP_RECOVERY.getSkill());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "HPrecovery":
|
||||
{
|
||||
if (player.getAdena() >= HP_COST)
|
||||
{
|
||||
takeItems(player, Inventory.ADENA_ID, HP_COST);
|
||||
startQuestTimer("HPrecovery_delay", 2000, npc, player);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "HPrecovery_delay":
|
||||
{
|
||||
if ((player != null) && !player.isInsideZone(ZoneId.PVP))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(HP_RECOVERY.getSkill());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Buff":
|
||||
{
|
||||
if (player.getAdena() >= BUFF_COST)
|
||||
{
|
||||
takeItems(player, Inventory.ADENA_ID, BUFF_COST);
|
||||
npc.setTarget(player);
|
||||
for (SkillHolder skill : BUFFS)
|
||||
{
|
||||
npc.doCast(skill.getSkill());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new ArenaManager();
|
||||
}
|
||||
}
|
9
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-01.html
vendored
Normal file
9
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-01.html
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
I am Avant-Garde, the Transformation Wizard. I have long wandered through the land and only recently settled here.<br>
|
||||
In fact, my young friend, I am not a wizard of the Ivory Tower. You look surprised! Heh. Think of me as a wanderer who acquired a special power quite by chance... My magic, however, requires some very specialized items.<br>
|
||||
If you have acquired these unique items from the dark wizard in Hardin's Academy, then perhaps I can help you.<br>
|
||||
<a action="bypass -h Quest AvantGarde 32323-02.html">Ask about transformation.</a><br>
|
||||
<a action="bypass -h Quest AvantGarde LearnTransformationSkill">Learn transformation.</a><br>
|
||||
<a action="bypass -h Quest AvantGarde BuyTransformationItems">Purchase items related to transformation.</a><br>
|
||||
<a action="bypass -h npc_%objectId%_Quest">Quest.</a>
|
||||
</body></html>
|
7
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-02.html
vendored
Normal file
7
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-02.html
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<html><body>Wizard of Trasformation Avant-Garde:<br>
|
||||
What do you wish to know about transformation?<br>
|
||||
<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest AvantGarde 32323-02a.html">"What do I need to know about transformation?"</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest AvantGarde 32323-02b.html">"What do I need to do to transform into another shape?"</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest AvantGarde 32323-02c.html">"What do I need to know before transformation?"</Button>
|
||||
</body></html>
|
7
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-02a.html
vendored
Normal file
7
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-02a.html
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
To learn the magic of transformation, you will need to receive special training.<br>
|
||||
Find the Wizard of Darkness, who lives at Hardin's Academy. He will open the path to transformation.<br>
|
||||
You must have reached at least <font color="LEVEL">level 50 </font> to embark on this path.<br>
|
||||
You will also need a special seal. I do not know how you can obtain it, but without it transformation is impossible.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest AvantGarde 32323-02.html">Back.</Button>
|
||||
</body></html>
|
5
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-02b.html
vendored
Normal file
5
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-02b.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
After you have been guided through the process of transformation by a wizard, you may transform yourself into another shape by bringing a transform sealbook to me.<br>
|
||||
Know that it is no easy task to earn one. I have heard, however, that you may find one through the Marketeer of Mammon or the Adventure Guild.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest AvantGarde 32323-02.html">Back.</Button>
|
||||
</body></html>
|
5
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-02c.html
vendored
Normal file
5
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-02c.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
You must remember that once you have been transformed, you must not go into <font color="LEVEL">deep water</font>. Once you have reverted to your original form, your soul will need time to recover -- you will not be able to transform again for some time. Understand?<br>
|
||||
Other than that... Each individual soul contains its own <font color="LEVEL">unique character</font>. If you transform into something that matches that character, you may earn some benefits. Think of it as wearing a suit of clothes that fit you perfectly. Every race has its own respective "figure," so I advise you to do a little research about what kind of transformation would fit you best.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest AvantGarde 32323-02.html">Back.</Button>
|
||||
</body></html>
|
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-03.html
vendored
Normal file
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-03.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
This is not a path for every one. It is meaningless for me to even teach you Transformation until you have proven your ability.<br>
|
||||
Meet the great wizard who uses black magic, open the road of Transformation, and then return to me.
|
||||
</body></html>
|
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-04.html
vendored
Normal file
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-04.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
You must be able to transform in order to buy transformation-related goods.<br>
|
||||
Find a great wizard who wields black magic and can open the path to transformation for you. Then you may return here.
|
||||
</body></html>
|
10
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-05.html
vendored
Normal file
10
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-05.html
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
If your subclass skill is above a certain level, you can transfer that power to your main class.<br>
|
||||
Because this is a very dangerous mission, however, you must be certified in order to carry it out.<br>
|
||||
If you were certified by your subclass master and have brought the certificate, I will transfer some of your subclass power to your main class.<br>
|
||||
Be warned: this will inflict a serious shock to your soul. You must strengthen it in preparation for this rite.<br>
|
||||
In order to learn certified subclass skills, you must first speak to Hardin and obtain the first sealbook. Hardin's Academy is in Dragon Valley.<br>
|
||||
Do you wish to proceed?<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest AvantGarde LearnSubClassSkill">Learn skills.</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest AvantGarde 32323-06.html">Return.</Button>
|
||||
</body></html>
|
5
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-05a.html
vendored
Normal file
5
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-05a.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
What do you wish to know about subclass certification?<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest AvantGarde 32323-05.html">Learn skills of the certified subclass.</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest AvantGarde 32323-05no.html">Certification removal.</Button>
|
||||
</body></html>
|
7
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-05no.html
vendored
Normal file
7
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-05no.html
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
It is a tremendous endeavor to obtain subclass certification and learn the appropriate skills. Beyond the purely physical effort, the burden on your soul is beyond your imagination... It is almost a suicidal venture.<br>
|
||||
However, the process can be undone. There is a special kind of herb that can be used to remove your previously chosen skills. The price of the herb, though, is approximately <font color="LEVEL">10 million Adena</font>... I have the herb here, so I can cancel the certification anytime once you have paid.<br>
|
||||
If the certification is canceled, <font color="LEVEL">the current certification status and skills will vanish immediately -- poof!</font> Now then, do you really wish to cancel certification?<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest AvantGarde CancelCertification">Cancel certification.</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest AvantGarde 32323-06no.html">Return.</Button>
|
||||
</body></html>
|
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-06.html
vendored
Normal file
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-06.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
If you want to give up, I cannot help you.<br>
|
||||
To use the subclass power in the main class requires a great deal of power, after all.
|
||||
</body></html>
|
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-06no.html
vendored
Normal file
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-06no.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
An excellent decision, I think. In fact, it is very difficult to even get the herb. Since there's no one except that vicious Dark Wizard who lives in Dragon Valley who knows the technique, I didn't feel like it either...<br>
|
||||
But isn't it a pity to throw away all of the skills for which you have already been certified?
|
||||
</body></html>
|
5
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-07.html
vendored
Normal file
5
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-07.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Transformation Wizard Avant-garde:<br>
|
||||
A great deal of soul energy is needed to transfer subclass powers to the main class. Although you vanquished the Bridle of Soul by Mimir's Elixir, it is not so easy to practice it.<br>
|
||||
To utilize the subclass power, you must be ritually cleansed by both the <font color="LEVEL">Dark Wizard and Mimir's Elixir</font>. Visit the Dark Wizard inside the Dragon Valley to obtain the magic power of transformation.<br>
|
||||
Once you have learned the magic power of transformation, <font color="LEVEL">visit a subclass master</font> in order to certify your ability. Then come back to me on your main class.
|
||||
</body></html>
|
3
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-08.html
vendored
Normal file
3
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-08.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
To transfer the sub-class power, <font color="LEVEL">make your current class your main class and bring me either a certificate or a Scroll of Transformation</font>.
|
||||
</body></html>
|
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-08no.html
vendored
Normal file
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-08no.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
As I just told you, you need 10 million Adena.<br>
|
||||
I don't see that much money on you...
|
||||
</body></html>
|
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-09no.html
vendored
Normal file
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-09no.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
Then I have no choice...<br>
|
||||
Your certifications are all canceled in exchange for <font color="LEVEL">10 million Adena</font>. However, that does not change the fact that you are very skilled. Why don't you find another master and obtain the certification you want?
|
||||
</body></html>
|
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-10no.html
vendored
Normal file
4
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/32323-10no.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Transformation Wizard Avant-Garde:<br>
|
||||
What are you going to cancel? You have neither certification nor the related skills.<br>
|
||||
This herb is very rare -- unless you really need it, I would rather not use it.
|
||||
</body></html>
|
158
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/AvantGarde.java
vendored
Normal file
158
trunk/dist/game/data_classic/scripts/ai/npc/AvantGarde/AvantGarde.java
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.npc.AvantGarde;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.data.xml.impl.MultisellData;
|
||||
import com.l2jserver.gameserver.data.xml.impl.SkillTreesData;
|
||||
import com.l2jserver.gameserver.model.L2SkillLearn;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.base.AcquireSkillType;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
import com.l2jserver.gameserver.network.SystemMessageId;
|
||||
import com.l2jserver.gameserver.network.clientpackets.RequestAcquireSkill;
|
||||
import com.l2jserver.gameserver.network.serverpackets.ExAcquirableSkillListByClass;
|
||||
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
|
||||
|
||||
/**
|
||||
* Avant-Garde AI.<br>
|
||||
* Sub-Class Certification system, skill learning and certification canceling.<br>
|
||||
* Transformation skill learning and transformation scroll sell.
|
||||
* @author Zoey76
|
||||
*/
|
||||
public final class AvantGarde extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int AVANT_GARDE = 32323;
|
||||
|
||||
public AvantGarde()
|
||||
{
|
||||
super(AvantGarde.class.getSimpleName(), "ai/npc");
|
||||
addStartNpc(AVANT_GARDE);
|
||||
addTalkId(AVANT_GARDE);
|
||||
addFirstTalkId(AVANT_GARDE);
|
||||
addAcquireSkillId(AVANT_GARDE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAcquireSkill(L2Npc npc, L2PcInstance player, Skill skill, AcquireSkillType type)
|
||||
{
|
||||
if (type.equals(AcquireSkillType.TRANSFORM))
|
||||
{
|
||||
showTransformSkillList(player);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
String htmltext = null;
|
||||
switch (event)
|
||||
{
|
||||
case "32323-02.html":
|
||||
case "32323-02a.html":
|
||||
case "32323-02b.html":
|
||||
case "32323-02c.html":
|
||||
case "32323-05.html":
|
||||
case "32323-05no.html":
|
||||
case "32323-06.html":
|
||||
case "32323-06no.html":
|
||||
{
|
||||
htmltext = event;
|
||||
break;
|
||||
}
|
||||
case "LearnTransformationSkill":
|
||||
{
|
||||
if (RequestAcquireSkill.canTransform(player))
|
||||
{
|
||||
showTransformSkillList(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
htmltext = "32323-03.html";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "BuyTransformationItems":
|
||||
{
|
||||
if (RequestAcquireSkill.canTransform(player))
|
||||
{
|
||||
MultisellData.getInstance().separateAndSend(32323001, player, npc, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
htmltext = "32323-04.html";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return htmltext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFirstTalk(L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
return "32323-01.html";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onTalk(L2Npc npc, L2PcInstance talker)
|
||||
{
|
||||
return "32323-01.html";
|
||||
}
|
||||
|
||||
/**
|
||||
* This displays Transformation Skill List to the player.
|
||||
* @param player the active character.
|
||||
*/
|
||||
public static void showTransformSkillList(L2PcInstance player)
|
||||
{
|
||||
final List<L2SkillLearn> skills = SkillTreesData.getInstance().getAvailableTransformSkills(player);
|
||||
|
||||
if (skills.isEmpty())
|
||||
{
|
||||
final int minlevel = SkillTreesData.getInstance().getMinLevelForNewSkill(player, SkillTreesData.getInstance().getTransformSkillTree());
|
||||
if (minlevel > 0)
|
||||
{
|
||||
// No more skills to learn, come back when you level.
|
||||
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_DO_NOT_HAVE_ANY_FURTHER_SKILLS_TO_LEARN_COME_BACK_WHEN_YOU_HAVE_REACHED_LEVEL_S1);
|
||||
sm.addInt(minlevel);
|
||||
player.sendPacket(sm);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendPacket(SystemMessageId.THERE_ARE_NO_OTHER_SKILLS_TO_LEARN);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendPacket(new ExAcquirableSkillListByClass(skills, AcquireSkillType.TRANSFORM));
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new AvantGarde();
|
||||
}
|
||||
}
|
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-01.html
vendored
Normal file
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-01.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Black Judge:<br>
|
||||
Death leaves a scar which all must bear.<br>
|
||||
Do you wish it to be healed completely?<br>
|
||||
Ah, I perceive that you have long been apart from this world. I am strangely heartened by your return. I will heal this wound and remove death's scar.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BlackJudge remove_dp">Remove 1 level of Death Penalty (3600 Adena).</Button>
|
||||
</body></html>
|
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-02.html
vendored
Normal file
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-02.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Black Judge:<br>
|
||||
Death leaves a scar which all must bear.<br>
|
||||
Do you wish it to be healed completely?<br>
|
||||
You have only recently begun your journey in this world, and your youth touches me. I will heal this wound and remove death's scar.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BlackJudge remove_dp">Remove 1 level of Death Penalty (8640 Adena)</Button>
|
||||
</body></html>
|
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-03.html
vendored
Normal file
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-03.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Black Judge:<br>
|
||||
Death leaves a scar which all must bear.<br>
|
||||
Do you wish it to be healed completely?<br>
|
||||
You have only begun to learn the world, and your innocence touches me. I will heal this wound and remove death's scar.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BlackJudge remove_dp">Remove 1 level of Death Penalty (25200 Adena).</Button>
|
||||
</body></html>
|
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-04.html
vendored
Normal file
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-04.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Black Judge:<br>
|
||||
Death leaves a scar which all must bear.<br>
|
||||
Do you wish it to be healed completely?<br>
|
||||
As I see you are a true adventurer, I will heal this wound and remove death's scar.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BlackJudge remove_dp">Remove 1 level of Death Penalty (50400 Adena).</Button>
|
||||
</body></html>
|
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-05.html
vendored
Normal file
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-05.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Black Judge:<br>
|
||||
Death leaves a scar which all must bear.<br>
|
||||
Do you wish it to be healed completely?<br>
|
||||
Great adventurer, I will heal this wound and remove death's scar.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BlackJudge remove_dp">Remove 1 level of Death Penalty (86400 Adena)</Button>
|
||||
</body></html>
|
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-06.html
vendored
Normal file
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-06.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Black Judge:<br>
|
||||
Death leaves a scar which all must bear.<br>
|
||||
Do you wish it to be healed completely?<br>
|
||||
Because you walk the hero's path, I will heal this wound and remove death's scar.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BlackJudge remove_dp">Remove 1 level of Death Penalty (144000 Adena).</Button>
|
||||
</body></html>
|
3
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-07.html
vendored
Normal file
3
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-07.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Black Judge:<br>
|
||||
The wound you have received from death's touch is too deep to be healed for the money you have to give me. Find more money if you wish death's mark to be fully removed from you.
|
||||
</body></html>
|
4
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-08.html
vendored
Normal file
4
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981-08.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Black Judge:<br>
|
||||
You have no more death wounds that require healing.<br>
|
||||
Go forth and fight, both for this world and your own glory.
|
||||
</body></html>
|
5
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981.html
vendored
Normal file
5
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/30981.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Black Judge:<br>
|
||||
I came to this land to save those poor souls who are contaminated by sin. We black judges do not divide good and evil by light and darkness. We help instead those with strong wills and noble souls -- whether or not they wish our help. Come, sinners, come to us . . .<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BlackJudge remove_info">Remove Death Penalties.</Button>
|
||||
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
|
||||
</body></html>
|
118
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/BlackJudge.java
vendored
Normal file
118
trunk/dist/game/data_classic/scripts/ai/npc/BlackJudge/BlackJudge.java
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.npc.BlackJudge;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.datatables.SkillData;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.itemcontainer.Inventory;
|
||||
import com.l2jserver.gameserver.model.skills.BuffInfo;
|
||||
import com.l2jserver.gameserver.model.skills.CommonSkill;
|
||||
import com.l2jserver.gameserver.model.skills.Skill;
|
||||
import com.l2jserver.gameserver.network.SystemMessageId;
|
||||
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
|
||||
|
||||
/**
|
||||
* Black Judge AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
public class BlackJudge extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int BLACK_JUDGE = 30981;
|
||||
// Misc
|
||||
// @formatter:off
|
||||
private static final int[] COSTS =
|
||||
{
|
||||
3600, 8640, 25200, 50400, 86400, 144000
|
||||
};
|
||||
// @formatter:on
|
||||
|
||||
private BlackJudge()
|
||||
{
|
||||
super(BlackJudge.class.getSimpleName(), "ai/npc");
|
||||
addStartNpc(BLACK_JUDGE);
|
||||
addTalkId(BLACK_JUDGE);
|
||||
addFirstTalkId(BLACK_JUDGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
String htmltext = null;
|
||||
final int level = ((player.getExpertiseLevel() < 5) ? player.getExpertiseLevel() : 5);
|
||||
switch (event)
|
||||
{
|
||||
case "remove_info":
|
||||
{
|
||||
htmltext = "30981-0" + (level + 1) + ".html";
|
||||
break;
|
||||
}
|
||||
case "remove_dp":
|
||||
{
|
||||
if (player.getShilensBreathDebuffLevel() > 0)
|
||||
{
|
||||
int cost = COSTS[level];
|
||||
|
||||
if (player.getAdena() >= cost)
|
||||
{
|
||||
takeItems(player, Inventory.ADENA_ID, cost);
|
||||
final int nextLv = player.getShilensBreathDebuffLevel() - 1;
|
||||
|
||||
if (nextLv > 0)
|
||||
{
|
||||
final Skill skill = SkillData.getInstance().getSkill(CommonSkill.SHILENS_BREATH.getId(), nextLv);
|
||||
if (skill != null)
|
||||
{
|
||||
skill.applyEffects(player, player);
|
||||
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_VE_BEEN_AFFLICTED_BY_SHILEN_S_BREATH_LEVEL_S1).addInt(nextLv));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final BuffInfo buff = player.getEffectList().getBuffInfoBySkillId(CommonSkill.SHILENS_BREATH.getId());
|
||||
if (buff != null)
|
||||
{
|
||||
player.getEffectList().remove(true, buff);
|
||||
}
|
||||
player.sendPacket(SystemMessageId.SHILEN_S_BREATH_HAS_BEEN_PURIFIED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
htmltext = "30981-07.html";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
htmltext = "30981-08.html";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return htmltext;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new BlackJudge();
|
||||
}
|
||||
}
|
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackMarketeerOfMammon/31092-01.html
vendored
Normal file
6
trunk/dist/game/data_classic/scripts/ai/npc/BlackMarketeerOfMammon/31092-01.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Black Marketeer of Mammon:<br>
|
||||
<font color="LEVEL">[Exchange Ancient Adena for Adena]</font><br>
|
||||
Enter the amount of Ancient Adena you wish to exchange.<br>
|
||||
<td align=left><edit var="data1" width=100></td>
|
||||
<button value="Exchange" action="bypass -h Quest BlackMarketeerOfMammon exchange $data1" back="L2UI_CT1.Button_DF_Down" fore="L2UI_CT1.Button_DF" width=80 height=27>
|
||||
</body></html>
|
5
trunk/dist/game/data_classic/scripts/ai/npc/BlackMarketeerOfMammon/31092-02.html
vendored
Normal file
5
trunk/dist/game/data_classic/scripts/ai/npc/BlackMarketeerOfMammon/31092-02.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><head><body>Black Marketeer of Mammon:<br>
|
||||
<font color="FF0000">[Exchange failure]</font><br>
|
||||
You've entered an invalid value. Please input a correct amount.<br>
|
||||
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest BlackMarketeerOfMammon 31092-01.html">Back</Button>
|
||||
</body></html>
|
5
trunk/dist/game/data_classic/scripts/ai/npc/BlackMarketeerOfMammon/31092-03.html
vendored
Normal file
5
trunk/dist/game/data_classic/scripts/ai/npc/BlackMarketeerOfMammon/31092-03.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><head><body>Black Marketeer of Mammon:<br>
|
||||
<font color="FF0000">[Exchange failure]</font><br>
|
||||
You don't have enough of the item that you're trying to exchange.<br>
|
||||
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest BlackMarketeerOfMammon 31092-01.html">Back</Button>
|
||||
</body></html>
|
5
trunk/dist/game/data_classic/scripts/ai/npc/BlackMarketeerOfMammon/31092-04.html
vendored
Normal file
5
trunk/dist/game/data_classic/scripts/ai/npc/BlackMarketeerOfMammon/31092-04.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Black Marketeer of Mammon:<br>
|
||||
<FONT color="LEVEL">[Exchange success]</FONT><br>
|
||||
Thank you! There you go! Are you satisfied now? Or do you want to exchange something else?<br>
|
||||
<Button ALIGN=LEFT ICON="RETURN" action="Quest BlackMarketeerOfMammon 31092-01.html">Back</Button>
|
||||
</body></html>
|
11
trunk/dist/game/data_classic/scripts/ai/npc/BlackMarketeerOfMammon/31092.html
vendored
Normal file
11
trunk/dist/game/data_classic/scripts/ai/npc/BlackMarketeerOfMammon/31092.html
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<html><body>Black Marketeer of Mammon:<br>
|
||||
The Lords of Dawn and the Revolutionary Troops of Dusk use <font color="LEVEL">Ancient Adena</font> as their currency, following in the old empire's tradition.<br>
|
||||
Tradition and customs are important but they are so old... If you were to go to the market with that money in this day and age, you couldn't buy a thing.<br>
|
||||
Do you have any ancient adena that you don't know what to do with? If you do, I'll exchange them for adena.<br>
|
||||
Also, if your weapon has a special ability that you do not want, I can remove that, too. I dont't know why you would want to take off a special ability that's been bestowed on your weapon, but we'll do anything for adena.<br>
|
||||
I have also obtained some rare goods, so stop by some time - these items aren't easy to obtain!<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BlackMarketeerOfMammon 31092-01.html">"I want to exchange Ancient Adena for Adena."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 310922002">"Can I trade black market goods?"</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_exc_multisell 310922001">"I want to remove special abilities from my weapon."</Button>
|
||||
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
|
||||
</body></html>
|
94
trunk/dist/game/data_classic/scripts/ai/npc/BlackMarketeerOfMammon/BlackMarketeerOfMammon.java
vendored
Normal file
94
trunk/dist/game/data_classic/scripts/ai/npc/BlackMarketeerOfMammon/BlackMarketeerOfMammon.java
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.npc.BlackMarketeerOfMammon;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.itemcontainer.Inventory;
|
||||
import com.l2jserver.gameserver.util.Util;
|
||||
|
||||
/**
|
||||
* Black Marketeer of Mammon AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
public final class BlackMarketeerOfMammon extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int BLACK_MARKETEER = 31092;
|
||||
|
||||
private BlackMarketeerOfMammon()
|
||||
{
|
||||
super(BlackMarketeerOfMammon.class.getSimpleName(), "ai/npc");
|
||||
addStartNpc(BLACK_MARKETEER);
|
||||
addTalkId(BLACK_MARKETEER);
|
||||
addFirstTalkId(BLACK_MARKETEER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equals("31092-01.html"))
|
||||
{
|
||||
return event;
|
||||
}
|
||||
else if (event.startsWith("exchange"))
|
||||
{
|
||||
final StringTokenizer st = new StringTokenizer(event, " ");
|
||||
event = st.nextToken();
|
||||
|
||||
if (!st.hasMoreElements())
|
||||
{
|
||||
return "31092-02.html";
|
||||
}
|
||||
|
||||
final String value = st.nextToken();
|
||||
if (!Util.isDigit(value))
|
||||
{
|
||||
return "31092-02.html";
|
||||
}
|
||||
|
||||
final long count = Integer.parseInt(value);
|
||||
final long AAcount = player.getAncientAdena();
|
||||
|
||||
if (count < 1)
|
||||
{
|
||||
return "31092-02.html";
|
||||
}
|
||||
|
||||
if (count > AAcount)
|
||||
{
|
||||
return "31092-03.html";
|
||||
|
||||
}
|
||||
takeItems(player, Inventory.ANCIENT_ADENA_ID, count);
|
||||
giveAdena(player, count, false);
|
||||
return "31092-04.html";
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new BlackMarketeerOfMammon();
|
||||
}
|
||||
}
|
178
trunk/dist/game/data_classic/scripts/ai/npc/CastleAmbassador/CastleAmbassador.java
vendored
Normal file
178
trunk/dist/game/data_classic/scripts/ai/npc/CastleAmbassador/CastleAmbassador.java
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2015 L2J DataPack
|
||||
*
|
||||
* This file is part of L2J DataPack.
|
||||
*
|
||||
* L2J DataPack is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* L2J DataPack is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.npc.CastleAmbassador;
|
||||
|
||||
import ai.npc.AbstractNpcAI;
|
||||
|
||||
import com.l2jserver.gameserver.model.L2Object;
|
||||
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.entity.Castle;
|
||||
import com.l2jserver.gameserver.model.entity.Fort;
|
||||
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
|
||||
|
||||
/**
|
||||
* Castle Ambassador AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
public final class CastleAmbassador extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
// @formatter:off
|
||||
private static final int[] CASTLE_AMBASSADOR =
|
||||
{
|
||||
36393, 36394, 36437, 36435, // Gludio
|
||||
36395, 36436, 36439, 36441, // Dion
|
||||
36396, 36440, 36444, 36449, 36451, // Giran
|
||||
36397, 36438, 36442, 36443, 36446, // Oren
|
||||
36398, 36399, 36445, 36448, // Aden
|
||||
36400, 36450, // Innadril
|
||||
36401, 36447, 36453, // Goddard
|
||||
36433, 36452, 36454, // Rune
|
||||
36434, 36455, // Schuttgart
|
||||
};
|
||||
// @formatter:on
|
||||
|
||||
private CastleAmbassador()
|
||||
{
|
||||
super(CastleAmbassador.class.getSimpleName(), "ai/npc");
|
||||
addStartNpc(CASTLE_AMBASSADOR);
|
||||
addTalkId(CASTLE_AMBASSADOR);
|
||||
addFirstTalkId(CASTLE_AMBASSADOR);
|
||||
addEventReceivedId(CASTLE_AMBASSADOR);
|
||||
addSpawnId(CASTLE_AMBASSADOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
final Fort fortresss = npc.getFort();
|
||||
String htmltext = null;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case "signed":
|
||||
{
|
||||
if (fortresss.getFortState() == 0)
|
||||
{
|
||||
fortresss.setFortState(2, fortresss.getCastleIdByAmbassador(npc.getId()));
|
||||
cancelQuestTimer("DESPAWN", npc, null);
|
||||
startQuestTimer("DESPAWN", 3000, npc, null);
|
||||
htmltext = "ambassador-05.html";
|
||||
}
|
||||
else if (fortresss.getFortState() == 1)
|
||||
{
|
||||
htmltext = "ambassador-04.html";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "rejected":
|
||||
{
|
||||
if (fortresss.getFortState() == 0)
|
||||
{
|
||||
fortresss.setFortState(1, fortresss.getCastleIdByAmbassador(npc.getId()));
|
||||
cancelQuestTimer("DESPAWN", npc, null);
|
||||
startQuestTimer("DESPAWN", 3000, npc, null);
|
||||
htmltext = "ambassador-02.html";
|
||||
}
|
||||
else if (fortresss.getFortState() == 2)
|
||||
{
|
||||
htmltext = "ambassador-02.html";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "DESPAWN":
|
||||
{
|
||||
if (fortresss.getFortState() == 0)
|
||||
{
|
||||
fortresss.setFortState(1, fortresss.getCastleIdByAmbassador(npc.getId()));
|
||||
}
|
||||
cancelQuestTimer("DESPAWN", npc, null);
|
||||
npc.broadcastEvent("DESPAWN", 1000, null);
|
||||
npc.deleteMe();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (htmltext != null)
|
||||
{
|
||||
final NpcHtmlMessage packet = new NpcHtmlMessage(npc.getObjectId());
|
||||
packet.setHtml(getHtm(player.getHtmlPrefix(), htmltext));
|
||||
packet.replace("%castleName%", String.valueOf(fortresss.getCastleByAmbassador(npc.getId()).getName()));
|
||||
player.sendPacket(packet);
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onEventReceived(String eventName, L2Npc sender, L2Npc receiver, L2Object reference)
|
||||
{
|
||||
if (receiver != null)
|
||||
{
|
||||
receiver.deleteMe();
|
||||
}
|
||||
return super.onEventReceived(eventName, sender, receiver, reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFirstTalk(L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
final Fort fortresss = npc.getFort();
|
||||
final int fortOwner = fortresss.getOwnerClan() == null ? 0 : fortresss.getOwnerClan().getId();
|
||||
String htmltext = null;
|
||||
|
||||
if (player.isClanLeader() && (player.getClanId() == fortOwner))
|
||||
{
|
||||
htmltext = (fortresss.isBorderFortress()) ? "ambassador-01.html" : "ambassador.html";
|
||||
}
|
||||
else
|
||||
{
|
||||
htmltext = "ambassador-03.html";
|
||||
}
|
||||
|
||||
final NpcHtmlMessage packet = new NpcHtmlMessage(npc.getObjectId());
|
||||
packet.setHtml(getHtm(player.getHtmlPrefix(), htmltext));
|
||||
packet.replace("%castleName%", String.valueOf(fortresss.getCastleByAmbassador(npc.getId()).getName()));
|
||||
player.sendPacket(packet);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
final Castle castle = npc.getFort().getCastleByAmbassador(npc.getId());
|
||||
if (castle.getOwnerId() == 0)
|
||||
{
|
||||
npc.deleteMe();
|
||||
}
|
||||
else
|
||||
{
|
||||
startQuestTimer("DESPAWN", 3600000, npc, null);
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new CastleAmbassador();
|
||||
}
|
||||
}
|
8
trunk/dist/game/data_classic/scripts/ai/npc/CastleAmbassador/ambassador-01.html
vendored
Normal file
8
trunk/dist/game/data_classic/scripts/ai/npc/CastleAmbassador/ambassador-01.html
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<html><body>Ambassador of %castleName%:<br>
|
||||
My master is the great ruler of %castleName% Castle. The message I am commanded to relay to you, the new possessor of this fortress, is: "Protect this territory from our enemies!"<br>
|
||||
If you do not have the strength to protect this place, my master inquires whether you would care to use our clan's strength to develop your skills.<br>
|
||||
<br>
|
||||
<center>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleAmbassador rejected">"We decline. We will walk our own path."</Button>
|
||||
</center>
|
||||
</body></html>
|
3
trunk/dist/game/data_classic/scripts/ai/npc/CastleAmbassador/ambassador-02.html
vendored
Normal file
3
trunk/dist/game/data_classic/scripts/ai/npc/CastleAmbassador/ambassador-02.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Ambassador of %castleName%:<br>
|
||||
Hmm... I see that negotiations have been broken off. I must cease for now.
|
||||
</body></html>
|
3
trunk/dist/game/data_classic/scripts/ai/npc/CastleAmbassador/ambassador-03.html
vendored
Normal file
3
trunk/dist/game/data_classic/scripts/ai/npc/CastleAmbassador/ambassador-03.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Ambassador of %castleName%:<br>
|
||||
Impudent pup! The letter I hold may only be seen by your leader.
|
||||
</body></html>
|
3
trunk/dist/game/data_classic/scripts/ai/npc/CastleAmbassador/ambassador-04.html
vendored
Normal file
3
trunk/dist/game/data_classic/scripts/ai/npc/CastleAmbassador/ambassador-04.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Ambassador of %castleName%:<br>
|
||||
You have already rejected my lord's offer. Why have you now changed your mind?
|
||||
</body></html>
|
3
trunk/dist/game/data_classic/scripts/ai/npc/CastleAmbassador/ambassador-05.html
vendored
Normal file
3
trunk/dist/game/data_classic/scripts/ai/npc/CastleAmbassador/ambassador-05.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Ambassador of %castleName%:<br>
|
||||
You have signed the contract. I am sure that my lord will be pleased.
|
||||
</body></html>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user