This commit is contained in:
mobius
2015-01-01 20:02:50 +00:00
parent eeae660458
commit a6a3718849
17894 changed files with 2818932 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2004-2014 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.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* Aden Reconstructor Manager AI.
* @author St3eT
*/
public final class AdenReconstructorManager extends AbstractNpcAI
{
// NPCs
private static final int[] NPCS =
{
33584, // Moe
33581, // Eeny
};
private AdenReconstructorManager()
{
super(AdenReconstructorManager.class.getSimpleName(), "ai/individual");
addSpawnId(NPCS);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (npc != null)
{
switch (event)
{
case "SPAM_TEXT":
{
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.THE_LAND_OF_ADEN_IS_IN_NEED_OF_MATERIALS_TO_REBUILD_FROM_SHILEN_S_DESTRUCTION);
startQuestTimer("SPAM_TEXT2", 1000, npc, null);
break;
}
case "SPAM_TEXT2":
{
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.PLEASE_DONATE_ANY_UNUSED_MATERIALS_YOU_HAVE_TO_HELP_REBUILD_ADEN);
startQuestTimer("SPAM_TEXT3", 1000, npc, null);
break;
}
case "SPAM_TEXT3":
{
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.YOU_LL_RECEIVE_A_GIFT_FOR_ANY_APPLICABLE_DONATION);
break;
}
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSpawn(L2Npc npc)
{
startQuestTimer("SPAM_TEXT", (5 * 60 * 1000), npc, null, true);
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new AdenReconstructorManager();
}
}

View File

@@ -0,0 +1,487 @@
/*
* Copyright (C) 2004-2014 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.List;
import java.util.Map;
import javolution.util.FastMap;
import quests.Q00020_BringUpWithLove.Q00020_BringUpWithLove;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.idfactory.IdFactory;
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.actor.templates.L2NpcTemplate;
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 Map<Integer, Integer> _FeedInfo = new FastMap<>();
private static Map<Integer, GrowthCapableMob> _GrowthCapableMobs = new FastMap<>();
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);
_GrowthCapableMobs.put(18873, temp);
temp = new GrowthCapableMob(40, 1, 18869);
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18876);
_GrowthCapableMobs.put(18874, temp);
temp = new GrowthCapableMob(40, 1, 18869);
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18877);
_GrowthCapableMobs.put(18875, temp);
temp = new GrowthCapableMob(25, 2, 18869);
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18878);
_GrowthCapableMobs.put(18876, temp);
temp = new GrowthCapableMob(25, 2, 18869);
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18879);
_GrowthCapableMobs.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);
_GrowthCapableMobs.put(18880, temp);
temp = new GrowthCapableMob(40, 1, 18870);
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18883);
_GrowthCapableMobs.put(18881, temp);
temp = new GrowthCapableMob(40, 1, 18870);
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18884);
_GrowthCapableMobs.put(18882, temp);
temp = new GrowthCapableMob(25, 2, 18870);
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18885);
_GrowthCapableMobs.put(18883, temp);
temp = new GrowthCapableMob(25, 2, 18870);
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18886);
_GrowthCapableMobs.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);
_GrowthCapableMobs.put(18887, temp);
temp = new GrowthCapableMob(40, 1, 18871);
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18890);
_GrowthCapableMobs.put(18888, temp);
temp = new GrowthCapableMob(40, 1, 18871);
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18891);
_GrowthCapableMobs.put(18889, temp);
temp = new GrowthCapableMob(25, 2, 18871);
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18892);
_GrowthCapableMobs.put(18890, temp);
temp = new GrowthCapableMob(25, 2, 18871);
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18893);
_GrowthCapableMobs.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);
_GrowthCapableMobs.put(18894, temp);
temp = new GrowthCapableMob(40, 1, 18872);
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18897);
_GrowthCapableMobs.put(18895, temp);
temp = new GrowthCapableMob(40, 1, 18872);
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18898);
_GrowthCapableMobs.put(18896, temp);
temp = new GrowthCapableMob(25, 2, 18872);
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18899);
_GrowthCapableMobs.put(18897, temp);
temp = new GrowthCapableMob(25, 2, 18872);
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18900);
_GrowthCapableMobs.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 (_FeedInfo.containsKey(npc.getObjectId()))
{
if (_FeedInfo.get(npc.getObjectId()) == player.getObjectId())
{
_FeedInfo.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))
{
L2NpcTemplate template = NpcData.getInstance().getTemplate(nextNpcId);
L2TamedBeastInstance nextNpc = new L2TamedBeastInstance(IdFactory.getInstance().getNextId(), template, 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
_FeedInfo.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 (_GrowthCapableMobs.containsKey(npcId))
{
growthLevel = _GrowthCapableMobs.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) && _FeedInfo.containsKey(objectId))
{
return super.onSkillSee(npc, caster, skill, targets, isSummon);
}
_FeedInfo.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 (_GrowthCapableMobs.containsKey(npcId))
{
// do nothing if this mob doesn't eat the specified food (food gets consumed but has no effect).
int newNpcId = _GrowthCapableMobs.get(npcId).getLeveledNpcId(skillId);
if (newNpcId == -1)
{
if (growthLevel == 0)
{
_FeedInfo.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) && (_FeedInfo.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 (_FeedInfo.containsKey(npc.getObjectId()))
{
_FeedInfo.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 FastMap<>();
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();
}
}

View File

@@ -0,0 +1,238 @@
/*
* Copyright (C) 2004-2014 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 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)
{
_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)
{
_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();
}
}

View File

@@ -0,0 +1,299 @@
/*
* Copyright (C) 2004-2014 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.EnumMap;
import ai.npc.AbstractNpcAI;
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.L2PcInstance;
import com.l2jserver.gameserver.model.base.ClassId;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.util.Util;
/**
* Dragon Valley AI.
* @author St3eT
*/
public final class DragonValley extends AbstractNpcAI
{
// NPC
private static final int NECROMANCER_OF_THE_VALLEY = 22858;
private static final int EXPLODING_ORC_GHOST = 22818;
private static final int WRATHFUL_ORC_GHOST = 22819;
private static final int DRAKOS_ASSASSIN = 22823;
private static final int[] SUMMON_NPC =
{
22822, // Drakos Warrior
22824, // Drakos Guardian
22862, // Drakos Hunter
};
private static final int[] SPAWN_ANIMATION =
{
22826, // Scorpion Bones
22823, // Drakos Assassin
22828, // Parasitic Leech
};
private static final int[] SPOIL_REACT_MONSTER =
{
22822, // Drakos Warrior
22823, // Drakos Assassin
22824, // Drakos Guardian
22825, // Giant Scorpion Bones
22826, // Scorpion Bones
22827, // Batwing Drake
22828, // Parasitic Leech
22829, // Emerald Drake
22830, // Gem Dragon
22831, // Dragon Tracker of the Valley
22832, // Dragon Scout of the Valley
22833, // Sand Drake Tracker
22834, // Dust Dragon Tracker
22860, // Hungry Parasitic Leech
22861, // Hard Scorpion Bones
22862, // Drakos Hunter
};
// Items
private static final int GREATER_HERB_OF_MANA = 8604;
private static final int SUPERIOR_HERB_OF_MANA = 8605;
// Skills
private static final SkillHolder SELF_DESTRUCTION = new SkillHolder(6850, 1);
private static final SkillHolder MORALE_BOOST1 = new SkillHolder(6885, 1);
private static final SkillHolder MORALE_BOOST2 = new SkillHolder(6885, 2);
private static final SkillHolder MORALE_BOOST3 = new SkillHolder(6885, 3);
// Misc
private static final int MIN_DISTANCE = 1500;
private static final int MIN_MEMBERS = 3;
private static final int MIN_LVL = 80;
private static final int CLASS_LVL = 3;
private static final EnumMap<ClassId, Double> CLASS_POINTS = new EnumMap<>(ClassId.class);
{
CLASS_POINTS.put(ClassId.ADVENTURER, 0.2);
CLASS_POINTS.put(ClassId.ARCANA_LORD, 1.5);
CLASS_POINTS.put(ClassId.ARCHMAGE, 0.3);
CLASS_POINTS.put(ClassId.CARDINAL, -0.6);
CLASS_POINTS.put(ClassId.DOMINATOR, 0.2);
CLASS_POINTS.put(ClassId.DOOMBRINGER, 0.2);
CLASS_POINTS.put(ClassId.DOOMCRYER, 0.1);
CLASS_POINTS.put(ClassId.DREADNOUGHT, 0.7);
CLASS_POINTS.put(ClassId.DUELIST, 0.2);
CLASS_POINTS.put(ClassId.ELEMENTAL_MASTER, 1.4);
CLASS_POINTS.put(ClassId.EVA_SAINT, -0.6);
CLASS_POINTS.put(ClassId.EVA_TEMPLAR, 0.8);
CLASS_POINTS.put(ClassId.FEMALE_SOUL_HOUND, 0.4);
CLASS_POINTS.put(ClassId.FORTUNE_SEEKER, 0.9);
CLASS_POINTS.put(ClassId.GHOST_HUNTER, 0.2);
CLASS_POINTS.put(ClassId.GHOST_SENTINEL, 0.2);
CLASS_POINTS.put(ClassId.GRAND_KHAVATARI, 0.2);
CLASS_POINTS.put(ClassId.HELL_KNIGHT, 0.6);
CLASS_POINTS.put(ClassId.HIEROPHANT, 0.0);
CLASS_POINTS.put(ClassId.JUDICATOR, 0.1);
CLASS_POINTS.put(ClassId.MOONLIGHT_SENTINEL, 0.2);
CLASS_POINTS.put(ClassId.MAESTRO, 0.7);
CLASS_POINTS.put(ClassId.MALE_SOUL_HOUND, 0.4);
CLASS_POINTS.put(ClassId.MYSTIC_MUSE, 0.3);
CLASS_POINTS.put(ClassId.PHOENIX_KNIGHT, 0.6);
CLASS_POINTS.put(ClassId.SAGITTARIUS, 0.2);
CLASS_POINTS.put(ClassId.SHILLIEN_SAINT, -0.6);
CLASS_POINTS.put(ClassId.SHILLIEN_TEMPLAR, 0.8);
CLASS_POINTS.put(ClassId.SOULTAKER, 0.3);
CLASS_POINTS.put(ClassId.SPECTRAL_DANCER, 0.4);
CLASS_POINTS.put(ClassId.SPECTRAL_MASTER, 1.4);
CLASS_POINTS.put(ClassId.STORM_SCREAMER, 0.3);
CLASS_POINTS.put(ClassId.SWORD_MUSE, 0.4);
CLASS_POINTS.put(ClassId.TITAN, 0.3);
CLASS_POINTS.put(ClassId.TRICKSTER, 0.5);
CLASS_POINTS.put(ClassId.WIND_RIDER, 0.2);
}
private DragonValley()
{
super(DragonValley.class.getSimpleName(), "ai/group_template");
addAttackId(NECROMANCER_OF_THE_VALLEY);
addAttackId(SUMMON_NPC);
addKillId(NECROMANCER_OF_THE_VALLEY);
addKillId(SPOIL_REACT_MONSTER);
addSpawnId(EXPLODING_ORC_GHOST, NECROMANCER_OF_THE_VALLEY);
addSpawnId(SPOIL_REACT_MONSTER);
addSpellFinishedId(EXPLODING_ORC_GHOST);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("SELF_DESTRUCTION") && (npc != null) && !npc.isDead())
{
final L2Playable playable = npc.getVariables().getObject("playable", L2Playable.class);
if ((playable != null) && (npc.calculateDistance(playable, true, false) < 250))
{
npc.disableCoreAI(true);
npc.doCast(SELF_DESTRUCTION.getSkill());
}
else if (playable != null)
{
startQuestTimer("SELF_DESTRUCTION", 3000, npc, null);
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
if (npc.getId() == NECROMANCER_OF_THE_VALLEY)
{
spawnGhost(npc, attacker, isSummon, 1);
}
else
{
if ((npc.getCurrentHp() < (npc.getMaxHp() / 2)) && (getRandom(100) < 5) && npc.isScriptValue(0))
{
npc.setScriptValue(1);
final int rnd = getRandom(3, 5);
for (int i = 0; i < rnd; i++)
{
final L2Playable playable = isSummon ? attacker.getSummon() : attacker;
final L2Npc minion = addSpawn(DRAKOS_ASSASSIN, npc.getX(), npc.getY(), npc.getZ() + 10, npc.getHeading(), true, 0, true);
addAttackPlayerDesire(minion, playable);
}
}
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
if (npc.getId() == NECROMANCER_OF_THE_VALLEY)
{
spawnGhost(npc, killer, isSummon, 20);
}
else if (((L2Attackable) npc).isSweepActive())
{
npc.dropItem(killer, getRandom(GREATER_HERB_OF_MANA, SUPERIOR_HERB_OF_MANA), 1);
manageMoraleBoost(killer, npc);
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onSpawn(L2Npc npc)
{
((L2Attackable) npc).setOnKillDelay(0);
if (npc.getId() == EXPLODING_ORC_GHOST)
{
startQuestTimer("SELF_DESTRUCTION", 3000, npc, null);
}
else if (Util.contains(SPAWN_ANIMATION, npc.getId()))
{
npc.setShowSummonAnimation(true);
}
return super.onSpawn(npc);
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
if (skill == SELF_DESTRUCTION.getSkill())
{
npc.doDie(player);
}
return super.onSpellFinished(npc, player, skill);
}
private void manageMoraleBoost(L2PcInstance player, L2Npc npc)
{
double points = 0;
int moraleBoostLv = 0;
if (player.isInParty() && (player.getParty().getMemberCount() >= MIN_MEMBERS) && (npc != null))
{
for (L2PcInstance member : player.getParty().getMembers())
{
if ((member.getLevel() >= MIN_LVL) && (member.getClassId().level() >= CLASS_LVL) && (npc.calculateDistance(member, true, false) < MIN_DISTANCE))
{
points += CLASS_POINTS.get(member.getClassId());
}
}
if (points >= 3)
{
moraleBoostLv = 3;
}
else if (points >= 2)
{
moraleBoostLv = 2;
}
else if (points >= 1)
{
moraleBoostLv = 1;
}
for (L2PcInstance member : player.getParty().getMembers())
{
if (npc.calculateDistance(member, true, false) < MIN_DISTANCE)
{
switch (moraleBoostLv)
{
case 1:
MORALE_BOOST1.getSkill().applyEffects(member, member);
break;
case 2:
MORALE_BOOST2.getSkill().applyEffects(member, member);
break;
case 3:
MORALE_BOOST3.getSkill().applyEffects(member, member);
break;
}
}
}
}
}
private void spawnGhost(L2Npc npc, L2PcInstance player, boolean isSummon, int chance)
{
if ((npc.getScriptValue() < 2) && (getRandom(100) < chance))
{
int val = npc.getScriptValue();
final L2Playable attacker = isSummon ? player.getSummon() : player;
final L2Npc ghost1 = addSpawn(EXPLODING_ORC_GHOST, npc.getX(), npc.getY(), npc.getZ() + 10, npc.getHeading(), false, 0, true);
ghost1.getVariables().set("playable", attacker);
addAttackPlayerDesire(ghost1, attacker);
val++;
if ((val < 2) && (getRandomBoolean()))
{
final L2Npc ghost2 = addSpawn(WRATHFUL_ORC_GHOST, npc.getX(), npc.getY(), npc.getZ() + 20, npc.getHeading(), false, 0, false);
addAttackPlayerDesire(ghost2, attacker);
val++;
}
npc.setScriptValue(val);
}
}
public static void main(String[] args)
{
new DragonValley();
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (C) 2004-2014 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.getSummon() : 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();
}
}

View File

@@ -0,0 +1,617 @@
/*
* Copyright (C) 2004-2014 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.Map;
import javolution.util.FastMap;
import quests.Q00020_BringUpWithLove.Q00020_BringUpWithLove;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.idfactory.IdFactory;
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.actor.templates.L2NpcTemplate;
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;
// @formatter:off
private static final int[] TAMED_BEASTS =
{
16013, 16014, 16015, 16016, 16017, 16018
};
// 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, 16013, 16014, 16015, 16016, 16017, 16018
};
// @formatter:on
private static final Map<Integer, Integer> MAD_COW_POLYMORPH = new FastMap<>();
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 Map<Integer, Integer> _FeedInfo = new FastMap<>();
private static Map<Integer, GrowthCapableMob> _GrowthCapableMobs = new FastMap<>();
// 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 FastMap<>();
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}, { 16017, 16018 }};
final int[][] Kookabura_2_2 = {{ 21469, 21825}, { 16017, 16018 }};
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}, {16013, 16014 }};
final int[][] Buffalo_2_2 = {{ 21488,21827}, {16013, 16014 }};
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 }, { 16015,16016 }};
final int[][] Cougar_2_2 = {{ 21507, 21829 }, { 16015,16016 }};
//@formatter:on
// Alpen Kookabura
temp = new GrowthCapableMob(0, 100);
temp.addMobs(GOLDEN_SPICE, Kookabura_0_Gold);
temp.addMobs(CRYSTAL_SPICE, Kookabura_0_Crystal);
_GrowthCapableMobs.put(21451, temp);
temp = new GrowthCapableMob(1, 40);
temp.addMobs(GOLDEN_SPICE, Kookabura_1_Gold_1);
_GrowthCapableMobs.put(21452, temp);
_GrowthCapableMobs.put(21454, temp);
temp = new GrowthCapableMob(1, 40);
temp.addMobs(GOLDEN_SPICE, Kookabura_1_Gold_2);
_GrowthCapableMobs.put(21453, temp);
_GrowthCapableMobs.put(21455, temp);
temp = new GrowthCapableMob(1, 40);
temp.addMobs(CRYSTAL_SPICE, Kookabura_1_Crystal_1);
_GrowthCapableMobs.put(21456, temp);
_GrowthCapableMobs.put(21458, temp);
temp = new GrowthCapableMob(1, 40);
temp.addMobs(CRYSTAL_SPICE, Kookabura_1_Crystal_2);
_GrowthCapableMobs.put(21457, temp);
_GrowthCapableMobs.put(21459, temp);
temp = new GrowthCapableMob(2, 25);
temp.addMobs(GOLDEN_SPICE, Kookabura_2_1);
_GrowthCapableMobs.put(21460, temp);
_GrowthCapableMobs.put(21462, temp);
temp = new GrowthCapableMob(2, 25);
temp.addMobs(GOLDEN_SPICE, Kookabura_2_2);
_GrowthCapableMobs.put(21461, temp);
_GrowthCapableMobs.put(21463, temp);
temp = new GrowthCapableMob(2, 25);
temp.addMobs(CRYSTAL_SPICE, Kookabura_2_1);
_GrowthCapableMobs.put(21464, temp);
_GrowthCapableMobs.put(21466, temp);
temp = new GrowthCapableMob(2, 25);
temp.addMobs(CRYSTAL_SPICE, Kookabura_2_2);
_GrowthCapableMobs.put(21465, temp);
_GrowthCapableMobs.put(21467, temp);
// Alpen Buffalo
temp = new GrowthCapableMob(0, 100);
temp.addMobs(GOLDEN_SPICE, Buffalo_0_Gold);
temp.addMobs(CRYSTAL_SPICE, Buffalo_0_Crystal);
_GrowthCapableMobs.put(21470, temp);
temp = new GrowthCapableMob(1, 40);
temp.addMobs(GOLDEN_SPICE, Buffalo_1_Gold_1);
_GrowthCapableMobs.put(21471, temp);
_GrowthCapableMobs.put(21473, temp);
temp = new GrowthCapableMob(1, 40);
temp.addMobs(GOLDEN_SPICE, Buffalo_1_Gold_2);
_GrowthCapableMobs.put(21472, temp);
_GrowthCapableMobs.put(21474, temp);
temp = new GrowthCapableMob(1, 40);
temp.addMobs(CRYSTAL_SPICE, Buffalo_1_Crystal_1);
_GrowthCapableMobs.put(21475, temp);
_GrowthCapableMobs.put(21477, temp);
temp = new GrowthCapableMob(1, 40);
temp.addMobs(CRYSTAL_SPICE, Buffalo_1_Crystal_2);
_GrowthCapableMobs.put(21476, temp);
_GrowthCapableMobs.put(21478, temp);
temp = new GrowthCapableMob(2, 25);
temp.addMobs(GOLDEN_SPICE, Buffalo_2_1);
_GrowthCapableMobs.put(21479, temp);
_GrowthCapableMobs.put(21481, temp);
temp = new GrowthCapableMob(2, 25);
temp.addMobs(GOLDEN_SPICE, Buffalo_2_2);
_GrowthCapableMobs.put(21480, temp);
_GrowthCapableMobs.put(21482, temp);
temp = new GrowthCapableMob(2, 25);
temp.addMobs(CRYSTAL_SPICE, Buffalo_2_1);
_GrowthCapableMobs.put(21483, temp);
_GrowthCapableMobs.put(21485, temp);
temp = new GrowthCapableMob(2, 25);
temp.addMobs(CRYSTAL_SPICE, Buffalo_2_2);
_GrowthCapableMobs.put(21484, temp);
_GrowthCapableMobs.put(21486, temp);
// Alpen Cougar
temp = new GrowthCapableMob(0, 100);
temp.addMobs(GOLDEN_SPICE, Cougar_0_Gold);
temp.addMobs(CRYSTAL_SPICE, Cougar_0_Crystal);
_GrowthCapableMobs.put(21489, temp);
temp = new GrowthCapableMob(1, 40);
temp.addMobs(GOLDEN_SPICE, Cougar_1_Gold_1);
_GrowthCapableMobs.put(21490, temp);
_GrowthCapableMobs.put(21492, temp);
temp = new GrowthCapableMob(1, 40);
temp.addMobs(GOLDEN_SPICE, Cougar_1_Gold_2);
_GrowthCapableMobs.put(21491, temp);
_GrowthCapableMobs.put(21493, temp);
temp = new GrowthCapableMob(1, 40);
temp.addMobs(CRYSTAL_SPICE, Cougar_1_Crystal_1);
_GrowthCapableMobs.put(21494, temp);
_GrowthCapableMobs.put(21496, temp);
temp = new GrowthCapableMob(1, 40);
temp.addMobs(CRYSTAL_SPICE, Cougar_1_Crystal_2);
_GrowthCapableMobs.put(21495, temp);
_GrowthCapableMobs.put(21497, temp);
temp = new GrowthCapableMob(2, 25);
temp.addMobs(GOLDEN_SPICE, Cougar_2_1);
_GrowthCapableMobs.put(21498, temp);
_GrowthCapableMobs.put(21500, temp);
temp = new GrowthCapableMob(2, 25);
temp.addMobs(GOLDEN_SPICE, Cougar_2_2);
_GrowthCapableMobs.put(21499, temp);
_GrowthCapableMobs.put(21501, temp);
temp = new GrowthCapableMob(2, 25);
temp.addMobs(CRYSTAL_SPICE, Cougar_2_1);
_GrowthCapableMobs.put(21502, temp);
_GrowthCapableMobs.put(21504, temp);
temp = new GrowthCapableMob(2, 25);
temp.addMobs(CRYSTAL_SPICE, Cougar_2_2);
_GrowthCapableMobs.put(21503, temp);
_GrowthCapableMobs.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 = _GrowthCapableMobs.get(npcId).getMob(food, 1, 1);
}
else
{
nextNpcId = _GrowthCapableMobs.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 = _GrowthCapableMobs.get(npcId).getMob(food, 0, 1);
}
else
{
nextNpcId = _GrowthCapableMobs.get(npcId).getMob(food, 0, 0);
}
}
}
else
{
// all other levels of growth are straight-forward
nextNpcId = _GrowthCapableMobs.get(npcId).getRandomMob(food);
}
// remove the feedinfo of the mob that got despawned, if any
if (_FeedInfo.containsKey(npc.getObjectId()))
{
if (_FeedInfo.get(npc.getObjectId()) == player.getObjectId())
{
_FeedInfo.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();
}
}
L2NpcTemplate template = NpcData.getInstance().getTemplate(nextNpcId);
L2TamedBeastInstance nextNpc = new L2TamedBeastInstance(IdFactory.getInstance().getNextId(), template, player, food - FOODSKILLDIFF, npc.getX(), npc.getY(), npc.getZ());
nextNpc.setRunning();
Q00020_BringUpWithLove.checkJewelOfInnocence(player);
// also, perform a rare random chat
if (getRandom(20) == 0)
{
NpcStringId message = NpcStringId.getNpcStringId(getRandom(2024, 2029));
NpcSay packet = new NpcSay(nextNpc, 0, 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
_FeedInfo.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 (_FeedInfo.get(npc.getObjectId()) == player.getObjectId())
{
_FeedInfo.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
_FeedInfo.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 (_GrowthCapableMobs.containsKey(npcId))
{
growthLevel = _GrowthCapableMobs.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) && _FeedInfo.containsKey(objectId))
{
return super.onSkillSee(npc, caster, skill, targets, isSummon);
}
_FeedInfo.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 (_GrowthCapableMobs.containsKey(npcId))
{
// do nothing if this mob doesn't eat the specified food (food gets consumed but has no effect).
if (_GrowthCapableMobs.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, 0, message);
if (message.getParamCount() > 0) // player name, $s1
{
packet.addStringParameter(caster.getName());
}
npc.broadcastPacket(packet);
}
if ((growthLevel > 0) && (_FeedInfo.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) < _GrowthCapableMobs.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, 0, 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 (_FeedInfo.containsKey(npc.getObjectId()))
{
_FeedInfo.remove(npc.getObjectId());
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new FeedableBeasts();
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2004-2014 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.Config;
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.getSummon() : 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;
if (Config.GEODATA > 0)
{
destination = GeoData.getInstance().moveCheck(npc.getX(), npc.getY(), npc.getZ(), posX, posY, posZ, attacker.getInstanceId());
}
else
{
destination = new Location(posX, posY, posZ);
}
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
return super.onAttack(npc, attacker, damage, isSummon);
}
public static void main(String[] args)
{
new FleeMonsters();
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2004-2014 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();
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2004-2014 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.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.clientpackets.Say2;
/**
* 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, Say2.NPC_SHOUT, NpcStringId.INTRUDER_DETECTED);
}
else
{
broadcastNpcSay(npc, Say2.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, Say2.NPC_ALL, NpcStringId.YOU_GUYS_ARE_DETECTED);
}
else
{
broadcastNpcSay(npc, Say2.NPC_ALL, 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();
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2004-2014 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();
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2004-2014 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.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
/**
* Isle of Prayer AI.
* @author Zoey76
*/
public final class IsleOfPrayer extends AbstractNpcAI
{
// Items
private static final int YELLOW_SEED_OF_EVIL_SHARD = 9593;
private static final int GREEN_SEED_OF_EVIL_SHARD = 9594;
private static final int BLUE_SEED_OF_EVIL_SHARD = 9595;
private static final int RED_SEED_OF_EVIL_SHARD = 9596;
// Monsters
private static final Map<Integer, ItemChanceHolder> MONSTERS = new HashMap<>();
static
{
MONSTERS.put(22257, new ItemChanceHolder(YELLOW_SEED_OF_EVIL_SHARD, 2087)); // Island Guardian
MONSTERS.put(22258, new ItemChanceHolder(YELLOW_SEED_OF_EVIL_SHARD, 2147)); // White Sand Mirage
MONSTERS.put(22259, new ItemChanceHolder(YELLOW_SEED_OF_EVIL_SHARD, 2642)); // Muddy Coral
MONSTERS.put(22260, new ItemChanceHolder(YELLOW_SEED_OF_EVIL_SHARD, 2292)); // Kleopora
MONSTERS.put(22261, new ItemChanceHolder(GREEN_SEED_OF_EVIL_SHARD, 1171)); // Seychelles
MONSTERS.put(22262, new ItemChanceHolder(GREEN_SEED_OF_EVIL_SHARD, 1173)); // Naiad
MONSTERS.put(22263, new ItemChanceHolder(GREEN_SEED_OF_EVIL_SHARD, 1403)); // Sonneratia
MONSTERS.put(22264, new ItemChanceHolder(GREEN_SEED_OF_EVIL_SHARD, 1207)); // Castalia
MONSTERS.put(22265, new ItemChanceHolder(RED_SEED_OF_EVIL_SHARD, 575)); // Chrysocolla
MONSTERS.put(22266, new ItemChanceHolder(RED_SEED_OF_EVIL_SHARD, 493)); // Pythia
MONSTERS.put(22267, new ItemChanceHolder(RED_SEED_OF_EVIL_SHARD, 770)); // Dark Water Dragon
MONSTERS.put(22268, new ItemChanceHolder(BLUE_SEED_OF_EVIL_SHARD, 987)); // Shade
MONSTERS.put(22269, new ItemChanceHolder(BLUE_SEED_OF_EVIL_SHARD, 995)); // Shade
MONSTERS.put(22270, new ItemChanceHolder(BLUE_SEED_OF_EVIL_SHARD, 1008)); // Water Dragon Detractor
MONSTERS.put(22271, new ItemChanceHolder(BLUE_SEED_OF_EVIL_SHARD, 1008)); // Water Dragon Detractor
}
private IsleOfPrayer()
{
super(IsleOfPrayer.class.getSimpleName(), "ai/group_template");
addKillId(MONSTERS.keySet());
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
final ItemChanceHolder holder = MONSTERS.get(npc.getId());
if (getRandom(10000) <= holder.getChance())
{
npc.dropItem(killer, holder);
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new IsleOfPrayer();
}
}

View File

@@ -0,0 +1,144 @@
/*
* Copyright (C) 2004-2014 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.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.ValidateLocation;
/**
* Lair of Antharas AI.
* @author St3eT, UnAfraid
*/
public final class LairOfAntharas extends AbstractNpcAI
{
// NPC
final private static int KNORIKS = 22857;
final private static int DRAGON_KNIGHT = 22844;
final private static int DRAGON_KNIGHT2 = 22845;
final private static int ELITE_DRAGON_KNIGHT = 22846;
final private static int DRAGON_GUARD = 22852;
final private static int DRAGON_MAGE = 22853;
// Misc
final private static int KNIGHT_CHANCE = 30;
final private static int KNORIKS_CHANCE = 60;
final private static int KNORIKS_CHANCE2 = 50;
private LairOfAntharas()
{
super(LairOfAntharas.class.getSimpleName(), "ai/group_template");
addKillId(DRAGON_KNIGHT, DRAGON_KNIGHT2, DRAGON_GUARD, DRAGON_MAGE);
addSpawnId(DRAGON_KNIGHT, DRAGON_KNIGHT2, DRAGON_GUARD, DRAGON_MAGE);
addMoveFinishedId(DRAGON_GUARD, DRAGON_MAGE);
addAggroRangeEnterId(KNORIKS);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("CHECK_HOME") && (npc != null) && !npc.isDead())
{
if ((npc.calculateDistance(npc.getSpawn().getLocation(), false, false) > 10) && !npc.isInCombat())
{
((L2Attackable) npc).returnHome();
}
else if ((npc.getHeading() != npc.getSpawn().getHeading()) && !npc.isInCombat())
{
npc.setHeading(npc.getSpawn().getHeading());
npc.broadcastPacket(new ValidateLocation(npc));
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
if (npc.isScriptValue(0) && (getRandom(100) < KNORIKS_CHANCE))
{
if (getRandom(100) < KNORIKS_CHANCE2)
{
npc.setScriptValue(1);
}
broadcastNpcSay(npc, Say2.NPC_SHOUT, NpcStringId.WHO_S_THERE_IF_YOU_DISTURB_THE_TEMPER_OF_THE_GREAT_LAND_DRAGON_ANTHARAS_I_WILL_NEVER_FORGIVE_YOU);
}
return super.onAggroRangeEnter(npc, player, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
switch (npc.getId())
{
case DRAGON_KNIGHT:
{
if (getRandom(100) > KNIGHT_CHANCE)
{
final L2Npc newKnight = addSpawn(DRAGON_KNIGHT2, npc, false, 0, true);
npc.deleteMe();
broadcastNpcSay(newKnight, Say2.NPC_SHOUT, NpcStringId.THOSE_WHO_SET_FOOT_IN_THIS_PLACE_SHALL_NOT_LEAVE_ALIVE);
addAttackPlayerDesire(newKnight, killer);
}
break;
}
case DRAGON_KNIGHT2:
{
if (getRandom(100) > KNIGHT_CHANCE)
{
final L2Npc eliteKnight = addSpawn(ELITE_DRAGON_KNIGHT, npc, false, 0, true);
npc.deleteMe();
broadcastNpcSay(eliteKnight, Say2.NPC_SHOUT, NpcStringId.IF_YOU_WISH_TO_SEE_HELL_I_WILL_GRANT_YOU_YOUR_WISH);
addAttackPlayerDesire(eliteKnight, killer);
}
break;
}
case DRAGON_GUARD:
case DRAGON_MAGE:
{
cancelQuestTimer("CHECK_HOME", npc, null);
break;
}
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onSpawn(L2Npc npc)
{
final L2Attackable mob = (L2Attackable) npc;
mob.setOnKillDelay(0);
if ((npc.getId() == DRAGON_GUARD) || (npc.getId() == DRAGON_MAGE))
{
mob.setIsNoRndWalk(true);
startQuestTimer("CHECK_HOME", 10000, npc, null, true);
}
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new LairOfAntharas();
}
}

View File

@@ -0,0 +1,455 @@
/*
* Copyright (C) 2004-2014 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.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;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* 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, Say2.NPC_ALL, ON_ATTACK_MSG[getRandom(ON_ATTACK_MSG.length)]);
}
}
}
return super.onAttack(npc, attacker, damage, isSummon);
}
public static void main(String[] args)
{
new MinionSpawnManager();
}
}

View File

@@ -0,0 +1,296 @@
/*
* Copyright (C) 2004-2014 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.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;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* 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, Say2.NPC_ALL, 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, Say2.ALL, 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, Say2.NPC_ALL, 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, Say2.NPC_ALL, 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();
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2004-2014 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();
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2004-2014 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();
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2004-2014 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.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.clientpackets.Say2;
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, Say2.NPC_ALL, MONSTERS_MSG[i], player.getName());
}
else
{
broadcastNpcSay(npc, Say2.NPC_ALL, 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, Say2.NPC_ALL, MONSTERS_ASSIST_MSG[getRandom(3)]);
}
}
npc.setScriptValue(1);
}
return super.onAttack(npc, player, damage, isSummon);
}
public static void main(String[] args)
{
new PlainsOfDion();
}
}

View File

@@ -0,0 +1,244 @@
/*
* Copyright (C) 2004-2014 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();
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2004-2014 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.Map;
import javolution.util.FastMap;
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 FastMap<>();
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();
}
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2004-2014 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.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.clientpackets.Say2;
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(), Say2.NPC_ALL, 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.getSummon() : 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();
}
}

View File

@@ -0,0 +1,515 @@
/*
* Copyright (C) 2004-2014 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.handler.IItemHandler;
import com.l2jserver.gameserver.handler.ItemHandler;
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;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.util.Util;
/**
* Primeval Isle AI.
* @author St3eT
*/
public final class PrimevalIsle extends AbstractNpcAI
{
// NPC
private static final int EGG = 18344; // Ancient Egg
private static final int SAILREN = 29065; // Sailren
private static final int ORNIT = 22742; // Ornithomimus
private static final int DEINO = 22743; // Deinonychus
private static final int[] SPRIGNANT =
{
18345, // Sprigant (Anesthesia)
18346, // Sprigant (Deadly Poison)
};
private static final int[] MONSTERS =
{
22196, // Velociraptor
22198, // Velociraptor
22200, // Ornithomimus
22202, // Ornithomimus
22203, // Deinonychus
22205, // Deinonychus
22208, // Pachycephalosaurus
22210, // Pachycephalosaurus
22211, // Wild Strider
22213, // Wild Strider
22223, // Velociraptor
22224, // Ornithomimus
22225, // Deinonychus
22226, // Pachycephalosaurus
22227, // Wild Strider
22742, // Ornithomimus
22743, // Deinonychus
};
private static final int[] TREX =
{
22215, // Tyrannosaurus
22216, // Tyrannosaurus
22217, // Tyrannosaurus
};
private static final int[] VEGETABLE =
{
22200, // Ornithomimus
22201, // Ornithomimus
22202, // Ornithomimus
22203, // Deinonychus
22204, // Deinonychus
22205, // Deinonychus
22224, // Ornithomimus
22225, // Deinonychus
};
// Item
private static final int DEINONYCHUS = 14828; // Deinonychus Mesozoic Stone
// Skill
private static final SkillHolder ANESTHESIA = new SkillHolder(5085, 1); // Anesthesia
private static final SkillHolder DEADLY_POISON = new SkillHolder(5086, 1); // Deadly Poison
private static final SkillHolder SELFBUFF1 = new SkillHolder(5087, 1); // Berserk
private static final SkillHolder SELFBUFF2 = new SkillHolder(5087, 2); // Berserk
private static final SkillHolder LONGRANGEDMAGIC1 = new SkillHolder(5120, 1); // Stun
private static final SkillHolder PHYSICALSPECIAL1 = new SkillHolder(5083, 4); // Stun
private static final SkillHolder PHYSICALSPECIAL2 = new SkillHolder(5081, 4); // Silence
private static final SkillHolder PHYSICALSPECIAL3 = new SkillHolder(5082, 4); // NPC Spinning, Slashing Trick
private static final SkillHolder CREW_SKILL = new SkillHolder(6172, 1); // Presentation - Tyranno
private static final SkillHolder INVIN_BUFF_ON = new SkillHolder(5225, 1); // Invincible
private PrimevalIsle()
{
super(PrimevalIsle.class.getSimpleName(), "ai/group_template");
addSpawnId(TREX);
addSpawnId(SPRIGNANT);
addSpawnId(MONSTERS);
addAggroRangeEnterId(TREX);
addSpellFinishedId(TREX);
addAttackId(EGG);
addAttackId(TREX);
addAttackId(MONSTERS);
addKillId(EGG, SAILREN, DEINO, ORNIT);
addSeeCreatureId(TREX);
addSeeCreatureId(MONSTERS);
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
if (skill.getId() == CREW_SKILL.getSkillId())
{
startQuestTimer("START_INVUL", 4000, npc, null);
final L2Npc target = (L2Npc) npc.getTarget();
if (target != null)
{
target.doDie(npc);
}
}
if (npc.isInCombat())
{
final L2Attackable mob = (L2Attackable) npc;
final L2Character target = mob.getMostHated();
if (((npc.getCurrentHp() / npc.getMaxHp()) * 100) < 60)
{
if (skill.getId() == SELFBUFF1.getSkillId())
{
npc.setScriptValue(3);
if ((target != null))
{
npc.setTarget(target);
mob.setIsRunning(true);
mob.addDamageHate(target, 0, 555);
mob.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
}
}
}
else if (((npc.getCurrentHp() / npc.getMaxHp()) * 100) < 30)
{
if (skill.getId() == SELFBUFF1.getSkillId())
{
npc.setScriptValue(1);
if ((target != null))
{
npc.setTarget(target);
mob.setIsRunning(true);
mob.addDamageHate(target, 0, 555);
mob.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
}
}
else if (skill.getId() == SELFBUFF2.getSkillId())
{
npc.setScriptValue(5);
if ((target != null))
{
npc.setTarget(target);
mob.setIsRunning(true);
mob.addDamageHate(target, 0, 555);
mob.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
}
}
}
}
return super.onSpellFinished(npc, player, skill);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "USE_SKILL":
{
if ((npc != null) && !npc.isDead())
{
npc.doCast((npc.getId() == SPRIGNANT[0] ? ANESTHESIA.getSkill() : DEADLY_POISON.getSkill()));
startQuestTimer("USE_SKILL", 15000, npc, null);
}
break;
}
case "GHOST_DESPAWN":
{
if ((npc != null) && !npc.isDead())
{
if (!npc.isInCombat())
{
npc.deleteMe();
}
else
{
startQuestTimer("GHOST_DESPAWN", 1800000, npc, null);
}
}
break;
}
case "TREX_ATTACK":
{
if ((npc != null) && (player != null))
{
npc.setScriptValue(0);
if (player.isInsideRadius(npc, 800, true, false))
{
npc.setTarget(player);
npc.doCast(LONGRANGEDMAGIC1.getSkill());
addAttackPlayerDesire(npc, player);
}
}
break;
}
case "START_INVUL":
{
if ((npc != null) && !npc.isDead())
{
npc.doCast(INVIN_BUFF_ON.getSkill());
startQuestTimer("START_INVUL_2", 30000, npc, null);
}
break;
}
case "START_INVUL_2":
{
if ((npc != null) && !npc.isDead())
{
INVIN_BUFF_ON.getSkill().applyEffects(npc, npc);
}
break;
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSeeCreature(L2Npc npc, L2Character creature, boolean isSummon)
{
if (Util.contains(MONSTERS, npc.getId()))
{
if (creature.isPlayer())
{
final L2Attackable mob = (L2Attackable) npc;
final int ag_type = npc.getTemplate().getParameters().getInt("ag_type", 0);
final int probPhysicalSpecial1 = npc.getTemplate().getParameters().getInt("ProbPhysicalSpecial1", 0);
final int probPhysicalSpecial2 = npc.getTemplate().getParameters().getInt("ProbPhysicalSpecial2", 0);
final SkillHolder physicalSpecial1 = npc.getTemplate().getParameters().getObject("PhysicalSpecial1", SkillHolder.class);
final SkillHolder physicalSpecial2 = npc.getTemplate().getParameters().getObject("PhysicalSpecial2", SkillHolder.class);
if (((getRandom(100) < 30) && (npc.getId() == DEINO)) || ((npc.getId() == ORNIT) && npc.isScriptValue(0)))
{
mob.clearAggroList();
npc.setScriptValue(1);
npc.setRunning();
final int distance = 3000;
final int heading = Util.calculateHeadingFrom(creature, npc);
final double angle = Util.convertHeadingToDegree(heading);
final double radian = Math.toRadians(angle);
final double sin = Math.sin(radian);
final double cos = Math.cos(radian);
final int newX = (int) (npc.getX() + (cos * distance));
final int newY = (int) (npc.getY() + (sin * distance));
final Location loc = GeoData.getInstance().moveCheck(npc.getX(), npc.getY(), npc.getZ(), newX, newY, npc.getZ(), npc.getInstanceId());
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, loc, 0);
}
else if (ag_type == 1)
{
if (getRandom(100) <= (probPhysicalSpecial1 * npc.getVariables().getInt("SKILL_MULTIPLER")))
{
if (!npc.isSkillDisabled(physicalSpecial1.getSkillId()))
{
npc.setTarget(creature);
npc.doCast(physicalSpecial1.getSkill());
}
}
else if (getRandom(100) <= (probPhysicalSpecial2 * npc.getVariables().getInt("SKILL_MULTIPLER")))
{
if (!npc.isSkillDisabled(physicalSpecial2.getSkill()))
{
npc.setTarget(creature);
npc.doCast(physicalSpecial2.getSkill());
}
}
}
}
}
else if (Util.contains(VEGETABLE, creature.getId()))
{
npc.setTarget(creature);
npc.doCast(CREW_SKILL.getSkill());
npc.setIsRunning(true);
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, creature);
}
return super.onSeeCreature(npc, creature, isSummon);
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
if (npc.isScriptValue(0))
{
npc.setScriptValue(1);
broadcastNpcSay(npc, Say2.NPC_ALL, "?");
((L2Attackable) npc).clearAggroList();
startQuestTimer("TREX_ATTACK", 6000, npc, player);
}
return super.onAggroRangeEnter(npc, player, isSummon);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
if (npc.getId() == EGG)
{
if ((getRandom(100) <= 80) && npc.isScriptValue(0))
{
npc.setScriptValue(1);
final L2Playable playable = isSummon ? attacker.getSummon() : attacker;
for (L2Character characters : npc.getKnownList().getKnownCharactersInRadius(500))
{
if ((characters != null) && (characters.isAttackable()) && (getRandomBoolean()))
{
L2Attackable monster = (L2Attackable) characters;
addAttackPlayerDesire(monster, playable);
}
}
}
}
else if (Util.contains(TREX, npc.getId()))
{
final L2Attackable mob = (L2Attackable) npc;
final L2Character target = mob.getMostHated();
if (((npc.getCurrentHp() / npc.getMaxHp()) * 100) <= 30)
{
if (npc.isScriptValue(3))
{
if (!npc.isSkillDisabled(SELFBUFF1.getSkill()))
{
npc.doCast(SELFBUFF1.getSkill());
}
}
else if (npc.isScriptValue(1))
{
if (!npc.isSkillDisabled(SELFBUFF2.getSkill()))
{
npc.doCast(SELFBUFF2.getSkill());
}
}
}
else if ((((npc.getCurrentHp() / npc.getMaxHp()) * 100) <= 60) && (npc.isScriptValue(3)))
{
if (!npc.isSkillDisabled(SELFBUFF1.getSkill()))
{
npc.doCast(SELFBUFF1.getSkill());
}
}
if (Util.calculateDistance(npc, attacker, true, false) > 100)
{
if (!npc.isSkillDisabled(LONGRANGEDMAGIC1.getSkill()) && (getRandom(100) <= (10 * npc.getScriptValue())))
{
npc.setTarget(attacker);
npc.doCast(LONGRANGEDMAGIC1.getSkill());
}
}
else
{
if (!npc.isSkillDisabled(LONGRANGEDMAGIC1.getSkill()) && (getRandom(100) <= (10 * npc.getScriptValue())))
{
npc.setTarget(target);
npc.doCast(LONGRANGEDMAGIC1.getSkill());
}
if (!npc.isSkillDisabled(PHYSICALSPECIAL1.getSkill()) && (getRandom(100) <= (5 * npc.getScriptValue())))
{
npc.setTarget(target);
npc.doCast(PHYSICALSPECIAL1.getSkill());
}
if (!npc.isSkillDisabled(PHYSICALSPECIAL2.getSkill()) && (getRandom(100) <= (3 * npc.getScriptValue())))
{
npc.setTarget(target);
npc.doCast(PHYSICALSPECIAL2.getSkill());
}
if (!npc.isSkillDisabled(PHYSICALSPECIAL3.getSkill()) && (getRandom(100) <= (5 * npc.getScriptValue())))
{
npc.setTarget(target);
npc.doCast(PHYSICALSPECIAL3.getSkill());
}
}
}
else
{
L2Character target = null;
final int probPhysicalSpecial1 = npc.getTemplate().getParameters().getInt("ProbPhysicalSpecial1", 0);
final int probPhysicalSpecial2 = npc.getTemplate().getParameters().getInt("ProbPhysicalSpecial2", 0);
final SkillHolder selfRangeBuff1 = npc.getTemplate().getParameters().getObject("SelfRangeBuff1", SkillHolder.class);
final SkillHolder physicalSpecial1 = npc.getTemplate().getParameters().getObject("PhysicalSpecial1", SkillHolder.class);
final SkillHolder physicalSpecial2 = npc.getTemplate().getParameters().getObject("PhysicalSpecial2", SkillHolder.class);
if (((npc.getCurrentHp() / npc.getMaxHp()) * 100) <= 50)
{
npc.getVariables().set("SKILL_MULTIPLER", 2);
}
else
{
npc.getVariables().set("SKILL_MULTIPLER", 1);
}
if ((((npc.getCurrentHp() / npc.getMaxHp()) * 100) <= 30) && (npc.getVariables().getInt("SELFBUFF_USED") == 0))
{
final L2Attackable mob = (L2Attackable) npc;
target = mob.getMostHated();
mob.clearAggroList();
if (!npc.isSkillDisabled(selfRangeBuff1.getSkillId()))
{
npc.getVariables().set("SELFBUFF_USED", 1);
npc.doCast(selfRangeBuff1.getSkill());
npc.setIsRunning(true);
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
}
}
if (target != null)
{
if (getRandom(100) <= (probPhysicalSpecial1 * npc.getVariables().getInt("SKILL_MULTIPLER")))
{
if (!npc.isSkillDisabled(physicalSpecial1.getSkill()))
{
npc.setTarget(target);
npc.doCast(physicalSpecial1.getSkill());
}
}
if (getRandom(100) <= (probPhysicalSpecial2 * npc.getVariables().getInt("SKILL_MULTIPLER")))
{
if (!npc.isSkillDisabled(physicalSpecial2.getSkill()))
{
npc.setTarget(target);
npc.doCast(physicalSpecial2.getSkill());
}
}
}
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
if ((npc.getId() == DEINO) || ((npc.getId() == ORNIT) && !npc.isScriptValue(1)))
{
return super.onKill(npc, killer, isSummon);
}
if ((npc.getId() == SAILREN) || (getRandom(100) < 3))
{
final L2PcInstance player = npc.getId() == SAILREN ? getRandomPartyMember(killer) : killer;
if (player.getInventory().getSize(false) <= (player.getInventoryLimit() * 0.8))
{
giveItems(player, DEINONYCHUS, 1);
final L2ItemInstance summonItem = player.getInventory().getItemByItemId(DEINONYCHUS);
final IItemHandler handler = ItemHandler.getInstance().getHandler(summonItem.getEtcItem());
if ((handler != null) && !player.hasPet())
{
handler.useItem(player, summonItem, true);
}
showOnScreenMsg(player, NpcStringId.LIFE_STONE_FROM_THE_BEGINNING_ACQUIRED, 2, 6000);
}
else
{
showOnScreenMsg(player, NpcStringId.WHEN_INVENTORY_WEIGHT_NUMBER_ARE_MORE_THAN_80_THE_LIFE_STONE_FROM_THE_BEGINNING_CANNOT_BE_ACQUIRED, 2, 6000);
}
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onSpawn(L2Npc npc)
{
if (Util.contains(SPRIGNANT, npc.getId()))
{
startQuestTimer("USE_SKILL", 15000, npc, null);
}
else if (Util.contains(TREX, npc.getId()))
{
final int collectGhost = npc.getTemplate().getParameters().getInt("CollectGhost", 0);
final int collectDespawn = npc.getTemplate().getParameters().getInt("CollectGhostDespawnTime", 30);
if (collectGhost == 1)
{
startQuestTimer("GHOST_DESPAWN", collectDespawn * 60000, npc, null);
}
}
else
{
npc.getVariables().set("SELFBUFF_USED", 0);
npc.getVariables().set("SKILL_MULTIPLER", 1);
}
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new PrimevalIsle();
}
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright (C) 2004-2014 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.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;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* 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, Say2.ALL, 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, Say2.ALL, 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();
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright (C) 2004-2014 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.Map;
import javolution.util.FastMap;
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 Map<Integer, Location[]> SPAWN_POINTS = new FastMap<>();
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();
}
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2004-2014 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.NpcData;
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.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.util.Util;
/**
* Range Guard AI.
* @author St3eT.
*/
public final class RangeGuard extends AbstractNpcAI
{
// Skill
private static SkillHolder ULTIMATE_DEFENSE = new SkillHolder(5044, 3); // NPC Ultimate Defense
//@formatter:off
private static final int[] NOT_ALLOWED_SKILLS =
{
15, 28, // Charm / Aggression
51, 65, // Lure / Horror
106, 115, // Veil / Power Break
122, 127, // Hex / Hamstring
254, 352, // Spoil / Shield Bash
353, 358, // Shield Slam / Bluff
402, 403, // Arrest / Shackle
412, 485, // Sand Bomb / Disarm
501, 511, // Violent Temper / Temptation
522, 531, // Real Target / Critical Wound
680, 695, // Divine Knight Hate / Divine Wizard Divine Cloud
696, 716, // Divine Wizard Surrender to Divine / Zaken Hold
775, 792, // Weapon Blockade / Betrayal Mark
1042, 1049, // Hold Undead / Requiem
1069, 1071, // Sleep / Surrender To Water
1072, 1074, // Sleeping Cloud / Surrender To Wind
1083, 1097, // Surrender To Fire / Dreaming Spirit
1092, 1064, // Fear / Silence
1160, 1164, // Slow / Curse Weakness
1169, 1170, // Curse Fear / Anchor
1201, 1206, // Dryad Root / Wind Shackle
1222, 1223, // Curse Chaos / Surrender To Earth
1224, 1263, // Surrender To Poison / Curse Gloom
1269, 1336, // Curse Disease / Curse of Doom
1337, 1338, // Curse of Abyss / Arcane Chaos
1358, 1359, // Block Shield / Block Wind Walk
1386, 1394, // Arcane Disruption / Trance
1396, 1445, // Magical BackFire / Surrender to Dark
1446, 1447, // Shadow Bind / Voice Bind
1481, 1482, // Oblivion / Weak Constitution
1483, 1484, // Thin Skin / Enervation
1485, 1486, // Spite / Mental Impoverish
1511, 1524, // Curse of Life Flow / Surrender to the Divine
1529, // Soul Web
};
//@formatter:on
// Misc
private static final int MIN_DISTANCE = 150;
private RangeGuard()
{
super(RangeGuard.class.getSimpleName(), "ai/group_template");
for (L2NpcTemplate template : NpcData.getInstance().getAllNpcOfClassType("L2Monster"))
{
if (template.getParameters().getInt("LongRangeGuardRate", -1) > 0)
{
addAttackId(template.getId());
}
}
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
{
final L2Playable playable = (isSummon) ? attacker.getSummon() : attacker;
final int longRangeGuardRate = npc.getTemplate().getParameters().getInt("LongRangeGuardRate");
final double distance = Util.calculateDistance(npc, playable, true, false);
if (npc.isAffectedBySkill(ULTIMATE_DEFENSE.getSkillId()) && (distance <= MIN_DISTANCE))
{
npc.stopSkillEffects(true, ULTIMATE_DEFENSE.getSkillId());
}
else if ((distance > MIN_DISTANCE) && !npc.isSkillDisabled(ULTIMATE_DEFENSE.getSkillId()) && !((skill != null) && Util.contains(NOT_ALLOWED_SKILLS, skill.getId())) && (getRandom(100) < longRangeGuardRate))
{
npc.setTarget(npc);
npc.doCast(ULTIMATE_DEFENSE.getSkill());
}
return super.onAttack(npc, attacker, damage, isSummon, skill);
}
public static void main(String[] args)
{
new RangeGuard();
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2004-2014 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.L2Object;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.skills.Skill;
/**
* Remnants AI.
* @author DS
*/
public final class Remnants extends AbstractNpcAI
{
private static final int[] NPCS =
{
18463,
18464,
18465
};
private static final int SKILL_HOLY_WATER = 2358;
// TODO: Find retail strings.
// private static final String MSG = "The holy water affects Remnants Ghost. You have freed his soul.";
// private static final String MSG_DEREK = "The holy water affects Derek. You have freed his soul.";
private Remnants()
{
super(Remnants.class.getSimpleName(), "ai/group_template");
addSpawnId(NPCS);
addSkillSeeId(NPCS);
// Do not override onKill for Derek here. Let's make global Hellbound manipulations in Engine where it is possible.
}
@Override
public final String onSpawn(L2Npc npc)
{
npc.setIsMortal(false);
return super.onSpawn(npc);
}
@Override
public final String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
{
if (skill.getId() == SKILL_HOLY_WATER)
{
if (!npc.isDead())
{
if ((targets.length > 0) && (targets[0] == npc))
{
if (npc.getCurrentHp() < (npc.getMaxHp() * 0.02)) // Lower, than 2%
{
npc.doDie(caster);
//@formatter:off
/*if (npc.getNpcId() == DEREK)
{
caster.sendMessage(MSG_DEREK);
}
else
{
caster.sendMessage(MSG);
}*/
//@formatter:on
}
}
}
}
return super.onSkillSee(npc, caster, skill, targets, isSummon);
}
public static void main(String[] args)
{
new Remnants();
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2004-2014 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.holders.SkillHolder;
/**
* Sandstorms AI.
* @author Ectis
*/
public class Sandstorms extends AbstractNpcAI
{
// NPCs
private static final int SANDSTORM = 32350;
// Skills
private static final SkillHolder GUST = new SkillHolder(5435, 1); // Gust
public Sandstorms()
{
super(Sandstorms.class.getSimpleName(), "ai/group_template");
addAggroRangeEnterId(SANDSTORM); // Sandstorm
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
npc.setTarget(player);
npc.doCast(GUST.getSkill());
return super.onAggroRangeEnter(npc, player, isSummon);
}
public static void main(String[] args)
{
new Sandstorms();
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2004-2014 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();
}
}

View File

@@ -0,0 +1,321 @@
/*
* Copyright (C) 2004-2014 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.datatables.SpawnTable;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Spawn;
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;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.util.Util;
/**
* Sel Mahum Training Ground AI for drill groups.
* @author GKR
*/
public final class SelMahumDrill extends AbstractNpcAI
{
private static final int[] MAHUM_CHIEFS =
{
22775, // Sel Mahum Drill Sergeant
22776, // Sel Mahum Training Officer
22778, // Sel Mahum Drill Sergeant
};
private static final int[] MAHUM_SOLDIERS =
{
22780, // Sel Mahum Recruit
22782, // Sel Mahum Recruit
22783, // Sel Mahum Soldier
22784, // Sel Mahum Recruit
22785, // Sel Mahum Soldier
};
private static final int[] CHIEF_SOCIAL_ACTIONS =
{
1,
4,
5,
7
};
private static final Actions[] SOLDIER_SOCIAL_ACTIONS =
{
Actions.SCE_TRAINING_ACTION_A,
Actions.SCE_TRAINING_ACTION_B,
Actions.SCE_TRAINING_ACTION_C,
Actions.SCE_TRAINING_ACTION_D
};
private static final NpcStringId[] CHIEF_FSTRINGS =
{
NpcStringId.HOW_DARE_YOU_ATTACK_MY_RECRUITS,
NpcStringId.WHO_IS_DISRUPTING_THE_ORDER
};
private static final NpcStringId[] SOLDIER_FSTRINGS =
{
NpcStringId.THE_DRILLMASTER_IS_DEAD,
NpcStringId.LINE_UP_THE_RANKS
};
// Chiefs event broadcast range
private static final int TRAINING_RANGE = 1000;
private static enum Actions
{
SCE_TRAINING_ACTION_A(4, -1, 2, 2333),
SCE_TRAINING_ACTION_B(1, -1, 2, 4333),
SCE_TRAINING_ACTION_C(6, 5, 4, 1000),
SCE_TRAINING_ACTION_D(7, -1, 2, 1000);
private final int _socialActionId;
private final int _altSocialActionId;
private final int _repeatCount;
private final int _repeatInterval;
private Actions(int socialActionId, int altSocialActionId, int repeatCount, int repeatInterval)
{
_socialActionId = socialActionId;
_altSocialActionId = altSocialActionId;
_repeatCount = repeatCount;
_repeatInterval = repeatInterval;
}
protected int getSocialActionId()
{
return _socialActionId;
}
protected int getAltSocialActionId()
{
return _altSocialActionId;
}
protected int getRepeatCount()
{
return _repeatCount;
}
protected int getRepeatInterval()
{
return _repeatInterval;
}
}
private SelMahumDrill()
{
super(SelMahumDrill.class.getSimpleName(), "ai/group_template");
addAttackId(MAHUM_SOLDIERS);
addKillId(MAHUM_CHIEFS);
addEventReceivedId(MAHUM_CHIEFS);
addEventReceivedId(MAHUM_SOLDIERS);
addSpawnId(MAHUM_CHIEFS);
addSpawnId(MAHUM_SOLDIERS);
// Start global return home timer
startQuestTimer("return_home", 120000, null, null, true);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "do_social_action":
{
if ((npc != null) && !npc.isDead())
{
if (Util.contains(MAHUM_CHIEFS, npc.getId()))
{
if ((npc.getVariables().getInt("BUSY_STATE") == 0) && (npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_ACTIVE) && npc.staysInSpawnLoc())
{
final int idx = getRandom(6);
if (idx <= (CHIEF_SOCIAL_ACTIONS.length - 1))
{
npc.broadcastSocialAction(CHIEF_SOCIAL_ACTIONS[idx]);
npc.getVariables().set("SOCIAL_ACTION_NEXT_INDEX", idx); // Pass social action index to soldiers via script value
npc.broadcastEvent("do_social_action", TRAINING_RANGE, null);
}
}
startQuestTimer("do_social_action", 15000, npc, null);
}
else if (Util.contains(MAHUM_SOLDIERS, npc.getId()))
{
handleSocialAction(npc, SOLDIER_SOCIAL_ACTIONS[npc.getVariables().getInt("SOCIAL_ACTION_NEXT_INDEX")], false);
}
}
break;
}
case "reset_busy_state":
{
if (npc != null)
{
npc.getVariables().remove("BUSY_STATE");
npc.disableCoreAI(false);
}
break;
}
case "return_home":
{
for (int npcId : MAHUM_SOLDIERS)
{
for (L2Spawn npcSpawn : SpawnTable.getInstance().getSpawns(npcId))
{
final L2Npc soldier = npcSpawn.getLastSpawn();
if ((soldier != null) && !soldier.isDead() && (npcSpawn.getName() != null) && npcSpawn.getName().startsWith("smtg_drill_group") && !soldier.staysInSpawnLoc() && ((soldier.getAI().getIntention() == CtrlIntention.AI_INTENTION_ACTIVE) || (soldier.getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE)))
{
soldier.setHeading(npcSpawn.getHeading());
soldier.teleToLocation(npcSpawn.getLocation(), false);
}
}
}
break;
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
if (getRandom(10) < 1)
{
npc.broadcastEvent("ATTACKED", 1000, null);
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onEventReceived(String eventName, L2Npc sender, L2Npc receiver, L2Object reference)
{
if ((receiver != null) && !receiver.isDead() && receiver.isInMySpawnGroup(sender))
{
switch (eventName)
{
case "do_social_action":
{
if (Util.contains(MAHUM_SOLDIERS, receiver.getId()))
{
final int actionIndex = sender.getVariables().getInt("SOCIAL_ACTION_NEXT_INDEX");
receiver.getVariables().set("SOCIAL_ACTION_NEXT_INDEX", actionIndex);
handleSocialAction(receiver, SOLDIER_SOCIAL_ACTIONS[actionIndex], true);
}
break;
}
case "CHIEF_DIED":
{
if (Util.contains(MAHUM_SOLDIERS, receiver.getId()))
{
if (getRandom(4) < 1)
{
broadcastNpcSay(receiver, Say2.NPC_ALL, SOLDIER_FSTRINGS[getRandom(2)]);
}
if (receiver.canBeAttacked())
{
((L2Attackable) receiver).clearAggroList();
}
receiver.disableCoreAI(true);
receiver.getVariables().set("BUSY_STATE", 1);
receiver.setIsRunning(true);
receiver.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location((receiver.getX() + getRandom(-800, 800)), (receiver.getY() + getRandom(-800, 800)), receiver.getZ(), receiver.getHeading()));
startQuestTimer("reset_busy_state", 5000, receiver, null);
}
break;
}
case "ATTACKED":
{
if (Util.contains(MAHUM_CHIEFS, receiver.getId()))
{
broadcastNpcSay(receiver, Say2.NPC_ALL, CHIEF_FSTRINGS[getRandom(2)]);
}
break;
}
}
}
return super.onEventReceived(eventName, sender, receiver, reference);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
npc.broadcastEvent("CHIEF_DIED", TRAINING_RANGE, null);
return null;
}
@Override
public String onSpawn(L2Npc npc)
{
if (Util.contains(MAHUM_CHIEFS, npc.getId()))
{
startQuestTimer("do_social_action", 15000, npc, null);
}
else if ((getRandom(18) < 1) && Util.contains(MAHUM_SOLDIERS, npc.getId()))
{
npc.getVariables().set("SOCIAL_ACTION_ALT_BEHAVIOR", 1);
}
// Restore AI handling by core
npc.disableCoreAI(false);
return super.onSpawn(npc);
}
private void handleSocialAction(L2Npc npc, Actions action, boolean firstCall)
{
if ((npc.getVariables().getInt("BUSY_STATE") != 0) || (npc.getAI().getIntention() != CtrlIntention.AI_INTENTION_ACTIVE) || !npc.staysInSpawnLoc())
{
return;
}
final int socialActionId = (npc.getVariables().getInt("SOCIAL_ACTION_ALT_BEHAVIOR") == 0) ? action.getSocialActionId() : action.getAltSocialActionId();
if (socialActionId < 0)
{
return;
}
if (firstCall)
{
npc.getVariables().set("SOCIAL_ACTION_REMAINED_COUNT", action.getRepeatCount());
}
npc.broadcastSocialAction(socialActionId);
final int remainedCount = npc.getVariables().getInt("SOCIAL_ACTION_REMAINED_COUNT");
if (remainedCount > 0)
{
npc.getVariables().set("SOCIAL_ACTION_REMAINED_COUNT", (remainedCount - 1));
startQuestTimer("do_social_action", action.getRepeatInterval(), npc, null);
}
}
public static void main(String[] args)
{
new SelMahumDrill();
}
}

View File

@@ -0,0 +1,405 @@
/*
* Copyright (C) 2004-2014 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.GameTimeController;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.Location;
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.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.util.Util;
/**
* Sel Mahum Training Ground AI for squads and chefs.
* @author GKR
*/
public final class SelMahumSquad extends AbstractNpcAI
{
// NPC's
private static final int CHEF = 18908;
private static final int FIRE = 18927;
private static final int STOVE = 18933;
private static final int OHS_Weapon = 15280;
private static final int THS_Weapon = 15281;
// Sel Mahum Squad Leaders
private static final int[] SQUAD_LEADERS =
{
22786,
22787,
22788
};
private static final NpcStringId[] CHEF_FSTRINGS =
{
NpcStringId.I_BROUGHT_THE_FOOD,
NpcStringId.COME_AND_EAT
};
private static final int FIRE_EFFECT_BURN = 1;
private static final int FIRE_EFFECT_NONE = 2;
private static final int MAHUM_EFFECT_EAT = 1;
private static final int MAHUM_EFFECT_SLEEP = 2;
private static final int MAHUM_EFFECT_NONE = 3;
private SelMahumSquad()
{
super(SelMahumSquad.class.getSimpleName(), "ai/group_template");
addAttackId(CHEF);
addAttackId(SQUAD_LEADERS);
addEventReceivedId(CHEF, FIRE, STOVE);
addEventReceivedId(SQUAD_LEADERS);
addFactionCallId(SQUAD_LEADERS);
addKillId(CHEF);
addMoveFinishedId(SQUAD_LEADERS);
addNodeArrivedId(CHEF);
addSkillSeeId(STOVE);
addSpawnId(CHEF, FIRE);
addSpawnId(SQUAD_LEADERS);
addSpellFinishedId(CHEF);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "chef_disable_reward":
{
npc.getVariables().set("REWARD_TIME_GONE", 1);
break;
}
case "chef_heal_player":
{
healPlayer(npc, player);
break;
}
case "chef_remove_invul":
{
if (npc.isMonster())
{
npc.setIsInvul(false);
npc.getVariables().remove("INVUL_REMOVE_TIMER_STARTED");
if ((player != null) && !player.isDead() && npc.getKnownList().knowsThePlayer(player))
{
addAttackPlayerDesire(npc, player);
}
}
break;
}
case "chef_set_invul":
{
if (!npc.isDead())
{
npc.setIsInvul(true);
}
break;
}
case "fire":
{
startQuestTimer("fire", 30000 + getRandom(5000), npc, null);
npc.setDisplayEffect(FIRE_EFFECT_NONE);
if (getRandom(GameTimeController.getInstance().isNight() ? 2 : 4) < 1)
{
npc.setDisplayEffect(FIRE_EFFECT_BURN); // fire burns
npc.broadcastEvent("SCE_CAMPFIRE_START", 600, null);
}
else
{
npc.setDisplayEffect(FIRE_EFFECT_NONE); // fire goes out
npc.broadcastEvent("SCE_CAMPFIRE_END", 600, null);
}
break;
}
case "fire_arrived":
{
// myself.i_quest0 = 1;
npc.setIsRunning(false);
npc.setTarget(npc);
if (npc.isNoRndWalk())
{
npc.doCast(SkillData.getInstance().getSkill(6331, 1));
npc.setDisplayEffect(MAHUM_EFFECT_SLEEP);
}
if (npc.getVariables().getInt("BUSY_STATE") == 1) // Eating
{
npc.doCast(SkillData.getInstance().getSkill(6332, 1));
npc.setDisplayEffect(MAHUM_EFFECT_EAT);
}
startQuestTimer("remove_effects", 300000, npc, null);
break;
}
case "notify_dinner":
{
npc.broadcastEvent("SCE_DINNER_EAT", 600, null);
break;
}
case "remove_effects":
{
// myself.i_quest0 = 0;
npc.setIsRunning(true);
npc.setDisplayEffect(MAHUM_EFFECT_NONE);
break;
}
case "reset_full_bottle_prize":
{
npc.getVariables().remove("FULL_BARREL_REWARDING_PLAYER");
break;
}
case "return_from_fire":
{
if (npc.isMonster() && !npc.isDead())
{
((L2MonsterInstance) npc).returnHome();
}
break;
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
{
if ((npc.getId() == CHEF) && (npc.getVariables().getInt("BUSY_STATE") == 0))
{
if (npc.getVariables().getInt("INVUL_REMOVE_TIMER_STARTED") == 0)
{
startQuestTimer("chef_remove_invul", 180000, npc, attacker);
startQuestTimer("chef_disable_reward", 60000, npc, null);
npc.getVariables().set("INVUL_REMOVE_TIMER_STARTED", 1);
}
startQuestTimer("chef_heal_player", 1000, npc, attacker);
startQuestTimer("chef_set_invul", 60000, npc, null);
npc.getVariables().set("BUSY_STATE", 1);
}
else if (Util.contains(SQUAD_LEADERS, npc.getId()))
{
handlePreAttackMotion(npc);
}
return super.onAttack(npc, attacker, damage, isSummon, skill);
}
@Override
public String onFactionCall(L2Npc npc, L2Npc caller, L2PcInstance attacker, boolean isSummon)
{
handlePreAttackMotion(npc);
return super.onFactionCall(npc, caller, attacker, isSummon);
}
@Override
public String onEventReceived(String eventName, L2Npc sender, L2Npc receiver, L2Object reference)
{
switch (eventName)
{
case "SCE_DINNER_CHECK":
{
if (receiver.getId() == FIRE)
{
receiver.setDisplayEffect(FIRE_EFFECT_BURN);
final L2Npc stove = addSpawn(STOVE, receiver.getX(), receiver.getY(), receiver.getZ() + 100, 0, false, 0);
stove.setSummoner(receiver);
startQuestTimer("notify_dinner", 2000, receiver, null); // @SCE_DINNER_EAT
broadcastNpcSay(sender, Say2.NPC_ALL, CHEF_FSTRINGS[getRandom(2)], 1250);
}
break;
}
case "SCE_CAMPFIRE_START":
{
if (!receiver.isNoRndWalk() && !receiver.isDead() && (receiver.getAI().getIntention() != CtrlIntention.AI_INTENTION_ATTACK) && Util.contains(SQUAD_LEADERS, receiver.getId()))
{
receiver.setIsNoRndWalk(true); // Moving to fire - i_ai0 = 1
receiver.setIsRunning(true);
final Location loc = sender.getPointInRange(100, 200);
loc.setHeading(receiver.getHeading());
receiver.stopMove(null);
receiver.getVariables().set("DESTINATION_X", loc.getX());
receiver.getVariables().set("DESTINATION_Y", loc.getY());
receiver.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, loc);
}
break;
}
case "SCE_CAMPFIRE_END":
{
if ((receiver.getId() == STOVE) && (receiver.getSummoner() == sender))
{
receiver.deleteMe();
}
else if ((receiver.getAI().getIntention() != CtrlIntention.AI_INTENTION_ATTACK) && Util.contains(SQUAD_LEADERS, receiver.getId()))
{
receiver.setIsNoRndWalk(false);
receiver.getVariables().remove("BUSY_STATE");
receiver.setRHandId(THS_Weapon);
startQuestTimer("return_from_fire", 3000, receiver, null);
}
break;
}
case "SCE_DINNER_EAT":
{
if (!receiver.isDead() && (receiver.getAI().getIntention() != CtrlIntention.AI_INTENTION_ATTACK) && (receiver.getVariables().getInt("BUSY_STATE", 0) == 0) && Util.contains(SQUAD_LEADERS, receiver.getId()))
{
if (receiver.isNoRndWalk()) // i_ai0 == 1
{
receiver.setRHandId(THS_Weapon);
}
receiver.setIsNoRndWalk(true); // Moving to fire - i_ai0 = 1
receiver.getVariables().set("BUSY_STATE", 1); // Eating - i_ai3 = 1
receiver.setIsRunning(true);
broadcastNpcSay(receiver, Say2.NPC_ALL, (getRandom(3) < 1) ? NpcStringId.LOOKS_DELICIOUS : NpcStringId.LET_S_GO_EAT);
final Location loc = sender.getPointInRange(100, 200);
loc.setHeading(receiver.getHeading());
receiver.stopMove(null);
receiver.getVariables().set("DESTINATION_X", loc.getX());
receiver.getVariables().set("DESTINATION_Y", loc.getY());
receiver.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, loc);
}
break;
}
case "SCE_SOUP_FAILURE":
{
if (Util.contains(SQUAD_LEADERS, receiver.getId()))
{
receiver.getVariables().set("FULL_BARREL_REWARDING_PLAYER", reference.getObjectId()); // TODO: Use it in 289 quest
startQuestTimer("reset_full_bottle_prize", 180000, receiver, null);
}
break;
}
}
return super.onEventReceived(eventName, sender, receiver, reference);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
if (npc.isMonster() && (npc.getVariables().getInt("REWARD_TIME_GONE") == 0))
{
((L2MonsterInstance) npc).dropItem(killer, 15492, 1);
}
cancelQuestTimer("chef_remove_invul", npc, null);
cancelQuestTimer("chef_disable_reward", npc, null);
cancelQuestTimer("chef_heal_player", npc, null);
cancelQuestTimer("chef_set_invul", npc, null);
return super.onKill(npc, killer, isSummon);
}
@Override
public void onMoveFinished(L2Npc npc)
{
// Npc moves to fire
if (npc.isNoRndWalk() && (npc.getX() == npc.getVariables().getInt("DESTINATION_X")) && (npc.getY() == npc.getVariables().getInt("DESTINATION_Y")))
{
npc.setRHandId(OHS_Weapon);
startQuestTimer("fire_arrived", 3000, npc, null);
}
}
@Override
public void onNodeArrived(L2Npc npc)
{
npc.broadcastEvent("SCE_DINNER_CHECK", 300, null);
}
@Override
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
{
if ((npc.getId() == STOVE) && (skill.getId() == 9075) && Util.contains(targets, npc))
{
npc.doCast(SkillData.getInstance().getSkill(6688, 1));
npc.broadcastEvent("SCE_SOUP_FAILURE", 600, caster);
}
return super.onSkillSee(npc, caster, skill, targets, isSummon);
}
@Override
public String onSpawn(L2Npc npc)
{
if (npc.getId() == CHEF)
{
npc.setIsInvul(false);
}
else if (npc.getId() == FIRE)
{
startQuestTimer("fire", 1000, npc, null);
}
else if (Util.contains(SQUAD_LEADERS, npc.getId()))
{
npc.setDisplayEffect(3);
npc.setIsNoRndWalk(false);
}
return super.onSpawn(npc);
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
if ((skill != null) && (skill.getId() == 6330))
{
healPlayer(npc, player);
}
return super.onSpellFinished(npc, player, skill);
}
private void healPlayer(L2Npc npc, L2PcInstance player)
{
if ((player != null) && !player.isDead() && (npc.getVariables().getInt("INVUL_REMOVE_TIMER_STARTED") != 1) && ((npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_ATTACK) || (npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_CAST)))
{
npc.setTarget(player);
npc.doCast(SkillData.getInstance().getSkill(6330, 1));
}
else
{
cancelQuestTimer("chef_set_invul", npc, null);
npc.getVariables().remove("BUSY_STATE");
npc.getVariables().remove("INVUL_REMOVE_TIMER_STARTED");
npc.setIsRunning(false);
}
}
private void handlePreAttackMotion(L2Npc attacked)
{
cancelQuestTimer("remove_effects", attacked, null);
attacked.getVariables().remove("BUSY_STATE");
attacked.setIsNoRndWalk(false);
attacked.setDisplayEffect(MAHUM_EFFECT_NONE);
if (attacked.getRightHandItem() == OHS_Weapon)
{
attacked.setRHandId(THS_Weapon);
}
// TODO: Check about i_quest0
}
public static void main(String[] args)
{
new SelMahumSquad();
}
}

View File

@@ -0,0 +1,210 @@
/*
* Copyright (C) 2004-2014 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.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;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* 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, Say2.NPC_ALL, 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();
}
}

View File

@@ -0,0 +1,244 @@
/*
* Copyright (C) 2004-2014 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();
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2004-2014 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();
}
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (C) 2004-2014 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.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, 0, 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();
}
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright (C) 2004-2014 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 quests.Q00605_AllianceWithKetraOrcs.Q00605_AllianceWithKetraOrcs;
import quests.Q00606_BattleAgainstVarkaSilenos.Q00606_BattleAgainstVarkaSilenos;
import quests.Q00607_ProveYourCourageKetra.Q00607_ProveYourCourageKetra;
import quests.Q00608_SlayTheEnemyCommanderKetra.Q00608_SlayTheEnemyCommanderKetra;
import quests.Q00609_MagicalPowerOfWaterPart1.Q00609_MagicalPowerOfWaterPart1;
import quests.Q00610_MagicalPowerOfWaterPart2.Q00610_MagicalPowerOfWaterPart2;
import quests.Q00611_AllianceWithVarkaSilenos.Q00611_AllianceWithVarkaSilenos;
import quests.Q00612_BattleAgainstKetraOrcs.Q00612_BattleAgainstKetraOrcs;
import quests.Q00613_ProveYourCourageVarka.Q00613_ProveYourCourageVarka;
import quests.Q00614_SlayTheEnemyCommanderVarka.Q00614_SlayTheEnemyCommanderVarka;
import quests.Q00615_MagicalPowerOfFirePart1.Q00615_MagicalPowerOfFirePart1;
import quests.Q00616_MagicalPowerOfFirePart2.Q00616_MagicalPowerOfFirePart2;
import ai.npc.AbstractNpcAI;
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.quest.QuestState;
import com.l2jserver.gameserver.util.Util;
/**
* Varka Silenos Barracks and Ketra Orc Outpost AI
* @author malyelfik
*/
public class VarkaKetra extends AbstractNpcAI
{
// Monsters
private static final int[] KETRA =
{
21324, // Ketra Orc Footman
21325, // Ketra's War Hound
21327, // Ketra Orc Raider
21328, // Ketra Orc Scout
21329, // Ketra Orc Shaman
21331, // Ketra Orc Warrior
21332, // Ketra Orc Lieutenant
21334, // Ketra Orc Medium
21336, // Ketra Orc White Captain
21338, // Ketra Orc Seer
21339, // Ketra Orc General
21340, // Ketra Orc Battalion Commander
21342, // Ketra Orc Grand Seer
21343, // Ketra Commander
21344, // Ketra Elite Guard
21345, // Ketra's Head Shaman
21346, // Ketra's Head Guard
21347, // Ketra Prophet
21348, // Prophet's Guard
21349, // Prophet's Aide
25299, // Ketra's Hero Hekaton (Raid Boss)
25302, // Ketra's Commander Tayr (Raid Boss)
25305, // Ketra's Chief Brakki (Raid Boss)
25306, // Soul of Fire Nastron (Raid Boss)
};
private static final int[] VARKA =
{
21350, // Varka Silenos Recruit
21351, // Varka Silenos Footman
21353, // Varka Silenos Scout
21354, // Varka Silenos Hunter
21355, // Varka Silenos Shaman
21357, // Varka Silenos Priest
21358, // Varka Silenos Warrior
21360, // Varka Silenos Medium
21361, // Varka Silenos Magus
21362, // Varka Silenos Officer
21364, // Varka Silenos Seer
21365, // Varka Silenos Great Magus
21366, // Varka Silenos General
21368, // Varka Silenos Great Seer
21369, // Varka's Commander
21370, // Varka's Elite Guard
21371, // Varka's Head Magus
21372, // Varka's Head Guard
21373, // Varka's Prophet
21374, // Prophet's Guard
21375, // Disciple of Prophet
25309, // Varka's Hero Shadith (Raid Boss)
25312, // Varka's Commander Mos (Raid Boss)
25315, // Varka's Chief Horus (Raid Boss)
25316, // Soul of Water Ashutar (Raid Boss)
};
// Items
private static final int[] KETRA_MARKS =
{
7211, // Mark of Ketra's Alliance - Level 1
7212, // Mark of Ketra's Alliance - Level 2
7213, // Mark of Ketra's Alliance - Level 3
7214, // Mark of Ketra's Alliance - Level 4
7215, // Mark of Ketra's Alliance - Level 5
};
private static final int[] VARKA_MARKS =
{
7221, // Mark of Varka's Alliance - Level 1
7222, // Mark of Varka's Alliance - Level 2
7223, // Mark of Varka's Alliance - Level 3
7224, // Mark of Varka's Alliance - Level 4
7225, // Mark of Varka's Alliance - Level 5
};
// Quests
private static final String[] KETRA_QUESTS =
{
Q00605_AllianceWithKetraOrcs.class.getSimpleName(),
Q00606_BattleAgainstVarkaSilenos.class.getSimpleName(),
Q00607_ProveYourCourageKetra.class.getSimpleName(),
Q00608_SlayTheEnemyCommanderKetra.class.getSimpleName(),
Q00609_MagicalPowerOfWaterPart1.class.getSimpleName(),
Q00610_MagicalPowerOfWaterPart2.class.getSimpleName()
};
private static final String[] VARKA_QUESTS =
{
Q00611_AllianceWithVarkaSilenos.class.getSimpleName(),
Q00612_BattleAgainstKetraOrcs.class.getSimpleName(),
Q00613_ProveYourCourageVarka.class.getSimpleName(),
Q00614_SlayTheEnemyCommanderVarka.class.getSimpleName(),
Q00615_MagicalPowerOfFirePart1.class.getSimpleName(),
Q00616_MagicalPowerOfFirePart2.class.getSimpleName()
};
private VarkaKetra()
{
super(VarkaKetra.class.getSimpleName(), "ai/group_template");
addKillId(KETRA);
addKillId(VARKA);
addNpcHateId(KETRA);
addNpcHateId(VARKA);
}
@Override
public void actionForEachPlayer(L2PcInstance player, L2Npc npc, boolean isSummon)
{
if (Util.checkIfInRange(1500, player, npc, false))
{
if (Util.contains(KETRA, npc.getId()) && hasAtLeastOneQuestItem(player, KETRA_MARKS))
{
decreaseAlliance(player, KETRA_MARKS);
exitQuests(player, KETRA_QUESTS);
}
else if (Util.contains(VARKA, npc.getId()) && hasAtLeastOneQuestItem(player, VARKA_MARKS))
{
decreaseAlliance(player, VARKA_MARKS);
exitQuests(player, VARKA_QUESTS);
}
}
}
private final void decreaseAlliance(L2PcInstance player, int[] marks)
{
for (int i = 0; i < marks.length; i++)
{
if (hasQuestItems(player, marks[i]))
{
takeItems(player, marks[i], -1);
if (i > 0)
{
giveItems(player, marks[i - 1], 1);
}
return;
}
}
}
private final void exitQuests(L2PcInstance player, String[] quests)
{
for (String quest : quests)
{
final QuestState qs = player.getQuestState(quest);
if ((qs != null) && qs.isStarted())
{
qs.exitQuest(true);
}
}
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
executeForEachPlayer(killer, npc, isSummon, true, false);
return super.onKill(npc, killer, isSummon);
}
@Override
public boolean onNpcHate(L2Attackable mob, L2PcInstance player, boolean isSummon)
{
return stopAttack(player, mob) ? false : super.onNpcHate(mob, player, isSummon);
}
private final boolean stopAttack(L2PcInstance player, L2Character monster)
{
return (Util.contains(KETRA, monster.getId()) && hasAtLeastOneQuestItem(player, KETRA_MARKS)) || (Util.contains(VARKA, monster.getId()) && hasAtLeastOneQuestItem(player, VARKA_MARKS));
}
public static void main(String[] args)
{
new VarkaKetra();
}
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright (C) 2004-2014 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.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;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* 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, Say2.NPC_ALL, 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, Say2.NPC_ALL, 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, Say2.NPC_ALL, 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();
}
}

View 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"

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2004-2014 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;