This commit is contained in:
134
L2J_Mobius_Test/dist/game/data/scripts/ai/AbstractNpcAI.java
vendored
Normal file
134
L2J_Mobius_Test/dist/game/data/scripts/ai/AbstractNpcAI.java
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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;
|
||||
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.MinionHolder;
|
||||
import com.l2jmobius.gameserver.model.quest.Quest;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
|
||||
import com.l2jmobius.gameserver.util.Broadcast;
|
||||
|
||||
/**
|
||||
* Abstract NPC AI class for datapack based AIs.
|
||||
* @author UnAfraid, Zoey76
|
||||
*/
|
||||
public abstract class AbstractNpcAI extends Quest
|
||||
{
|
||||
public AbstractNpcAI(String name, String descr)
|
||||
{
|
||||
super(-1, name, descr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple on first talk event handler.
|
||||
*/
|
||||
@Override
|
||||
public String onFirstTalk(L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
return npc.getId() + ".html";
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the following events to the current script:<br>
|
||||
* <ul>
|
||||
* <li>ON_ATTACK</li>
|
||||
* <li>ON_KILL</li>
|
||||
* <li>ON_SPAWN</li>
|
||||
* <li>ON_SPELL_FINISHED</li>
|
||||
* <li>ON_SKILL_SEE</li>
|
||||
* <li>ON_FACTION_CALL</li>
|
||||
* <li>ON_AGGR_RANGE_ENTER</li>
|
||||
* </ul>
|
||||
* @param mobs
|
||||
*/
|
||||
public void registerMobs(int... mobs)
|
||||
{
|
||||
addAttackId(mobs);
|
||||
addKillId(mobs);
|
||||
addSpawnId(mobs);
|
||||
addSpellFinishedId(mobs);
|
||||
addSkillSeeId(mobs);
|
||||
addAggroRangeEnterId(mobs);
|
||||
addFactionCallId(mobs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts NpcSay packet to all known players with custom string.
|
||||
* @param npc
|
||||
* @param type
|
||||
* @param text
|
||||
*/
|
||||
protected void broadcastNpcSay(L2Npc npc, ChatType type, String text)
|
||||
{
|
||||
Broadcast.toKnownPlayers(npc, new NpcSay(npc.getObjectId(), type, npc.getTemplate().getDisplayId(), text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts NpcSay packet to all known players with npc string id.
|
||||
* @param npc
|
||||
* @param type
|
||||
* @param stringId
|
||||
*/
|
||||
protected void broadcastNpcSay(L2Npc npc, ChatType type, NpcStringId stringId)
|
||||
{
|
||||
Broadcast.toKnownPlayers(npc, new NpcSay(npc.getObjectId(), type, npc.getTemplate().getDisplayId(), stringId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts NpcSay packet to all known players with npc string id.
|
||||
* @param npc
|
||||
* @param type
|
||||
* @param stringId
|
||||
* @param parameters
|
||||
*/
|
||||
protected void broadcastNpcSay(L2Npc npc, ChatType type, NpcStringId stringId, String... parameters)
|
||||
{
|
||||
final NpcSay say = new NpcSay(npc.getObjectId(), type, npc.getTemplate().getDisplayId(), stringId);
|
||||
if (parameters != null)
|
||||
{
|
||||
for (String parameter : parameters)
|
||||
{
|
||||
say.addStringParameter(parameter);
|
||||
}
|
||||
}
|
||||
Broadcast.toKnownPlayers(npc, say);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts NpcSay packet to all known players with npc string id in specific radius.
|
||||
* @param npc
|
||||
* @param type
|
||||
* @param stringId
|
||||
* @param radius
|
||||
*/
|
||||
protected void broadcastNpcSay(L2Npc npc, ChatType type, NpcStringId stringId, int radius)
|
||||
{
|
||||
Broadcast.toKnownPlayersInRadius(npc, new NpcSay(npc.getObjectId(), type, npc.getTemplate().getDisplayId(), stringId), radius);
|
||||
}
|
||||
|
||||
public void spawnMinions(L2Npc npc, String spawnName)
|
||||
{
|
||||
for (MinionHolder is : npc.getTemplate().getParameters().getMinionList(spawnName))
|
||||
{
|
||||
addMinion((L2MonsterInstance) npc, is.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
85
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/AdenReconstructorManager.java
vendored
Normal file
85
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/AdenReconstructorManager.java
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Aden Reconstructor Manager AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
final class AdenReconstructorManager extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int[] NPCS =
|
||||
{
|
||||
33584, // Moe
|
||||
33581, // Eeny
|
||||
};
|
||||
|
||||
private AdenReconstructorManager()
|
||||
{
|
||||
super(AdenReconstructorManager.class.getSimpleName(), "ai/group_template");
|
||||
addSpawnId(NPCS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "SPAM_TEXT":
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, 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, ChatType.NPC_GENERAL, NpcStringId.PLEASE_DONATE_ANY_UNUSED_MATERIALS_YOU_HAVE_TO_HELP_REBUILD_ADEN);
|
||||
startQuestTimer("SPAM_TEXT3", 1000, npc, null);
|
||||
break;
|
||||
}
|
||||
case "SPAM_TEXT3":
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, 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();
|
||||
}
|
||||
}
|
||||
477
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/BeastFarm.java
vendored
Normal file
477
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/BeastFarm.java
vendored
Normal file
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.l2jmobius.gameserver.datatables.SkillData;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2TamedBeastInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.NpcInfo;
|
||||
import com.l2jmobius.gameserver.util.Util;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
import quests.Q00020_BringUpWithLove.Q00020_BringUpWithLove;
|
||||
|
||||
/**
|
||||
* Growth-capable mobs: Polymorphing upon successful feeding.<br>
|
||||
* Updated to Freya.
|
||||
* @author Fulminus, Gigiikun
|
||||
*/
|
||||
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;
|
||||
static final int[] SPECIAL_SPICE_CHANCES =
|
||||
{
|
||||
33,
|
||||
75
|
||||
};
|
||||
|
||||
// all mobs that can eat...
|
||||
private static final int[] FEEDABLE_BEASTS =
|
||||
{
|
||||
// Kookaburras
|
||||
18873,
|
||||
18874,
|
||||
18875,
|
||||
18876,
|
||||
18877,
|
||||
18878,
|
||||
18879,
|
||||
// Cougars
|
||||
18880,
|
||||
18881,
|
||||
18882,
|
||||
18883,
|
||||
18884,
|
||||
18885,
|
||||
18886,
|
||||
// Buffalos
|
||||
18887,
|
||||
18888,
|
||||
18889,
|
||||
18890,
|
||||
18891,
|
||||
18892,
|
||||
18893,
|
||||
// Grendels
|
||||
18894,
|
||||
18895,
|
||||
18896,
|
||||
18897,
|
||||
18898,
|
||||
18899,
|
||||
18900
|
||||
};
|
||||
|
||||
private static final Map<Integer, Integer> FEED_INFO = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, GrowthCapableMob> GROWTH_CAPABLE_MONSTERS = new HashMap<>();
|
||||
private static List<TamedBeast> TAMED_BEAST_DATA = new ArrayList<>();
|
||||
|
||||
private BeastFarm()
|
||||
{
|
||||
super(BeastFarm.class.getSimpleName(), "ai/group_template");
|
||||
addSkillSeeId(FEEDABLE_BEASTS);
|
||||
addKillId(FEEDABLE_BEASTS);
|
||||
|
||||
GrowthCapableMob temp;
|
||||
|
||||
// Kookabura
|
||||
temp = new GrowthCapableMob(100, 0, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18874);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18875);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_GOLDEN_SPICE, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_CRYSTAL_SPICE, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_GOLDEN_SPICE, 18878);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_CRYSTAL_SPICE, 18879);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18873, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18876);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18874, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18877);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18875, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18878);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18876, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18869);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18879);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18877, temp);
|
||||
|
||||
// Cougar
|
||||
temp = new GrowthCapableMob(100, 0, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18881);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18882);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_GOLDEN_SPICE, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_CRYSTAL_SPICE, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_GOLDEN_SPICE, 18885);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_CRYSTAL_SPICE, 18886);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18880, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18883);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18881, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18884);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18882, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18885);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18883, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18870);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18886);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18884, temp);
|
||||
|
||||
// Buffalo
|
||||
temp = new GrowthCapableMob(100, 0, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18888);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18889);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_GOLDEN_SPICE, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_CRYSTAL_SPICE, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_GOLDEN_SPICE, 18892);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_CRYSTAL_SPICE, 18893);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18887, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18890);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18888, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18891);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18889, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18892);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18890, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18871);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18893);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18891, temp);
|
||||
|
||||
// Grendel
|
||||
temp = new GrowthCapableMob(100, 0, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18895);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18896);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_GOLDEN_SPICE, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_BLESSED_CRYSTAL_SPICE, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_GOLDEN_SPICE, 18899);
|
||||
temp.addNpcIdForSkillId(SKILL_SGRADE_CRYSTAL_SPICE, 18900);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18894, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18897);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18895, temp);
|
||||
|
||||
temp = new GrowthCapableMob(40, 1, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18898);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18896, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_GOLDEN_SPICE, 18899);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18897, temp);
|
||||
|
||||
temp = new GrowthCapableMob(25, 2, 18872);
|
||||
temp.addNpcIdForSkillId(SKILL_CRYSTAL_SPICE, 18900);
|
||||
GROWTH_CAPABLE_MONSTERS.put(18898, temp);
|
||||
|
||||
// Tamed beasts data
|
||||
TAMED_BEAST_DATA.add(new TamedBeast("%name% of Focus", new SkillHolder(6432, 1), new SkillHolder(6668, 1)));
|
||||
TAMED_BEAST_DATA.add(new TamedBeast("%name% of Guiding", new SkillHolder(6433, 1), new SkillHolder(6670, 1)));
|
||||
TAMED_BEAST_DATA.add(new TamedBeast("%name% of Swifth", new SkillHolder(6434, 1), new SkillHolder(6667, 1)));
|
||||
TAMED_BEAST_DATA.add(new TamedBeast("Berserker %name%", new SkillHolder(6671, 1)));
|
||||
TAMED_BEAST_DATA.add(new TamedBeast("%name% of Protect", new SkillHolder(6669, 1), new SkillHolder(6672, 1)));
|
||||
TAMED_BEAST_DATA.add(new TamedBeast("%name% of Vigor", new SkillHolder(6431, 1), new SkillHolder(6666, 1)));
|
||||
}
|
||||
|
||||
public void spawnNext(L2Npc npc, L2PcInstance player, int nextNpcId, int food)
|
||||
{
|
||||
// remove the feedinfo of the mob that got despawned, if any
|
||||
if (FEED_INFO.containsKey(npc.getObjectId()) && (FEED_INFO.get(npc.getObjectId()) == player.getObjectId()))
|
||||
{
|
||||
FEED_INFO.remove(npc.getObjectId());
|
||||
}
|
||||
// despawn the old mob
|
||||
// TODO: same code? FIXED?
|
||||
/*
|
||||
* if (_GrowthCapableMobs.get(npc.getNpcId()).getGrowthLevel() == 0) { npc.deleteMe(); } else {
|
||||
*/
|
||||
npc.deleteMe();
|
||||
// }
|
||||
|
||||
// if this is finally a trained mob, then despawn any other trained mobs that the
|
||||
// player might have and initialize the Tamed Beast.
|
||||
if (Util.contains(TAMED_BEASTS, nextNpcId))
|
||||
{
|
||||
final L2TamedBeastInstance nextNpc = new L2TamedBeastInstance(nextNpcId, player, food, npc.getX(), npc.getY(), npc.getZ(), true);
|
||||
|
||||
final 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();
|
||||
|
||||
final 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?!)
|
||||
final L2Attackable nextNpc = (L2Attackable) addSpawn(nextNpcId, npc);
|
||||
|
||||
// register the player in the feedinfo for the mob that just spawned
|
||||
FEED_INFO.put(nextNpc.getObjectId(), player.getObjectId());
|
||||
addAttackDesire(nextNpc, 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
|
||||
final int npcId = npc.getId();
|
||||
final 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
|
||||
final int objectId = npc.getObjectId();
|
||||
final int growthLevel = GROWTH_CAPABLE_MONSTERS.containsKey(npcId) ? GROWTH_CAPABLE_MONSTERS.get(npcId).getGrowthLevel() : 3; // if a mob is in FEEDABLE_BEASTS but not in _GrowthCapableMobs, then it's at max growth (3)
|
||||
// prevent exploit which allows 2 players to simultaneously raise the same 0-growth beast
|
||||
// If the mob is at 0th level (when it still listens to all feeders) lock it to the first feeder!
|
||||
if ((growthLevel == 0) && FEED_INFO.containsKey(objectId))
|
||||
{
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
FEED_INFO.put(objectId, caster.getObjectId());
|
||||
|
||||
// display the social action of the beast eating the food.
|
||||
npc.broadcastSocialAction(2);
|
||||
|
||||
int food = 0;
|
||||
if ((skillId == SKILL_GOLDEN_SPICE) || (skillId == SKILL_BLESSED_GOLDEN_SPICE))
|
||||
{
|
||||
food = GOLDEN_SPICE;
|
||||
}
|
||||
else if ((skillId == SKILL_CRYSTAL_SPICE) || (skillId == SKILL_BLESSED_CRYSTAL_SPICE))
|
||||
{
|
||||
food = CRYSTAL_SPICE;
|
||||
}
|
||||
|
||||
// if this pet can't grow, it's all done.
|
||||
if (GROWTH_CAPABLE_MONSTERS.containsKey(npcId))
|
||||
{
|
||||
// do nothing if this mob doesn't eat the specified food (food gets consumed but has no effect).
|
||||
final int newNpcId = GROWTH_CAPABLE_MONSTERS.get(npcId).getLeveledNpcId(skillId);
|
||||
if (newNpcId == -1)
|
||||
{
|
||||
if (growthLevel == 0)
|
||||
{
|
||||
FEED_INFO.remove(objectId);
|
||||
addAttackDesire(npc, caster);
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
if ((growthLevel > 0) && (FEED_INFO.get(objectId) != caster.getObjectId()))
|
||||
{
|
||||
// check if this is the same player as the one who raised it from growth 0.
|
||||
// if no, then do not allow a chance to raise the pet (food gets consumed but has no effect).
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
spawnNext(npc, caster, newNpcId, food);
|
||||
}
|
||||
else
|
||||
{
|
||||
caster.sendMessage("The beast spit out the feed instead of eating it.");
|
||||
npc.dropItem(caster, food, 1);
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
// remove the feedinfo of the mob that got killed, if any
|
||||
if (FEED_INFO.containsKey(npc.getObjectId()))
|
||||
{
|
||||
FEED_INFO.remove(npc.getObjectId());
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
// all mobs that grow by eating
|
||||
private static class GrowthCapableMob
|
||||
{
|
||||
private final int _chance;
|
||||
private final int _growthLevel;
|
||||
private final int _tameNpcId;
|
||||
private final Map<Integer, Integer> _skillSuccessNpcIdList = new HashMap<>();
|
||||
|
||||
public GrowthCapableMob(int chance, int growthLevel, int tameNpcId)
|
||||
{
|
||||
_chance = chance;
|
||||
_growthLevel = growthLevel;
|
||||
_tameNpcId = tameNpcId;
|
||||
}
|
||||
|
||||
public void addNpcIdForSkillId(int skillId, int npcId)
|
||||
{
|
||||
_skillSuccessNpcIdList.put(skillId, npcId);
|
||||
}
|
||||
|
||||
public int getGrowthLevel()
|
||||
{
|
||||
return _growthLevel;
|
||||
}
|
||||
|
||||
public int getLeveledNpcId(int skillId)
|
||||
{
|
||||
if (!_skillSuccessNpcIdList.containsKey(skillId))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if ((skillId == SKILL_BLESSED_GOLDEN_SPICE) || (skillId == SKILL_BLESSED_CRYSTAL_SPICE) || (skillId == SKILL_SGRADE_GOLDEN_SPICE) || (skillId == SKILL_SGRADE_CRYSTAL_SPICE))
|
||||
{
|
||||
if (getRandom(100) < SPECIAL_SPICE_CHANCES[0])
|
||||
{
|
||||
if (getRandom(100) < SPECIAL_SPICE_CHANCES[1])
|
||||
{
|
||||
return _skillSuccessNpcIdList.get(skillId);
|
||||
}
|
||||
else if ((skillId == SKILL_BLESSED_GOLDEN_SPICE) || (skillId == SKILL_SGRADE_GOLDEN_SPICE))
|
||||
{
|
||||
return _skillSuccessNpcIdList.get(SKILL_GOLDEN_SPICE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _skillSuccessNpcIdList.get(SKILL_CRYSTAL_SPICE);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else if ((_growthLevel == 2) && (getRandom(100) < TAME_CHANCE))
|
||||
{
|
||||
return _tameNpcId;
|
||||
}
|
||||
else if (getRandom(100) < _chance)
|
||||
{
|
||||
return _skillSuccessNpcIdList.get(skillId);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class TamedBeast
|
||||
{
|
||||
private final String name;
|
||||
private final SkillHolder[] sh;
|
||||
|
||||
public TamedBeast(String beastName, SkillHolder... holders)
|
||||
{
|
||||
name = beastName;
|
||||
sh = holders;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public SkillHolder[] getSkills()
|
||||
{
|
||||
return sh;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new BeastFarm();
|
||||
}
|
||||
}
|
||||
219
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/DenOfEvil.java
vendored
Normal file
219
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/DenOfEvil.java
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.ThreadPoolManager;
|
||||
import com.l2jmobius.gameserver.datatables.SkillData;
|
||||
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.zone.type.L2EffectZone;
|
||||
import com.l2jmobius.gameserver.network.SystemMessageId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
|
||||
import com.l2jmobius.gameserver.util.Util;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Dummy AI for spawns/respawns only for testing.
|
||||
* @author Gnacik
|
||||
*/
|
||||
final class DenOfEvil extends AbstractNpcAI
|
||||
{
|
||||
// private static final int _buffer_id = 32656;
|
||||
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)
|
||||
{
|
||||
return SKILL_ID + ((npcId - EYE_IDS[0]) * 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
npc.disableCoreAI(true);
|
||||
npc.setIsImmobilized(true);
|
||||
final L2EffectZone zone = ZoneManager.getInstance().getZone(npc, L2EffectZone.class);
|
||||
if (zone == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
final int skillId = getSkillIdByNpcId(npc.getId());
|
||||
final 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);
|
||||
final L2EffectZone zone = ZoneManager.getInstance().getZone(npc, L2EffectZone.class);
|
||||
if (zone == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
final int skillId = getSkillIdByNpcId(npc.getId());
|
||||
final 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())
|
||||
{
|
||||
SkillData.getInstance().getSkill(6149, 1).applyEffects(character, character);
|
||||
}
|
||||
else if (character.doDie(null) && character.isNpc() && Util.contains(EYE_IDS, ((L2Npc) character).getId())) // mobs die
|
||||
{
|
||||
ThreadPoolManager.getInstance().scheduleAi(new RespawnNewEye(((L2Npc) character).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();
|
||||
}
|
||||
}
|
||||
73
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/EventShrines.java
vendored
Normal file
73
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/EventShrines.java
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.instancemanager.EventShrineManager;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.quest.Quest;
|
||||
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.OnEventTrigger;
|
||||
|
||||
/**
|
||||
* @author hlwrave, Mobius
|
||||
* @Add in event config.xml enableShrines="true" after event name to enable them.
|
||||
*/
|
||||
final class EventShrines extends Quest
|
||||
{
|
||||
private static final Map<Integer, Integer> ZONE_TRIGGERS = new HashMap<>();
|
||||
static
|
||||
{
|
||||
ZONE_TRIGGERS.put(11030, 23206292); // Hunter
|
||||
ZONE_TRIGGERS.put(11031, 24186292); // Aden
|
||||
ZONE_TRIGGERS.put(11032, 24166292); // Goddard
|
||||
ZONE_TRIGGERS.put(11035, 22136292); // Shuttgard
|
||||
ZONE_TRIGGERS.put(11028, 20226292); // Dion
|
||||
ZONE_TRIGGERS.put(11029, 22196292); // Oren
|
||||
ZONE_TRIGGERS.put(11020, 22226292); // Giran
|
||||
ZONE_TRIGGERS.put(11027, 19216292); // Gludio
|
||||
ZONE_TRIGGERS.put(11034, 23246292); // Heine
|
||||
ZONE_TRIGGERS.put(11025, 17226292); // Gluddin
|
||||
ZONE_TRIGGERS.put(11033, 21166292); // Rune
|
||||
ZONE_TRIGGERS.put(11042, 17256292); // Faeron
|
||||
ZONE_TRIGGERS.put(11043, 26206292); // Arcan
|
||||
ZONE_TRIGGERS.put(11022, 16256292); // Talking Island
|
||||
}
|
||||
|
||||
public EventShrines()
|
||||
{
|
||||
super(-1, "Event Shrines", "Event Shrines");
|
||||
addEnterZoneId(ZONE_TRIGGERS.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onEnterZone(L2Character character, L2ZoneType zone)
|
||||
{
|
||||
if (character.isPlayer() && EventShrineManager.getInstance().areShrinesEnabled())
|
||||
{
|
||||
character.sendPacket(new OnEventTrigger(ZONE_TRIGGERS.get(zone.getId()), true));
|
||||
}
|
||||
return super.onEnterZone(character, zone);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new EventShrines();
|
||||
}
|
||||
}
|
||||
88
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/FairyTrees.java
vendored
Normal file
88
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/FairyTrees.java
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Playable;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Fairy Trees AI.
|
||||
* @author Charus
|
||||
*/
|
||||
final class FairyTrees extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int SOUL_GUARDIAN = 27189; // Soul of Tree Guardian
|
||||
|
||||
private static final int[] MOBS =
|
||||
{
|
||||
27185, // Fairy Tree of Wind
|
||||
27186, // Fairy Tree of Star
|
||||
27187, // Fairy Tree of Twilight
|
||||
27188, // Fairy Tree of Abyss
|
||||
};
|
||||
|
||||
// Skill
|
||||
private static SkillHolder VENOMOUS_POISON = new SkillHolder(4243, 1); // Venomous Poison
|
||||
|
||||
// Misc
|
||||
private static final int MIN_DISTANCE = 1500;
|
||||
|
||||
private FairyTrees()
|
||||
{
|
||||
super(FairyTrees.class.getSimpleName(), "ai/group_template");
|
||||
addKillId(MOBS);
|
||||
addSpawnId(MOBS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (npc.calculateDistance(killer, true, false) <= MIN_DISTANCE)
|
||||
{
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
final L2Npc guardian = addSpawn(SOUL_GUARDIAN, npc, false, 30000);
|
||||
final L2Playable attacker = isSummon ? killer.getServitors().values().stream().findFirst().orElse(killer.getPet()) : killer;
|
||||
addAttackDesire(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();
|
||||
}
|
||||
}
|
||||
604
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/FeedableBeasts.java
vendored
Normal file
604
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/FeedableBeasts.java
vendored
Normal file
@@ -0,0 +1,604 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.group_template;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2TamedBeastInstance;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
|
||||
import com.l2jmobius.gameserver.util.Util;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
import quests.Q00020_BringUpWithLove.Q00020_BringUpWithLove;
|
||||
import quests.Q00655_AGrandPlanForTamingWildBeasts.Q00655_AGrandPlanForTamingWildBeasts;
|
||||
|
||||
/**
|
||||
* Growth-capable mobs: Polymorphing upon successful feeding.
|
||||
* @author Fulminus
|
||||
*/
|
||||
final class FeedableBeasts extends AbstractNpcAI
|
||||
{
|
||||
private static final int GOLDEN_SPICE = 6643;
|
||||
private static final int CRYSTAL_SPICE = 6644;
|
||||
private static final int SKILL_GOLDEN_SPICE = 2188;
|
||||
private static final int SKILL_CRYSTAL_SPICE = 2189;
|
||||
private static final int FOODSKILLDIFF = GOLDEN_SPICE - SKILL_GOLDEN_SPICE;
|
||||
// Tamed Wild Beasts
|
||||
private static final int TRAINED_BUFFALO1 = 16013;
|
||||
private static final int TRAINED_BUFFALO2 = 16014;
|
||||
private static final int TRAINED_COUGAR1 = 16015;
|
||||
private static final int TRAINED_COUGAR2 = 16016;
|
||||
private static final int TRAINED_KOOKABURRA1 = 16017;
|
||||
private static final int TRAINED_KOOKABURRA2 = 16018;
|
||||
// private static final int TRAINED_TINY_BABY_BUFFALO = 16020; // TODO: Implement.
|
||||
// private static final int TRAINED_TINY_BABY_COUGAR = 16022; // TODO: Implement.
|
||||
// private static final int TRAINED_TINY_BABY_KOOKABURRA = 16024; // TODO: Implement.
|
||||
// @formatter:off
|
||||
private static final int[] TAMED_BEASTS =
|
||||
{
|
||||
TRAINED_BUFFALO1, TRAINED_BUFFALO2, TRAINED_COUGAR1, TRAINED_COUGAR2, TRAINED_KOOKABURRA1, TRAINED_KOOKABURRA2
|
||||
};
|
||||
// all mobs that can eat...
|
||||
private static final int[] FEEDABLE_BEASTS =
|
||||
{
|
||||
21451, 21452, 21453, 21454, 21455, 21456, 21457, 21458, 21459, 21460,
|
||||
21461, 21462, 21463, 21464, 21465, 21466, 21467, 21468, 21469, 21470,
|
||||
21471, 21472, 21473, 21474, 21475, 21476, 21477, 21478, 21479, 21480,
|
||||
21481, 21482, 21483, 21484, 21485, 21486, 21487, 21488, 21489, 21490,
|
||||
21491, 21492, 21493, 21494, 21495, 21496, 21497, 21498, 21499, 21500,
|
||||
21501, 21502, 21503, 21504, 21505, 21506, 21507, 21824, 21825, 21826,
|
||||
21827, 21828, 21829, TRAINED_BUFFALO1, TRAINED_BUFFALO2, TRAINED_COUGAR1, TRAINED_COUGAR2, TRAINED_KOOKABURRA1, TRAINED_KOOKABURRA2
|
||||
};
|
||||
// @formatter:on
|
||||
|
||||
private static final Map<Integer, Integer> MAD_COW_POLYMORPH = new HashMap<>();
|
||||
static
|
||||
{
|
||||
MAD_COW_POLYMORPH.put(21824, 21468);
|
||||
MAD_COW_POLYMORPH.put(21825, 21469);
|
||||
MAD_COW_POLYMORPH.put(21826, 21487);
|
||||
MAD_COW_POLYMORPH.put(21827, 21488);
|
||||
MAD_COW_POLYMORPH.put(21828, 21506);
|
||||
MAD_COW_POLYMORPH.put(21829, 21507);
|
||||
}
|
||||
|
||||
private static final NpcStringId[][] TEXT =
|
||||
{
|
||||
{
|
||||
NpcStringId.WHAT_DID_YOU_JUST_DO_TO_ME,
|
||||
NpcStringId.ARE_YOU_TRYING_TO_TAME_ME_DON_T_DO_THAT,
|
||||
NpcStringId.DON_T_GIVE_SUCH_A_THING_YOU_CAN_ENDANGER_YOURSELF,
|
||||
NpcStringId.YUCK_WHAT_IS_THIS_IT_TASTES_TERRIBLE,
|
||||
NpcStringId.I_M_HUNGRY_GIVE_ME_A_LITTLE_MORE_PLEASE,
|
||||
NpcStringId.WHAT_IS_THIS_IS_THIS_EDIBLE,
|
||||
NpcStringId.DON_T_WORRY_ABOUT_ME,
|
||||
NpcStringId.THANK_YOU_THAT_WAS_DELICIOUS,
|
||||
NpcStringId.I_THINK_I_AM_STARTING_TO_LIKE_YOU,
|
||||
NpcStringId.EEEEEK_EEEEEK
|
||||
},
|
||||
{
|
||||
NpcStringId.DON_T_KEEP_TRYING_TO_TAME_ME_I_DON_T_WANT_TO_BE_TAMED,
|
||||
NpcStringId.IT_IS_JUST_FOOD_TO_ME_ALTHOUGH_IT_MAY_ALSO_BE_YOUR_HAND,
|
||||
NpcStringId.IF_I_KEEP_EATING_LIKE_THIS_WON_T_I_BECOME_FAT_CHOMP_CHOMP,
|
||||
NpcStringId.WHY_DO_YOU_KEEP_FEEDING_ME,
|
||||
NpcStringId.DON_T_TRUST_ME_I_M_AFRAID_I_MAY_BETRAY_YOU_LATER
|
||||
},
|
||||
{
|
||||
NpcStringId.GRRRRR,
|
||||
NpcStringId.YOU_BROUGHT_THIS_UPON_YOURSELF,
|
||||
NpcStringId.I_FEEL_STRANGE_I_KEEP_HAVING_THESE_EVIL_THOUGHTS,
|
||||
NpcStringId.ALAS_SO_THIS_IS_HOW_IT_ALL_ENDS,
|
||||
NpcStringId.I_DON_T_FEEL_SO_GOOD_OH_MY_MIND_IS_VERY_TROUBLED
|
||||
}
|
||||
};
|
||||
|
||||
private static final NpcStringId[] TAMED_TEXT =
|
||||
{
|
||||
NpcStringId.S1_SO_WHAT_DO_YOU_THINK_IT_IS_LIKE_TO_BE_TAMED,
|
||||
NpcStringId.S1_WHENEVER_I_SEE_SPICE_I_THINK_I_WILL_MISS_YOUR_HAND_THAT_USED_TO_FEED_IT_TO_ME,
|
||||
NpcStringId.S1_DON_T_GO_TO_THE_VILLAGE_I_DON_T_HAVE_THE_STRENGTH_TO_FOLLOW_YOU,
|
||||
NpcStringId.THANK_YOU_FOR_TRUSTING_ME_S1_I_HOPE_I_WILL_BE_HELPFUL_TO_YOU,
|
||||
NpcStringId.S1_WILL_I_BE_ABLE_TO_HELP_YOU,
|
||||
NpcStringId.I_GUESS_IT_S_JUST_MY_ANIMAL_MAGNETISM,
|
||||
NpcStringId.TOO_MUCH_SPICY_FOOD_MAKES_ME_SWEAT_LIKE_A_BEAST,
|
||||
NpcStringId.ANIMALS_NEED_LOVE_TOO
|
||||
};
|
||||
|
||||
private static final Map<Integer, Integer> FEED_INFO = new ConcurrentHashMap<>();
|
||||
private static final Map<Integer, GrowthCapableMob> GROWTH_CAPABLE_MONSTERS = new HashMap<>();
|
||||
|
||||
// all mobs that grow by eating
|
||||
private static class GrowthCapableMob
|
||||
{
|
||||
private final int _growthLevel;
|
||||
private final int _chance;
|
||||
|
||||
private final Map<Integer, int[][]> _spiceToMob = new HashMap<>();
|
||||
|
||||
public GrowthCapableMob(int growthLevel, int chance)
|
||||
{
|
||||
_growthLevel = growthLevel;
|
||||
_chance = chance;
|
||||
}
|
||||
|
||||
public void addMobs(int spice, int[][] Mobs)
|
||||
{
|
||||
_spiceToMob.put(spice, Mobs);
|
||||
}
|
||||
|
||||
public Integer getMob(int spice, int mobType, int classType)
|
||||
{
|
||||
return _spiceToMob.containsKey(spice) ? _spiceToMob.get(spice)[mobType][classType] : null;
|
||||
}
|
||||
|
||||
public Integer getRandomMob(int spice)
|
||||
{
|
||||
final int[][] temp = _spiceToMob.get(spice);
|
||||
return temp[0][getRandom(temp[0].length)];
|
||||
}
|
||||
|
||||
public Integer getChance()
|
||||
{
|
||||
return _chance;
|
||||
}
|
||||
|
||||
public Integer getGrowthLevel()
|
||||
{
|
||||
return _growthLevel;
|
||||
}
|
||||
}
|
||||
|
||||
private FeedableBeasts()
|
||||
{
|
||||
super(FeedableBeasts.class.getSimpleName(), "ai/group_template");
|
||||
addKillId(FEEDABLE_BEASTS);
|
||||
addSkillSeeId(FEEDABLE_BEASTS);
|
||||
|
||||
// TODO: no grendels?
|
||||
GrowthCapableMob temp;
|
||||
|
||||
//@formatter:off
|
||||
final int[][] Kookabura_0_Gold = {{ 21452, 21453, 21454, 21455 }};
|
||||
final int[][] Kookabura_0_Crystal = {{ 21456, 21457, 21458, 21459 }};
|
||||
final int[][] Kookabura_1_Gold_1= {{ 21460, 21462 }};
|
||||
final int[][] Kookabura_1_Gold_2 = {{ 21461, 21463 }};
|
||||
final int[][] Kookabura_1_Crystal_1 = {{ 21464, 21466 }};
|
||||
final int[][] Kookabura_1_Crystal_2 = {{ 21465, 21467 }};
|
||||
final int[][] Kookabura_2_1 = {{ 21468, 21824}, { TRAINED_KOOKABURRA1, TRAINED_KOOKABURRA2 }};
|
||||
final int[][] Kookabura_2_2 = {{ 21469, 21825}, { TRAINED_KOOKABURRA1, TRAINED_KOOKABURRA2 }};
|
||||
|
||||
final int[][] Buffalo_0_Gold = {{ 21471, 21472, 21473, 21474 }};
|
||||
final int[][] Buffalo_0_Crystal = {{ 21475, 21476, 21477, 21478 }};
|
||||
final int[][] Buffalo_1_Gold_1 = {{ 21479, 21481 }};
|
||||
final int[][] Buffalo_1_Gold_2 = {{ 21481, 21482 }};
|
||||
final int[][] Buffalo_1_Crystal_1 = {{ 21483, 21485 }};
|
||||
final int[][] Buffalo_1_Crystal_2 = {{ 21484, 21486 }};
|
||||
final int[][] Buffalo_2_1 = {{ 21487, 21826}, {TRAINED_BUFFALO1, TRAINED_BUFFALO2 }};
|
||||
final int[][] Buffalo_2_2 = {{ 21488, 21827}, {TRAINED_BUFFALO1, TRAINED_BUFFALO2 }};
|
||||
|
||||
final int[][] Cougar_0_Gold = {{ 21490, 21491, 21492, 21493 }};
|
||||
final int[][] Cougar_0_Crystal = {{ 21494, 21495, 21496, 21497 }};
|
||||
final int[][] Cougar_1_Gold_1 = {{ 21498, 21500 }};
|
||||
final int[][] Cougar_1_Gold_2 = {{ 21499, 21501 }};
|
||||
final int[][] Cougar_1_Crystal_1 = {{ 21502, 21504 }};
|
||||
final int[][] Cougar_1_Crystal_2 = {{ 21503, 21505 }};
|
||||
final int[][] Cougar_2_1 = {{ 21506, 21828 }, { TRAINED_COUGAR1, TRAINED_COUGAR2 }};
|
||||
final int[][] Cougar_2_2 = {{ 21507, 21829 }, { TRAINED_COUGAR1, TRAINED_COUGAR2 }};
|
||||
//@formatter:on
|
||||
|
||||
// Alpen Kookabura
|
||||
temp = new GrowthCapableMob(0, 100);
|
||||
temp.addMobs(GOLDEN_SPICE, Kookabura_0_Gold);
|
||||
temp.addMobs(CRYSTAL_SPICE, Kookabura_0_Crystal);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21451, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(GOLDEN_SPICE, Kookabura_1_Gold_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21452, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21454, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(GOLDEN_SPICE, Kookabura_1_Gold_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21453, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21455, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(CRYSTAL_SPICE, Kookabura_1_Crystal_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21456, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21458, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(CRYSTAL_SPICE, Kookabura_1_Crystal_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21457, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21459, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(GOLDEN_SPICE, Kookabura_2_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21460, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21462, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(GOLDEN_SPICE, Kookabura_2_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21461, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21463, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(CRYSTAL_SPICE, Kookabura_2_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21464, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21466, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(CRYSTAL_SPICE, Kookabura_2_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21465, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21467, temp);
|
||||
|
||||
// Alpen Buffalo
|
||||
temp = new GrowthCapableMob(0, 100);
|
||||
temp.addMobs(GOLDEN_SPICE, Buffalo_0_Gold);
|
||||
temp.addMobs(CRYSTAL_SPICE, Buffalo_0_Crystal);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21470, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(GOLDEN_SPICE, Buffalo_1_Gold_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21471, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21473, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(GOLDEN_SPICE, Buffalo_1_Gold_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21472, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21474, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(CRYSTAL_SPICE, Buffalo_1_Crystal_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21475, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21477, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(CRYSTAL_SPICE, Buffalo_1_Crystal_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21476, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21478, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(GOLDEN_SPICE, Buffalo_2_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21479, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21481, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(GOLDEN_SPICE, Buffalo_2_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21480, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21482, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(CRYSTAL_SPICE, Buffalo_2_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21483, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21485, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(CRYSTAL_SPICE, Buffalo_2_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21484, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21486, temp);
|
||||
|
||||
// Alpen Cougar
|
||||
temp = new GrowthCapableMob(0, 100);
|
||||
temp.addMobs(GOLDEN_SPICE, Cougar_0_Gold);
|
||||
temp.addMobs(CRYSTAL_SPICE, Cougar_0_Crystal);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21489, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(GOLDEN_SPICE, Cougar_1_Gold_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21490, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21492, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(GOLDEN_SPICE, Cougar_1_Gold_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21491, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21493, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(CRYSTAL_SPICE, Cougar_1_Crystal_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21494, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21496, temp);
|
||||
|
||||
temp = new GrowthCapableMob(1, 40);
|
||||
temp.addMobs(CRYSTAL_SPICE, Cougar_1_Crystal_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21495, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21497, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(GOLDEN_SPICE, Cougar_2_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21498, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21500, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(GOLDEN_SPICE, Cougar_2_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21499, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21501, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(CRYSTAL_SPICE, Cougar_2_1);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21502, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21504, temp);
|
||||
|
||||
temp = new GrowthCapableMob(2, 25);
|
||||
temp.addMobs(CRYSTAL_SPICE, Cougar_2_2);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21503, temp);
|
||||
GROWTH_CAPABLE_MONSTERS.put(21505, temp);
|
||||
}
|
||||
|
||||
private void spawnNext(L2Npc npc, int growthLevel, L2PcInstance player, int food)
|
||||
{
|
||||
final int npcId = npc.getId();
|
||||
int nextNpcId = 0;
|
||||
|
||||
// find the next mob to spawn, based on the current npcId, growthlevel, and food.
|
||||
if (growthLevel == 2)
|
||||
{
|
||||
// if tamed, the mob that will spawn depends on the class type (fighter/mage) of the player!
|
||||
if (getRandom(2) == 0)
|
||||
{
|
||||
if (player.getClassId().isMage())
|
||||
{
|
||||
nextNpcId = GROWTH_CAPABLE_MONSTERS.get(npcId).getMob(food, 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextNpcId = GROWTH_CAPABLE_MONSTERS.get(npcId).getMob(food, 1, 0);
|
||||
}
|
||||
}
|
||||
else // if not tamed, there is a small chance that have "mad cow" disease.
|
||||
// that is a stronger-than-normal animal that attacks its feeder
|
||||
if (getRandom(5) == 0)
|
||||
{
|
||||
nextNpcId = GROWTH_CAPABLE_MONSTERS.get(npcId).getMob(food, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextNpcId = GROWTH_CAPABLE_MONSTERS.get(npcId).getMob(food, 0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// all other levels of growth are straight-forward
|
||||
nextNpcId = GROWTH_CAPABLE_MONSTERS.get(npcId).getRandomMob(food);
|
||||
}
|
||||
|
||||
// remove the feedinfo of the mob that got despawned, if any
|
||||
if (FEED_INFO.containsKey(npc.getObjectId()))
|
||||
{
|
||||
if (FEED_INFO.get(npc.getObjectId()) == player.getObjectId())
|
||||
{
|
||||
FEED_INFO.remove(npc.getObjectId());
|
||||
}
|
||||
}
|
||||
// despawn the old mob
|
||||
// TODO: same code? FIXED?
|
||||
// @formatter:off
|
||||
/*
|
||||
* if (_GrowthCapableMobs.get(npcId).getGrowthLevel() == 0)
|
||||
{
|
||||
npc.deleteMe();
|
||||
}
|
||||
else
|
||||
{
|
||||
*/
|
||||
npc.deleteMe();
|
||||
// }
|
||||
// @formatter:on
|
||||
|
||||
// if this is finally a trained mob, then despawn any other trained mobs that the
|
||||
// player might have and initialize the Tamed Beast.
|
||||
if (Util.contains(TAMED_BEASTS, nextNpcId))
|
||||
{
|
||||
if ((player.getTrainedBeasts() != null) && !player.getTrainedBeasts().isEmpty())
|
||||
{
|
||||
for (L2TamedBeastInstance oldTrained : player.getTrainedBeasts())
|
||||
{
|
||||
oldTrained.deleteMe();
|
||||
}
|
||||
}
|
||||
|
||||
final L2TamedBeastInstance nextNpc = new L2TamedBeastInstance(nextNpcId, player, food - FOODSKILLDIFF, npc.getX(), npc.getY(), npc.getZ());
|
||||
nextNpc.setRunning();
|
||||
Q00020_BringUpWithLove.checkJewelOfInnocence(player);
|
||||
|
||||
// Support for A Grand Plan for Taming Wild Beasts (655) quest.
|
||||
Q00655_AGrandPlanForTamingWildBeasts.reward(player, nextNpc);
|
||||
|
||||
// also, perform a rare random chat
|
||||
if (getRandom(20) == 0)
|
||||
{
|
||||
final NpcStringId message = NpcStringId.getNpcStringId(getRandom(2024, 2029));
|
||||
final NpcSay packet = new NpcSay(nextNpc, ChatType.NPC_GENERAL, message);
|
||||
if (message.getParamCount() > 0) // player name, $s1
|
||||
{
|
||||
packet.addStringParameter(player.getName());
|
||||
}
|
||||
npc.broadcastPacket(packet);
|
||||
}
|
||||
// @formatter:off
|
||||
/*
|
||||
TODO: The tamed beast consumes one golden/crystal spice
|
||||
every 60 seconds with an initial delay of 60 seconds
|
||||
if (tamed beast exists and is alive)
|
||||
{
|
||||
if (player has 1+ golden/crystal spice)
|
||||
{
|
||||
take one golden/crystal spice;
|
||||
say random NpcString(getRandom(2029, 2038));
|
||||
}
|
||||
}
|
||||
*/
|
||||
// @formatter:on
|
||||
}
|
||||
else
|
||||
{
|
||||
// if not trained, the newly spawned mob will automatically be aggro against its feeder
|
||||
// (what happened to "never bite the hand that feeds you" anyway?!)
|
||||
final L2Attackable nextNpc = (L2Attackable) addSpawn(nextNpcId, npc);
|
||||
|
||||
if (MAD_COW_POLYMORPH.containsKey(nextNpcId))
|
||||
{
|
||||
startQuestTimer("polymorph Mad Cow", 10000, nextNpc, player);
|
||||
}
|
||||
|
||||
// register the player in the feedinfo for the mob that just spawned
|
||||
FEED_INFO.put(nextNpc.getObjectId(), player.getObjectId());
|
||||
addAttackDesire(nextNpc, player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("polymorph Mad Cow") && (npc != null) && (player != null) && MAD_COW_POLYMORPH.containsKey(npc.getId()))
|
||||
{
|
||||
// remove the feed info from the previous mob
|
||||
if (FEED_INFO.get(npc.getObjectId()) == player.getObjectId())
|
||||
{
|
||||
FEED_INFO.remove(npc.getObjectId());
|
||||
}
|
||||
// despawn the mad cow
|
||||
npc.deleteMe();
|
||||
// spawn the new mob
|
||||
final L2Attackable nextNpc = (L2Attackable) addSpawn(MAD_COW_POLYMORPH.get(npc.getId()), npc);
|
||||
// register the player in the feedinfo for the mob that just spawned
|
||||
FEED_INFO.put(nextNpc.getObjectId(), player.getObjectId());
|
||||
addAttackDesire(nextNpc, 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
|
||||
final int npcId = npc.getId();
|
||||
final 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
|
||||
final int objectId = npc.getObjectId();
|
||||
final int growthLevel = GROWTH_CAPABLE_MONSTERS.containsKey(npcId) ? GROWTH_CAPABLE_MONSTERS.get(npcId).getGrowthLevel() : 3; // if a mob is in FEEDABLE_BEASTS but not in _GrowthCapableMobs, then it's at max growth (3)
|
||||
// prevent exploit which allows 2 players to simultaneously raise the same 0-growth beast
|
||||
// If the mob is at 0th level (when it still listens to all feeders) lock it to the first feeder!
|
||||
if ((growthLevel == 0) && FEED_INFO.containsKey(objectId))
|
||||
{
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
FEED_INFO.put(objectId, caster.getObjectId());
|
||||
|
||||
int food = 0;
|
||||
if (skillId == SKILL_GOLDEN_SPICE)
|
||||
{
|
||||
food = GOLDEN_SPICE;
|
||||
}
|
||||
else if (skillId == SKILL_CRYSTAL_SPICE)
|
||||
{
|
||||
food = CRYSTAL_SPICE;
|
||||
}
|
||||
|
||||
// display the social action of the beast eating the food.
|
||||
npc.broadcastSocialAction(2);
|
||||
|
||||
// if this pet can't grow, it's all done.
|
||||
if (GROWTH_CAPABLE_MONSTERS.containsKey(npcId))
|
||||
{
|
||||
// do nothing if this mob doesn't eat the specified food (food gets consumed but has no effect).
|
||||
if (GROWTH_CAPABLE_MONSTERS.get(npcId).getMob(food, 0, 0) == null)
|
||||
{
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
// rare random talk...
|
||||
if (getRandom(20) == 0)
|
||||
{
|
||||
final NpcStringId message = TEXT[growthLevel][getRandom(TEXT[growthLevel].length)];
|
||||
final NpcSay packet = new NpcSay(npc, ChatType.NPC_GENERAL, message);
|
||||
if (message.getParamCount() > 0) // player name, $s1
|
||||
{
|
||||
packet.addStringParameter(caster.getName());
|
||||
}
|
||||
npc.broadcastPacket(packet);
|
||||
}
|
||||
|
||||
if ((growthLevel > 0) && (FEED_INFO.get(objectId) != caster.getObjectId()))
|
||||
{
|
||||
// check if this is the same player as the one who raised it from growth 0.
|
||||
// if no, then do not allow a chance to raise the pet (food gets consumed but has no effect).
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
// Polymorph the mob, with a certain chance, given its current growth level
|
||||
if (getRandom(100) < GROWTH_CAPABLE_MONSTERS.get(npcId).getChance())
|
||||
{
|
||||
spawnNext(npc, growthLevel, caster, food);
|
||||
}
|
||||
}
|
||||
else if (Util.contains(TAMED_BEASTS, npcId) && (npc instanceof L2TamedBeastInstance))
|
||||
{
|
||||
final L2TamedBeastInstance beast = (L2TamedBeastInstance) npc;
|
||||
if (skillId == beast.getFoodType())
|
||||
{
|
||||
beast.onReceiveFood();
|
||||
final NpcStringId message = TAMED_TEXT[getRandom(TAMED_TEXT.length)];
|
||||
final NpcSay packet = new NpcSay(npc, ChatType.NPC_GENERAL, message);
|
||||
if (message.getParamCount() > 0)
|
||||
{
|
||||
packet.addStringParameter(caster.getName());
|
||||
}
|
||||
beast.broadcastPacket(packet);
|
||||
}
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
// remove the feedinfo of the mob that got killed, if any
|
||||
if (FEED_INFO.containsKey(npc.getObjectId()))
|
||||
{
|
||||
FEED_INFO.remove(npc.getObjectId());
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new FeedableBeasts();
|
||||
}
|
||||
}
|
||||
83
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/FleeMonsters.java
vendored
Normal file
83
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/FleeMonsters.java
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.GeoData;
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Summon;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.interfaces.ILocational;
|
||||
import com.l2jmobius.gameserver.util.Util;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Flee Monsters AI.
|
||||
* @author Pandragon, NosBit
|
||||
*/
|
||||
final class FleeMonsters extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int[] MOBS =
|
||||
{
|
||||
18150, // Victim
|
||||
18151, // Victim
|
||||
18152, // Victim
|
||||
18153, // Victim
|
||||
18154, // Victim
|
||||
18155, // Victim
|
||||
18156, // Victim
|
||||
18157, // Victim
|
||||
20002, // Rabbit
|
||||
20432, // Elpy
|
||||
22228, // Grey Elpy
|
||||
25604, // Mutated Elpy
|
||||
};
|
||||
// Misc
|
||||
private static final int FLEE_DISTANCE = 500;
|
||||
|
||||
private FleeMonsters()
|
||||
{
|
||||
super(FleeMonsters.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(MOBS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
npc.disableCoreAI(true);
|
||||
npc.setRunning();
|
||||
|
||||
final L2Summon summon = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : null;
|
||||
final ILocational attackerLoc = summon == null ? attacker : summon;
|
||||
final double radians = Math.toRadians(Util.calculateAngleFrom(attackerLoc, npc));
|
||||
final int posX = (int) (npc.getX() + (FLEE_DISTANCE * Math.cos(radians)));
|
||||
final int posY = (int) (npc.getY() + (FLEE_DISTANCE * Math.sin(radians)));
|
||||
final int posZ = npc.getZ();
|
||||
|
||||
final Location destination = GeoData.getInstance().moveCheck(npc.getX(), npc.getY(), npc.getZ(), posX, posY, posZ, attacker.getInstanceId());
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new FleeMonsters();
|
||||
}
|
||||
}
|
||||
69
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/FrozenLabyrinth.java
vendored
Normal file
69
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/FrozenLabyrinth.java
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Frozen Labyrinth AI.
|
||||
* @author malyelfik
|
||||
*/
|
||||
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);
|
||||
addAttackDesire(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();
|
||||
}
|
||||
}
|
||||
112
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/GiantsCave.java
vendored
Normal file
112
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/GiantsCave.java
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Giant's Cave AI.
|
||||
* @author Gnacik, St3eT
|
||||
*/
|
||||
final class GiantsCave extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int[] SCOUTS =
|
||||
{
|
||||
22668, // Gamlin (Scout)
|
||||
22669, // Leogul (Scout)
|
||||
};
|
||||
|
||||
private GiantsCave()
|
||||
{
|
||||
super(GiantsCave.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(SCOUTS);
|
||||
addAggroRangeEnterId(SCOUTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equals("ATTACK") && (player != null) && (npc != null) && !npc.isDead())
|
||||
{
|
||||
if (npc.getId() == SCOUTS[0]) // Gamlin
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_SHOUT, NpcStringId.INTRUDER_DETECTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_SHOUT, NpcStringId.OH_GIANTS_AN_INTRUDER_HAS_BEEN_DISCOVERED);
|
||||
}
|
||||
|
||||
for (L2Character characters : npc.getKnownList().getKnownCharactersInRadius(450))
|
||||
{
|
||||
if ((characters != null) && characters.isAttackable() && getRandomBoolean())
|
||||
{
|
||||
addAttackDesire((L2Npc) characters, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equals("CLEAR") && (npc != null) && !npc.isDead())
|
||||
{
|
||||
npc.setScriptValue(0);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
startQuestTimer("ATTACK", 6000, npc, attacker);
|
||||
startQuestTimer("CLEAR", 120000, npc, null);
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
if (getRandomBoolean())
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.YOU_GUYS_ARE_DETECTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.WHAT_KIND_OF_CREATURES_ARE_YOU);
|
||||
}
|
||||
startQuestTimer("ATTACK", 6000, npc, player);
|
||||
startQuestTimer("CLEAR", 120000, npc, null);
|
||||
}
|
||||
return super.onAggroRangeEnter(npc, player, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new GiantsCave();
|
||||
}
|
||||
}
|
||||
114
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/HillsOfGold.java
vendored
Normal file
114
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/HillsOfGold.java
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Hills of Gold AI.
|
||||
* @author Mobius
|
||||
*/
|
||||
final class HillsOfGold extends AbstractNpcAI
|
||||
{
|
||||
// Npcs
|
||||
private static final int GOLEM_OF_REPAIRS = 19309;
|
||||
private static final int EXCAVATOR_GOLEM = 19312;
|
||||
private static final int DRILL_GOLEM = 19310;
|
||||
private static final int SPICULA_1 = 23246;
|
||||
private static final int SPICULA_2 = 23247;
|
||||
private static final int YIN_FRAGMENT = 19308;
|
||||
private static final int SPICULA_ELITE_GUARD = 23303;
|
||||
private static final int[] GOLEMS =
|
||||
{
|
||||
23255,
|
||||
23257,
|
||||
23259,
|
||||
23261,
|
||||
23263,
|
||||
23264,
|
||||
23266,
|
||||
23267,
|
||||
};
|
||||
|
||||
public HillsOfGold()
|
||||
{
|
||||
super(HillsOfGold.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(YIN_FRAGMENT);
|
||||
addSpawnId(SPICULA_1, SPICULA_2);
|
||||
addSpawnId(GOLEMS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equals("SPICULA_AGGRO") && (npc != null) && !npc.isDead())
|
||||
{
|
||||
for (L2Character nearby : npc.getKnownList().getKnownCharactersInRadius(npc.getAggroRange()))
|
||||
{
|
||||
if (npc.isInCombat())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (nearby.isMonster() && ((nearby.getId() == GOLEM_OF_REPAIRS) || (nearby.getId() == EXCAVATOR_GOLEM) || (nearby.getId() == DRILL_GOLEM)))
|
||||
{
|
||||
addAttackDesire(npc, nearby);
|
||||
break;
|
||||
}
|
||||
}
|
||||
startQuestTimer("SPICULA_AGGRO", 10000, npc, null);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
final L2Npc mob1 = addSpawn(SPICULA_ELITE_GUARD, npc.getX(), npc.getY(), npc.getZ(), attacker.getHeading() + 32500, true, npc.getSpawn().getRespawnDelay());
|
||||
addAttackDesire(mob1, attacker);
|
||||
final L2Npc mob2 = addSpawn(SPICULA_ELITE_GUARD, npc.getX(), npc.getY(), npc.getZ(), attacker.getHeading() + 32500, true, npc.getSpawn().getRespawnDelay());
|
||||
addAttackDesire(mob2, attacker);
|
||||
final L2Npc mob3 = addSpawn(SPICULA_ELITE_GUARD, npc.getX(), npc.getY(), npc.getZ(), attacker.getHeading() + 32500, true, npc.getSpawn().getRespawnDelay());
|
||||
addAttackDesire(mob3, attacker);
|
||||
final L2Npc mob4 = addSpawn(SPICULA_ELITE_GUARD, npc.getX(), npc.getY(), npc.getZ(), attacker.getHeading() + 32500, true, npc.getSpawn().getRespawnDelay());
|
||||
addAttackDesire(mob4, attacker);
|
||||
npc.deleteMe();
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
if ((npc.getId() == SPICULA_1) || (npc.getId() == SPICULA_2))
|
||||
{
|
||||
startQuestTimer("SPICULA_AGGRO", 5000, npc, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.setDisplayEffect(1);
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new HillsOfGold();
|
||||
}
|
||||
}
|
||||
107
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/HotSprings.java
vendored
Normal file
107
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/HotSprings.java
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.datatables.SkillData;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.skills.BuffInfo;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Hot Springs AI.
|
||||
* @author Pandragon
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
81
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/IsleOfPrayer.java
vendored
Normal file
81
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/IsleOfPrayer.java
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.ItemChanceHolder;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Isle of Prayer AI.
|
||||
* @author Zoey76
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
140
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/LairOfAntharas.java
vendored
Normal file
140
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/LairOfAntharas.java
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.ValidateLocation;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Lair of Antharas AI.
|
||||
* @author St3eT, UnAfraid
|
||||
*/
|
||||
final class LairOfAntharas extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int KNORIKS = 22857;
|
||||
private static final int DRAGON_KNIGHT = 22844;
|
||||
private static final int DRAGON_KNIGHT2 = 22845;
|
||||
private static final int ELITE_DRAGON_KNIGHT = 22846;
|
||||
|
||||
private static final int DRAGON_GUARD = 22852;
|
||||
private static final int DRAGON_MAGE = 22853;
|
||||
// Misc
|
||||
private static final int KNIGHT_CHANCE = 30;
|
||||
private static final int KNORIKS_CHANCE = 60;
|
||||
private static final 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, ChatType.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, ChatType.NPC_SHOUT, NpcStringId.THOSE_WHO_SET_FOOT_IN_THIS_PLACE_SHALL_NOT_LEAVE_ALIVE);
|
||||
addAttackDesire(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, ChatType.NPC_SHOUT, NpcStringId.IF_YOU_WISH_TO_SEE_HELL_I_WILL_GRANT_YOU_YOUR_WISH);
|
||||
addAttackDesire(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)
|
||||
{
|
||||
if ((npc.getId() == DRAGON_GUARD) || (npc.getId() == DRAGON_MAGE))
|
||||
{
|
||||
npc.setIsNoRndWalk(true);
|
||||
startQuestTimer("CHECK_HOME", 10000, npc, null, true);
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new LairOfAntharas();
|
||||
}
|
||||
}
|
||||
450
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/MinionSpawnManager.java
vendored
Normal file
450
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/MinionSpawnManager.java
vendored
Normal file
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.MinionHolder;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Minion Spawn Manager.
|
||||
* @author Zealar
|
||||
*/
|
||||
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(26094); // Sola
|
||||
NPC.add(26096); // Ariarc
|
||||
NPC.add(26099); // Sirra
|
||||
NPC.add(26102); // Dark Rider
|
||||
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(29001); // Queen Ant
|
||||
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() && !((L2MonsterInstance) npc).isTeleporting() && (getRandom(1, 100) <= npc.getTemplate().getParameters().getInt("SummonPrivateRate", 0)))
|
||||
{
|
||||
for (MinionHolder is : npc.getTemplate().getParameters().getMinionList("Privates"))
|
||||
{
|
||||
addMinion((L2MonsterInstance) npc, is.getId());
|
||||
}
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, ON_ATTACK_MSG[getRandom(ON_ATTACK_MSG.length)]);
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new MinionSpawnManager();
|
||||
}
|
||||
}
|
||||
291
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/MonasteryOfSilence.java
vendored
Normal file
291
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/MonasteryOfSilence.java
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.effects.L2EffectType;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Monastery of Silence AI.
|
||||
* @author Kerberos, nonom
|
||||
*/
|
||||
final class MonasteryOfSilence extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int CAPTAIN = 18910; // Solina Knight Captain
|
||||
private static final int KNIGHT = 18909; // Solina Knights
|
||||
private static final int SCARECROW = 18912; // Scarecrow
|
||||
private static final int GUIDE = 22789; // Guide Solina
|
||||
private static final int SEEKER = 22790; // Seeker Solina
|
||||
private static final int SAVIOR = 22791; // Savior Solina
|
||||
private static final int ASCETIC = 22793; // Ascetic Solina
|
||||
private static final int[] DIVINITY_CLAN =
|
||||
{
|
||||
22794, // Divinity Judge
|
||||
22795, // Divinity Manager
|
||||
};
|
||||
// Skills
|
||||
private static final SkillHolder ORDEAL_STRIKE = new SkillHolder(6303, 1); // Trial of the Coup
|
||||
private static final SkillHolder LEADER_STRIKE = new SkillHolder(6304, 1); // Shock
|
||||
private static final SkillHolder SAVER_STRIKE = new SkillHolder(6305, 1); // Sacred Gnosis
|
||||
private static final SkillHolder SAVER_BLEED = new SkillHolder(6306, 1); // Solina Strike
|
||||
private static final SkillHolder LEARNING_MAGIC = new SkillHolder(6308, 1); // Opus of the Wave
|
||||
private static final SkillHolder STUDENT_CANCEL = new SkillHolder(6310, 1); // Loss of Quest
|
||||
private static final SkillHolder WARRIOR_THRUSTING = new SkillHolder(6311, 1); // Solina Thrust
|
||||
private static final SkillHolder KNIGHT_BLESS = new SkillHolder(6313, 1); // Solina Bless
|
||||
// Misc
|
||||
private static final NpcStringId[] DIVINITY_MSG =
|
||||
{
|
||||
NpcStringId.S1_WHY_WOULD_YOU_CHOOSE_THE_PATH_OF_DARKNESS,
|
||||
NpcStringId.S1_HOW_DARE_YOU_DEFY_THE_WILL_OF_EINHASAD
|
||||
};
|
||||
private static final NpcStringId[] SOLINA_KNIGHTS_MSG =
|
||||
{
|
||||
NpcStringId.PUNISH_ALL_THOSE_WHO_TREAD_FOOTSTEPS_IN_THIS_PLACE,
|
||||
NpcStringId.WE_ARE_THE_SWORD_OF_TRUTH_THE_SWORD_OF_SOLINA,
|
||||
NpcStringId.WE_RAISE_OUR_BLADES_FOR_THE_GLORY_OF_SOLINA
|
||||
};
|
||||
|
||||
private MonasteryOfSilence()
|
||||
{
|
||||
super(MonasteryOfSilence.class.getSimpleName(), "ai/group_template");
|
||||
addSkillSeeId(DIVINITY_CLAN);
|
||||
addAttackId(KNIGHT, CAPTAIN, GUIDE, SEEKER, ASCETIC);
|
||||
addNpcHateId(GUIDE, SEEKER, SAVIOR, ASCETIC);
|
||||
addAggroRangeEnterId(GUIDE, SEEKER, SAVIOR, ASCETIC);
|
||||
addSpawnId(SCARECROW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "TRAINING":
|
||||
{
|
||||
for (L2Character character : npc.getKnownList().getKnownCharactersInRadius(400))
|
||||
{
|
||||
if ((getRandom(100) < 30) && character.isNpc() && !character.isDead() && !character.isInCombat())
|
||||
{
|
||||
if ((character.getId() == CAPTAIN) && (getRandom(100) < 10) && npc.isScriptValue(0))
|
||||
{
|
||||
final L2Npc captain = (L2Npc) character;
|
||||
broadcastNpcSay(captain, ChatType.NPC_GENERAL, SOLINA_KNIGHTS_MSG[getRandom(SOLINA_KNIGHTS_MSG.length)]);
|
||||
captain.setScriptValue(1);
|
||||
startQuestTimer("TIMER", 10000, captain, null);
|
||||
}
|
||||
else if (character.getId() == KNIGHT)
|
||||
{
|
||||
addAttackDesire((L2Npc) character, npc);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "DO_CAST":
|
||||
{
|
||||
if ((npc != null) && (player != null) && (getRandom(100) < 3))
|
||||
{
|
||||
if (npc.checkDoCastConditions(STUDENT_CANCEL.getSkill()))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(STUDENT_CANCEL.getSkill());
|
||||
}
|
||||
npc.setScriptValue(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "TIMER":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
npc.setScriptValue(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon)
|
||||
{
|
||||
final L2Attackable mob = (L2Attackable) npc;
|
||||
|
||||
switch (npc.getId())
|
||||
{
|
||||
case KNIGHT:
|
||||
{
|
||||
if ((getRandom(100) < 10) && (mob.getMostHated() == player) && mob.checkDoCastConditions(WARRIOR_THRUSTING.getSkill()))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(WARRIOR_THRUSTING.getSkill());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CAPTAIN:
|
||||
{
|
||||
if ((getRandom(100) < 20) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.5)) && npc.isScriptValue(0))
|
||||
{
|
||||
if (npc.checkDoCastConditions(KNIGHT_BLESS.getSkill()))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(KNIGHT_BLESS.getSkill());
|
||||
}
|
||||
npc.setScriptValue(1);
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.FOR_THE_GLORY_OF_SOLINA);
|
||||
addAttackDesire(addSpawn(KNIGHT, npc), player);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GUIDE:
|
||||
{
|
||||
if ((getRandom(100) < 3) && (mob.getMostHated() == player) && npc.checkDoCastConditions(ORDEAL_STRIKE.getSkill()))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(ORDEAL_STRIKE.getSkill());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SEEKER:
|
||||
{
|
||||
if ((getRandom(100) < 33) && (mob.getMostHated() == player) && npc.checkDoCastConditions(SAVER_STRIKE.getSkill()))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(SAVER_STRIKE.getSkill());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ASCETIC:
|
||||
{
|
||||
if ((mob.getMostHated() == player) && npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
startQuestTimer("DO_CAST", 20000, npc, player);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, player, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onNpcHate(L2Attackable mob, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
return player.getActiveWeaponInstance() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
if (player.getActiveWeaponInstance() != null)
|
||||
{
|
||||
SkillHolder skill = null;
|
||||
switch (npc.getId())
|
||||
{
|
||||
case GUIDE:
|
||||
{
|
||||
if (getRandom(100) < 3)
|
||||
{
|
||||
skill = LEADER_STRIKE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SEEKER:
|
||||
{
|
||||
skill = SAVER_BLEED;
|
||||
break;
|
||||
}
|
||||
case SAVIOR:
|
||||
{
|
||||
skill = LEARNING_MAGIC;
|
||||
break;
|
||||
}
|
||||
case ASCETIC:
|
||||
{
|
||||
if (getRandom(100) < 3)
|
||||
{
|
||||
skill = STUDENT_CANCEL;
|
||||
}
|
||||
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
startQuestTimer("DO_CAST", 20000, npc, player);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((skill != null) && npc.checkDoCastConditions(skill.getSkill()))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(skill.getSkill());
|
||||
}
|
||||
|
||||
if (!npc.isInCombat())
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.YOU_CANNOT_CARRY_A_WEAPON_WITHOUT_AUTHORIZATION);
|
||||
}
|
||||
|
||||
addAttackDesire(npc, player);
|
||||
}
|
||||
return super.onAggroRangeEnter(npc, player, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
|
||||
{
|
||||
if (skill.hasEffectType(L2EffectType.AGGRESSION) && (targets.length != 0))
|
||||
{
|
||||
for (L2Object obj : targets)
|
||||
{
|
||||
if (obj.equals(npc))
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, DIVINITY_MSG[getRandom(DIVINITY_MSG.length)], caster.getName());
|
||||
addAttackDesire(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();
|
||||
}
|
||||
}
|
||||
50
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/NonLethalableNpcs.java
vendored
Normal file
50
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/NonLethalableNpcs.java
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* @author UnAfraid
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
56
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/NonRandomWalkNpcs.java
vendored
Normal file
56
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/NonRandomWalkNpcs.java
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Non Random Walk Npcs AI.
|
||||
* @author Mobius
|
||||
*/
|
||||
final class NonRandomWalkNpcs extends AbstractNpcAI
|
||||
{
|
||||
private static final int[] NPCS =
|
||||
{
|
||||
27540, // Fields of Massacre - Embryo Purifier
|
||||
27541, // Fields of Massacre - Embryo Purifier
|
||||
23537, // Atelia Fortress - Atelia Infuser
|
||||
23583, // Atelia Fortress - Embryo Master Artisan
|
||||
23588, // Atelia Fortress - Hummel
|
||||
23587, // Atelia Fortress - Burnstein
|
||||
};
|
||||
|
||||
public NonRandomWalkNpcs()
|
||||
{
|
||||
super(NonRandomWalkNpcs.class.getSimpleName(), "ai/group_template");
|
||||
addSpawnId(NPCS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
npc.setIsNoRndWalk(true);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new NonRandomWalkNpcs();
|
||||
}
|
||||
}
|
||||
66
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PaganKey.java
vendored
Normal file
66
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PaganKey.java
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.ItemChanceHolder;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Pagan Key AI.
|
||||
* @author Zoey76. Adapted to PaganKey by Notorionn
|
||||
*/
|
||||
final class PaganKey extends AbstractNpcAI
|
||||
{
|
||||
// Items
|
||||
private static final int PAGAN_KEY = 8273;
|
||||
// Monsters
|
||||
private static final Map<Integer, ItemChanceHolder> MONSTERS = new HashMap<>();
|
||||
static
|
||||
{
|
||||
MONSTERS.put(22140, new ItemChanceHolder(PAGAN_KEY, 7000)); // Resurrected Worker
|
||||
MONSTERS.put(22141, new ItemChanceHolder(PAGAN_KEY, 6500)); // Forgotten Victim
|
||||
MONSTERS.put(22139, new ItemChanceHolder(PAGAN_KEY, 5200)); // Old Aristocrat's Soldier
|
||||
}
|
||||
|
||||
private PaganKey()
|
||||
{
|
||||
super(PaganKey.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 PaganKey();
|
||||
}
|
||||
}
|
||||
80
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PaganTemple.java
vendored
Normal file
80
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PaganTemple.java
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Pagan Temple AI.
|
||||
* @author Mobius
|
||||
*/
|
||||
final class PaganTemple extends AbstractNpcAI
|
||||
{
|
||||
// Npc
|
||||
private static final int TRIOL_HIGH_PRIEST = 19410;
|
||||
private static final int CHAPEL_GATEKEEPER = 22138;
|
||||
|
||||
public PaganTemple()
|
||||
{
|
||||
super(PaganTemple.class.getSimpleName(), "ai/group_template");
|
||||
addSpawnId(TRIOL_HIGH_PRIEST, CHAPEL_GATEKEEPER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equals("DESPAWN_TRIOL") && (npc != null))
|
||||
{
|
||||
if (npc.isInCombat())
|
||||
{
|
||||
startQuestTimer("DESPAWN_TRIOL", 10000, npc, null, false); // 10 seconds delay
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.deleteMe();
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
switch (npc.getId())
|
||||
{
|
||||
case CHAPEL_GATEKEEPER:
|
||||
{
|
||||
npc.setIsNoRndWalk(true);
|
||||
break;
|
||||
}
|
||||
case TRIOL_HIGH_PRIEST:
|
||||
{
|
||||
startQuestTimer("DESPAWN_TRIOL", 10000, npc, null, false); // 10 seconds delay
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PaganTemple();
|
||||
}
|
||||
}
|
||||
60
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PavelArchaic.java
vendored
Normal file
60
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PavelArchaic.java
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Pavel Archaic AI.
|
||||
* @author Gnacik, St3eT
|
||||
*/
|
||||
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);
|
||||
addAttackDesire(golem1, killer);
|
||||
|
||||
final L2Npc golem2 = addSpawn(PINCER_GOLEM3, npc.getX(), npc.getY(), npc.getZ() + 10, npc.getHeading(), false, 0, false);
|
||||
addAttackDesire(golem2, killer);
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PavelArchaic();
|
||||
}
|
||||
}
|
||||
97
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PlainsOfDion.java
vendored
Normal file
97
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PlainsOfDion.java
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.GeoData;
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.util.Util;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* AI for mobs in Plains of Dion (near Floran Village).
|
||||
* @author Gladicek
|
||||
*/
|
||||
final class PlainsOfDion extends AbstractNpcAI
|
||||
{
|
||||
private static final int DELU_LIZARDMEN[] =
|
||||
{
|
||||
21104, // Delu Lizardman Supplier
|
||||
21105, // Delu Lizardman Special Agent
|
||||
21107, // Delu Lizardman Commander
|
||||
};
|
||||
|
||||
private static final NpcStringId[] MONSTERS_MSG =
|
||||
{
|
||||
NpcStringId.S1_HOW_DARE_YOU_INTERRUPT_OUR_FIGHT_HEY_GUYS_HELP,
|
||||
NpcStringId.S1_HEY_WE_RE_HAVING_A_DUEL_HERE,
|
||||
NpcStringId.THE_DUEL_IS_OVER_ATTACK,
|
||||
NpcStringId.FOUL_KILL_THE_COWARD,
|
||||
NpcStringId.HOW_DARE_YOU_INTERRUPT_A_SACRED_DUEL_YOU_MUST_BE_TAUGHT_A_LESSON
|
||||
};
|
||||
|
||||
private static final NpcStringId[] MONSTERS_ASSIST_MSG =
|
||||
{
|
||||
NpcStringId.DIE_YOU_COWARD,
|
||||
NpcStringId.KILL_THE_COWARD,
|
||||
NpcStringId.WHAT_ARE_YOU_LOOKING_AT
|
||||
};
|
||||
|
||||
private PlainsOfDion()
|
||||
{
|
||||
super(PlainsOfDion.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(DELU_LIZARDMEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
final int i = getRandom(5);
|
||||
if (i < 2)
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, MONSTERS_MSG[i], player.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, MONSTERS_MSG[i]);
|
||||
}
|
||||
|
||||
for (L2Character obj : npc.getKnownList().getKnownCharactersInRadius(npc.getTemplate().getClanHelpRange()))
|
||||
{
|
||||
if (obj.isMonster() && Util.contains(DELU_LIZARDMEN, obj.getId()) && !obj.isAttackingNow() && !obj.isDead() && GeoData.getInstance().canSeeTarget(npc, obj))
|
||||
{
|
||||
final L2Npc monster = (L2Npc) obj;
|
||||
addAttackDesire(monster, player);
|
||||
broadcastNpcSay(monster, ChatType.NPC_GENERAL, MONSTERS_ASSIST_MSG[getRandom(3)]);
|
||||
}
|
||||
}
|
||||
npc.setScriptValue(1);
|
||||
}
|
||||
return super.onAttack(npc, player, damage, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PlainsOfDion();
|
||||
}
|
||||
}
|
||||
252
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PlainsOfLizardman.java
vendored
Normal file
252
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PlainsOfLizardman.java
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Playable;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Plains of Lizardmen AI.
|
||||
* @author Gnacik, malyelfik
|
||||
*/
|
||||
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());
|
||||
addAttackDesire(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)
|
||||
{
|
||||
addAttackDesire(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();
|
||||
}
|
||||
}
|
||||
61
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PolymorphingAngel.java
vendored
Normal file
61
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PolymorphingAngel.java
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Angel spawns...when one of the angels in the keys dies, the other angel will spawn.
|
||||
*/
|
||||
final class PolymorphingAngel extends AbstractNpcAI
|
||||
{
|
||||
private static final Map<Integer, Integer> ANGELSPAWNS = new HashMap<>();
|
||||
static
|
||||
{
|
||||
ANGELSPAWNS.put(20830, 20859);
|
||||
ANGELSPAWNS.put(21067, 21068);
|
||||
ANGELSPAWNS.put(21062, 21063);
|
||||
ANGELSPAWNS.put(20831, 20860);
|
||||
ANGELSPAWNS.put(21070, 21071);
|
||||
}
|
||||
|
||||
private PolymorphingAngel()
|
||||
{
|
||||
super(PolymorphingAngel.class.getSimpleName(), "ai/group_template");
|
||||
addKillId(ANGELSPAWNS.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
final L2Attackable newNpc = (L2Attackable) addSpawn(ANGELSPAWNS.get(npc.getId()), npc);
|
||||
newNpc.setRunning();
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PolymorphingAngel();
|
||||
}
|
||||
}
|
||||
112
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PolymorphingOnAttack.java
vendored
Normal file
112
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PolymorphingOnAttack.java
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.CreatureSay;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Polymorphing on attack monsters AI.
|
||||
* @author Slyce
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
private 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) && (npc.getCurrentHp() <= ((npc.getMaxHp() * tmp.get(1)) / 100.0)) && (getRandom(100) < tmp.get(2)))
|
||||
{
|
||||
if (tmp.get(3) >= 0)
|
||||
{
|
||||
final NpcStringId npcString = MOBTEXTS[tmp.get(3)][getRandom(MOBTEXTS[tmp.get(3)].length)];
|
||||
npc.broadcastPacket(new CreatureSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getName(), npcString));
|
||||
}
|
||||
npc.deleteMe();
|
||||
final L2Attackable newNpc = (L2Attackable) addSpawn(tmp.get(0), npc.getX(), npc.getY(), npc.getZ() + 10, npc.getHeading(), false, 0, true);
|
||||
final L2Character originalAttacker = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : attacker;
|
||||
addAttackDesire(newNpc, originalAttacker);
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PolymorphingOnAttack();
|
||||
}
|
||||
}
|
||||
153
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PrisonGuards.java
vendored
Normal file
153
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/PrisonGuards.java
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Prison Guards AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
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) && (getQuestItemsCount(player, STAMP) <= 3) && npc.isScriptValue(0))
|
||||
{
|
||||
giveItems(player, STAMP, 1);
|
||||
npc.setScriptValue(1);
|
||||
startQuestTimer("CLEAR_STATUS", 600000, npc, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(STONE.getSkill());
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.IT_S_NOT_EASY_TO_OBTAIN);
|
||||
}
|
||||
}
|
||||
else if (!player.isAffectedBySkill(TIMER) && (npc.calculateDistance(npc.getSpawn().getLocation(), false, false) < 2000))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(STONE.getSkill());
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.YOU_RE_OUT_OF_YOUR_MIND_COMING_HERE);
|
||||
}
|
||||
return super.onAttack(npc, player, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
|
||||
{
|
||||
if (!caster.isAffectedBySkill(TIMER))
|
||||
{
|
||||
npc.setTarget(caster);
|
||||
npc.doCast(SILENCE.getSkill());
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
|
||||
{
|
||||
if ((skill == SILENCE.getSkill()) || (skill == STONE.getSkill()))
|
||||
{
|
||||
((L2Attackable) npc).clearAggroList();
|
||||
npc.setTarget(npc);
|
||||
}
|
||||
return super.onSpellFinished(npc, player, skill);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onNpcHate(L2Attackable mob, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
return player.isAffectedBySkill(TIMER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
if (npc.getId() == GUARD_HEAD)
|
||||
{
|
||||
npc.setIsImmobilized(true);
|
||||
npc.setIsInvul(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.setIsNoRndWalk(true);
|
||||
cancelQuestTimer("CHECK_HOME", npc, null);
|
||||
startQuestTimer("CHECK_HOME", 30000, npc, null);
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new PrisonGuards();
|
||||
}
|
||||
}
|
||||
121
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/RandomSpawn.java
vendored
Normal file
121
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/RandomSpawn.java
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.ThreadPoolManager;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Manages spawn of NPCs having several random spawn points.
|
||||
* @author GKR
|
||||
*/
|
||||
final class RandomSpawn extends AbstractNpcAI
|
||||
{
|
||||
private static final Map<Integer, Location[]> SPAWN_POINTS = new HashMap<>();
|
||||
static
|
||||
{
|
||||
// Keltas
|
||||
SPAWN_POINTS.put(22341, new Location[]
|
||||
{
|
||||
new Location(-27136, 250938, -3523),
|
||||
new Location(-29658, 252897, -3523),
|
||||
new Location(-27237, 251943, -3527),
|
||||
new Location(-28868, 250113, -3479)
|
||||
});
|
||||
// Keymaster
|
||||
SPAWN_POINTS.put(22361, new Location[]
|
||||
{
|
||||
new Location(14091, 250533, -1940),
|
||||
new Location(15762, 252440, -2015),
|
||||
new Location(19836, 256212, -2090),
|
||||
new Location(21940, 254107, -2010),
|
||||
new Location(17299, 252943, -2015),
|
||||
});
|
||||
// Typhoon
|
||||
SPAWN_POINTS.put(25539, new Location[]
|
||||
{
|
||||
new Location(-20641, 255370, -3235),
|
||||
new Location(-16157, 250993, -3058),
|
||||
new Location(-18269, 250721, -3151),
|
||||
new Location(-16532, 254864, -3223),
|
||||
new Location(-19055, 253489, -3440),
|
||||
new Location(-9684, 254256, -3148),
|
||||
new Location(-6209, 251924, -3189),
|
||||
new Location(-10547, 251359, -2929),
|
||||
new Location(-7254, 254997, -3261),
|
||||
new Location(-4883, 253171, -3322)
|
||||
});
|
||||
// Mutated Elpy
|
||||
SPAWN_POINTS.put(25604, new Location[]
|
||||
{
|
||||
new Location(-46080, 246368, -14183),
|
||||
new Location(-44816, 246368, -14183),
|
||||
new Location(-44224, 247440, -14184),
|
||||
new Location(-44896, 248464, -14183),
|
||||
new Location(-46064, 248544, -14183),
|
||||
new Location(-46720, 247424, -14183)
|
||||
});
|
||||
}
|
||||
|
||||
public RandomSpawn()
|
||||
{
|
||||
super(RandomSpawn.class.getSimpleName(), "ai/group_template");
|
||||
addSpawnId(SPAWN_POINTS.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String onSpawn(L2Npc npc)
|
||||
{
|
||||
final Location[] spawnlist = SPAWN_POINTS.get(npc.getId());
|
||||
final Location loc = spawnlist[getRandom(spawnlist.length)];
|
||||
if (!npc.isInsideRadius(loc, 200, false, false))
|
||||
{
|
||||
npc.getSpawn().setLocation(loc);
|
||||
ThreadPoolManager.getInstance().scheduleGeneral(new Teleport(npc, loc), 100);
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
private static class Teleport implements Runnable
|
||||
{
|
||||
private final L2Npc _npc;
|
||||
private final Location _loc;
|
||||
|
||||
public Teleport(L2Npc npc, Location loc)
|
||||
{
|
||||
_npc = npc;
|
||||
_loc = loc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
_npc.teleToLocation(_loc, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new RandomSpawn();
|
||||
}
|
||||
}
|
||||
72
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/Remnants.java
vendored
Normal file
72
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/Remnants.java
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Remnants AI.
|
||||
* @author DS
|
||||
*/
|
||||
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) && !npc.isDead() && (targets.length > 0) && (targets[0] == npc) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.02)))
|
||||
{
|
||||
npc.doDie(caster);
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Remnants();
|
||||
}
|
||||
}
|
||||
54
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/Sandstorms.java
vendored
Normal file
54
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/Sandstorms.java
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Sandstorms AI.
|
||||
* @author Ectis
|
||||
*/
|
||||
final 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();
|
||||
}
|
||||
}
|
||||
61
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/SeeThroughSilentMove.java
vendored
Normal file
61
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/SeeThroughSilentMove.java
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* See Through Silent Move AI.
|
||||
* @author Gigiikun
|
||||
*/
|
||||
final 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();
|
||||
}
|
||||
}
|
||||
218
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/SilentValley.java
vendored
Normal file
218
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/SilentValley.java
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Summon;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Silent Valley AI
|
||||
* @author malyelfik
|
||||
*/
|
||||
final class SilentValley extends AbstractNpcAI
|
||||
{
|
||||
// Skills
|
||||
private static final SkillHolder BETRAYAL = new SkillHolder(6033, 1); // Treasure Seeker's Betrayal
|
||||
private static final SkillHolder BLAZE = new SkillHolder(4157, 10); // NPC Blaze - Magic
|
||||
// Item
|
||||
private static final int SACK = 13799; // Treasure Sack of the Ancient Giants
|
||||
// Chance
|
||||
private static final int SPAWN_CHANCE = 2;
|
||||
private static final int CHEST_DIE_CHANCE = 5;
|
||||
// Monsters
|
||||
private static final int CHEST = 18693; // Treasure Chest of the Ancient Giants
|
||||
private static final int GUARD1 = 18694; // Treasure Chest Guard
|
||||
private static final int GUARD2 = 18695; // Treasure Chest Guard
|
||||
private static final int[] MOBS =
|
||||
{
|
||||
20965, // Chimera Piece
|
||||
20966, // Changed Creation
|
||||
20967, // Past Creature
|
||||
20968, // Nonexistent Man
|
||||
20969, // Giant's Shadow
|
||||
20970, // Soldier of Ancient Times
|
||||
20971, // Warrior of Ancient Times
|
||||
20972, // Shaman of Ancient Times
|
||||
20973, // Forgotten Ancient People
|
||||
};
|
||||
|
||||
private SilentValley()
|
||||
{
|
||||
super(SilentValley.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(MOBS);
|
||||
addAttackId(CHEST, GUARD1, GUARD2);
|
||||
addEventReceivedId(GUARD1, GUARD2);
|
||||
addKillId(MOBS);
|
||||
addSeeCreatureId(MOBS);
|
||||
addSeeCreatureId(GUARD1, GUARD2);
|
||||
addSpawnId(CHEST, GUARD2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if ((npc != null) && !npc.isDead())
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "CLEAR":
|
||||
{
|
||||
npc.doDie(null);
|
||||
break;
|
||||
}
|
||||
case "CLEAR_EVENT":
|
||||
{
|
||||
npc.broadcastEvent("CLEAR_ALL_INSTANT", 2000, null);
|
||||
npc.doDie(null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN_CHEST":
|
||||
{
|
||||
addSpawn(CHEST, npc.getX() - 100, npc.getY(), npc.getZ() - 100, 0, false, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon)
|
||||
{
|
||||
switch (npc.getId())
|
||||
{
|
||||
case CHEST:
|
||||
{
|
||||
if (!isSummon && npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.YOU_WILL_BE_CURSED_FOR_SEEKING_THE_TREASURE);
|
||||
npc.setTarget(player);
|
||||
npc.doCast(BETRAYAL.getSkill());
|
||||
}
|
||||
else if (isSummon || (getRandom(100) < CHEST_DIE_CHANCE))
|
||||
{
|
||||
npc.dropItem(player, SACK, 1);
|
||||
npc.broadcastEvent("CLEAR_ALL", 2000, null);
|
||||
npc.doDie(null);
|
||||
cancelQuestTimer("CLEAR_EVENT", npc, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GUARD1:
|
||||
case GUARD2:
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(BLAZE.getSkill());
|
||||
addAttackDesire(npc, player);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (isSummon)
|
||||
{
|
||||
addAttackDesire(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());
|
||||
addAttackDesire(npc, player);
|
||||
}
|
||||
else if (creature.isAffectedBySkill(BETRAYAL.getSkillId()))
|
||||
{
|
||||
addAttackDesire(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();
|
||||
}
|
||||
}
|
||||
255
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/StakatoNest.java
vendored
Normal file
255
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/StakatoNest.java
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.datatables.SkillData;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
|
||||
import com.l2jmobius.gameserver.util.Broadcast;
|
||||
import com.l2jmobius.gameserver.util.Util;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Stakato Nest AI.
|
||||
* @author Gnacik
|
||||
*/
|
||||
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)
|
||||
{
|
||||
final 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++)
|
||||
{
|
||||
final L2Npc spawned = addSpawn(STAKATO_CAPTAIN, monster, true);
|
||||
addAttackDesire(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++)
|
||||
{
|
||||
final L2Npc spawned = addSpawn(STAKATO_GUARD, monster, true);
|
||||
addAttackDesire(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())
|
||||
{
|
||||
for (L2PcInstance member : killer.getParty().getMembers())
|
||||
{
|
||||
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);
|
||||
addAttackDesire(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);
|
||||
addAttackDesire(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();
|
||||
}
|
||||
}
|
||||
103
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/SummonPc.java
vendored
Normal file
103
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/SummonPc.java
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Summon Pc AI.<br>
|
||||
* Summon the player to the NPC on attack.
|
||||
* @author Zoey76
|
||||
*/
|
||||
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);
|
||||
// Misc
|
||||
private static final int MIN_DISTANCE = 300;
|
||||
private static final int MIN_DISTANCE_MOST_HATED = 100;
|
||||
|
||||
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 boolean attacked = npc.getVariables().getBoolean("attacked", false);
|
||||
if (attacked)
|
||||
{
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
final int chance = getRandom(100);
|
||||
final double distance = npc.calculateDistance(attacker, true, false);
|
||||
if (distance > MIN_DISTANCE)
|
||||
{
|
||||
if (chance < 50)
|
||||
{
|
||||
doSummonPc(npc, attacker);
|
||||
}
|
||||
}
|
||||
else if ((distance > MIN_DISTANCE_MOST_HATED) && (((L2Attackable) npc).getMostHated() != null) && (((((L2Attackable) npc).getMostHated() == attacker) && (chance < 50)) || (chance < 10)))
|
||||
{
|
||||
doSummonPc(npc, attacker);
|
||||
}
|
||||
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);
|
||||
|
||||
// TODO(Zoey76): Teleport removes the player from all known lists, affecting aggro lists.
|
||||
addAttackDesire(npc, player);
|
||||
}
|
||||
return super.onSpellFinished(npc, player, skill);
|
||||
}
|
||||
|
||||
private static void doSummonPc(L2Npc npc, L2PcInstance attacker)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new SummonPc();
|
||||
}
|
||||
}
|
||||
151
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/TurekOrcs.java
vendored
Normal file
151
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/TurekOrcs.java
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.L2World;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Turek Orcs AI - flee and return with assistance
|
||||
* @author GKR
|
||||
*/
|
||||
final class TurekOrcs extends AbstractNpcAI
|
||||
{
|
||||
// Monster to spawn
|
||||
private static final int CHERTUBA_ILLUSION = 23422;
|
||||
private static final int CHERTUBA_MIRAGE = 23421;
|
||||
// NPCs
|
||||
private static final int[] MOBS =
|
||||
{
|
||||
20494, // Turek War Hound
|
||||
20495, // Turek Orc Prefect
|
||||
20496, // Turek Orc Archer
|
||||
20497, // Turek Orc Skirmisher
|
||||
20498, // Turek Orc Supplier
|
||||
20499, // Turek Orc Footman
|
||||
20500, // Turek Orc Sentinel
|
||||
20501, // Turek Orc Priest
|
||||
20546, // Turek Orc Elder
|
||||
};
|
||||
|
||||
private TurekOrcs()
|
||||
{
|
||||
super(TurekOrcs.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(MOBS);
|
||||
addEventReceivedId(MOBS);
|
||||
addMoveFinishedId(MOBS);
|
||||
addKillId(20495, 20496, 20497, 20499, 20500, 20501, 20546);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("checkState") && !npc.isDead() && (npc.getAI().getIntention() != CtrlIntention.AI_INTENTION_ATTACK))
|
||||
{
|
||||
if ((npc.getCurrentHp() > (npc.getMaxHp() * 0.7)) && (npc.getVariables().getInt("state") == 2))
|
||||
{
|
||||
npc.getVariables().set("state", 3);
|
||||
((L2Attackable) npc).returnHome();
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.getVariables().remove("state");
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (!npc.getVariables().hasVariable("isHit"))
|
||||
{
|
||||
npc.getVariables().set("isHit", 1);
|
||||
}
|
||||
else if ((npc.getCurrentHp() < (npc.getMaxHp() * 0.5)) && (npc.getCurrentHp() > (npc.getMaxHp() * 0.3)) && (attacker.getCurrentHp() > (attacker.getMaxHp() * 0.25)) && npc.hasAIValue("fleeX") && npc.hasAIValue("fleeY") && npc.hasAIValue("fleeZ") && (npc.getVariables().getInt("state") == 0) && (getRandom(100) < 10))
|
||||
{
|
||||
// Say and flee
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.getNpcStringId(getRandom(1000007, 1000027)));
|
||||
npc.disableCoreAI(true); // to avoid attacking behaviour, while flee
|
||||
npc.setIsRunning(true);
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(npc.getAIValue("fleeX"), npc.getAIValue("fleeY"), npc.getAIValue("fleeZ")));
|
||||
npc.getVariables().set("state", 1);
|
||||
npc.getVariables().set("attacker", attacker.getObjectId());
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onEventReceived(String eventName, L2Npc sender, L2Npc receiver, L2Object reference)
|
||||
{
|
||||
if (eventName.equals("WARNING") && !receiver.isDead() && (receiver.getAI().getIntention() != CtrlIntention.AI_INTENTION_ATTACK) && (reference != null) && (reference.getActingPlayer() != null) && !reference.getActingPlayer().isDead())
|
||||
{
|
||||
receiver.getVariables().set("state", 3);
|
||||
addAttackDesire(receiver, reference.getActingPlayer());
|
||||
}
|
||||
return super.onEventReceived(eventName, sender, receiver, reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
final L2Npc newSpawn = addSpawn(getRandomBoolean() ? CHERTUBA_MIRAGE : CHERTUBA_ILLUSION, npc.getLocation(), false, 300000); // 5 minute despawn time
|
||||
addAttackDesire(newSpawn, killer);
|
||||
showOnScreenMsg(killer, NpcStringId.A_POWERFUL_MONSTER_HAS_COME_TO_FACE_YOU, ExShowScreenMessage.TOP_CENTER, 4500);
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
136
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/WarriorFishingBlock.java
vendored
Normal file
136
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/WarriorFishingBlock.java
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Warrior Fishing Block AI.
|
||||
* @author Zoey76
|
||||
*/
|
||||
final class WarriorFishingBlock extends AbstractNpcAI
|
||||
{
|
||||
// Monsters
|
||||
private static final int[] MONSTERS =
|
||||
{
|
||||
18319, // Caught Frog
|
||||
18320, // Caught Undine
|
||||
18321, // Caught Rakul
|
||||
18322, // Caught Sea Giant
|
||||
18323, // Caught Sea Horse Soldier
|
||||
18324, // Caught Homunculus
|
||||
18325, // Caught Flava
|
||||
18326, // Caught Gigantic Eye
|
||||
};
|
||||
// NPC Strings
|
||||
private static final NpcStringId[] NPC_STRINGS_ON_SPAWN =
|
||||
{
|
||||
NpcStringId.CROAK_CROAK_FOOD_LIKE_S1_IN_THIS_PLACE,
|
||||
NpcStringId.S1_HOW_LUCKY_I_AM,
|
||||
NpcStringId.PRAY_THAT_YOU_CAUGHT_A_WRONG_FISH_S1
|
||||
};
|
||||
private static final NpcStringId[] NPC_STRINGS_ON_ATTACK =
|
||||
{
|
||||
NpcStringId.DO_YOU_KNOW_WHAT_A_FROG_TASTES_LIKE,
|
||||
NpcStringId.I_WILL_SHOW_YOU_THE_POWER_OF_A_FROG,
|
||||
NpcStringId.I_WILL_SWALLOW_AT_A_MOUTHFUL
|
||||
};
|
||||
private static final NpcStringId[] NPC_STRINGS_ON_KILL =
|
||||
{
|
||||
NpcStringId.UGH_NO_CHANCE_HOW_COULD_THIS_ELDER_PASS_AWAY_LIKE_THIS,
|
||||
NpcStringId.CROAK_CROAK_A_FROG_IS_DYING,
|
||||
NpcStringId.A_FROG_TASTES_BAD_YUCK
|
||||
};
|
||||
// Misc
|
||||
private static final int CHANCE_TO_SHOUT_ON_ATTACK = 33;
|
||||
private static final int DESPAWN_TIME = 50; // 50 seconds to despawn
|
||||
|
||||
public WarriorFishingBlock()
|
||||
{
|
||||
super(WarriorFishingBlock.class.getSimpleName(), "ai/group_template");
|
||||
addAttackId(MONSTERS);
|
||||
addKillId(MONSTERS);
|
||||
addSpawnId(MONSTERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "SPAWN":
|
||||
{
|
||||
final L2Object obj = npc.getTarget();
|
||||
if ((obj == null) || !obj.isPlayer())
|
||||
{
|
||||
npc.decayMe();
|
||||
}
|
||||
else
|
||||
{
|
||||
final L2PcInstance target = obj.getActingPlayer();
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NPC_STRINGS_ON_SPAWN[getRandom(NPC_STRINGS_ON_SPAWN.length)], target.getName());
|
||||
addAttackDesire(npc, target);
|
||||
|
||||
startQuestTimer("DESPAWN", DESPAWN_TIME * 1000, npc, target);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "DESPAWN":
|
||||
{
|
||||
npc.decayMe();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (getRandom(100) < CHANCE_TO_SHOUT_ON_ATTACK)
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NPC_STRINGS_ON_ATTACK[getRandom(NPC_STRINGS_ON_ATTACK.length)]);
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NPC_STRINGS_ON_KILL[getRandom(NPC_STRINGS_ON_KILL.length)]);
|
||||
cancelQuestTimer("DESPAWN", npc, killer);
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
startQuestTimer("SPAWN", 2000, npc, null);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new WarriorFishingBlock();
|
||||
}
|
||||
}
|
||||
75
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/Wasteland.java
vendored
Normal file
75
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/Wasteland.java
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Wasteland AI.
|
||||
* @author Stayway, Mobius
|
||||
*/
|
||||
final class Wasteland extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int JOEL = 33516;
|
||||
private static final int SHUAZEN = 33517;
|
||||
private static final int GUARD = 19126;
|
||||
|
||||
public Wasteland()
|
||||
{
|
||||
super(Wasteland.class.getSimpleName(), "ai/group_template");
|
||||
addSpawnId(JOEL, SHUAZEN, GUARD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equals("GUARD_AGGRO") && (npc != null) && !npc.isDead())
|
||||
{
|
||||
for (L2Character nearby : npc.getKnownList().getKnownCharactersInRadius(npc.getAggroRange()))
|
||||
{
|
||||
if (npc.isInCombat())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (nearby.isMonster())
|
||||
{
|
||||
addAttackDesire(npc, nearby);
|
||||
break;
|
||||
}
|
||||
}
|
||||
startQuestTimer("GUARD_AGGRO", 10000, npc, null);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
startQuestTimer("GUARD_AGGRO", 5000, npc, null);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Wasteland();
|
||||
}
|
||||
}
|
||||
12
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/documentation.txt
vendored
Normal file
12
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/documentation.txt
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
Group Template AI:
|
||||
This folder contains AI scripts for group templates. That is, if many different mobs share the same behaviour,
|
||||
a group AI script can be created for all of them. Such group templates ought to be here.
|
||||
|
||||
Group templates can be subclassed. In other words, a group may inherit from another group. For example,
|
||||
one group template might define mobs that cast spells. Another template may then define the AI for mobs
|
||||
that cast spells AND use shots. In that case, instead of rewriting all the attack and spell-use AI, we can
|
||||
inherit from the first group template, then add the new behaviours, and split up the NPC registrations appropriately.
|
||||
|
||||
"NPC registrations" refers to the addition of NPCs in the various events of the scripts, such as onAttack, onKill, etc
|
||||
Those are done by using keywords such as "addKillId" etc. For more details on registrations, see
|
||||
"scripts/quests/documentation.txt"
|
||||
35
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/package-info.java
vendored
Normal file
35
L2J_Mobius_Test/dist/game/data/scripts/ai/group_template/package-info.java
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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;
|
||||
189
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Anais.java
vendored
Normal file
189
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Anais.java
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Anais AI.
|
||||
* @author nonom
|
||||
*/
|
||||
final class Anais extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int ANAIS = 25701;
|
||||
private static final int DIVINE_BURNER = 18915;
|
||||
private static final int GRAIL_WARD = 18929;
|
||||
// Skill
|
||||
private static SkillHolder DIVINE_NOVA = new SkillHolder(6326, 1);
|
||||
// Instances
|
||||
ArrayList<L2Npc> _divineBurners = new ArrayList<>(4);
|
||||
private L2PcInstance _nextTarget = null;
|
||||
private L2Npc _current = null;
|
||||
private int _pot = 0;
|
||||
|
||||
private Anais()
|
||||
{
|
||||
super(Anais.class.getSimpleName(), "ai/individual");
|
||||
addAttackId(ANAIS);
|
||||
addSpawnId(DIVINE_BURNER);
|
||||
addKillId(GRAIL_WARD);
|
||||
}
|
||||
|
||||
private void burnerOnAttack(int pot, L2Npc anais)
|
||||
{
|
||||
final L2Npc npc = _divineBurners.get(pot);
|
||||
npc.setDisplayEffect(1);
|
||||
npc.setIsRunning(false);
|
||||
if (pot < 4)
|
||||
{
|
||||
_current = npc;
|
||||
if (getQuestTimer("CHECK", anais, null) == null)
|
||||
{
|
||||
startQuestTimer("CHECK", 3000, anais, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cancelQuestTimer("CHECK", anais, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "CHECK":
|
||||
{
|
||||
if (!npc.isAttackingNow())
|
||||
{
|
||||
cancelQuestTimer("CHECK", npc, null);
|
||||
}
|
||||
if ((_current != null) || (_pot < 4))
|
||||
{
|
||||
final Map<Integer, L2PcInstance> players = npc.getKnownList().getKnownPlayers();
|
||||
final L2PcInstance target = players.get(getRandom(players.size() - 1));
|
||||
_nextTarget = target;
|
||||
if (_nextTarget == null)
|
||||
{
|
||||
_nextTarget = (L2PcInstance) npc.getTarget();
|
||||
}
|
||||
final L2Npc b = _divineBurners.get(_pot);
|
||||
_pot = _pot + 1;
|
||||
b.setDisplayEffect(1);
|
||||
b.setIsRunning(false);
|
||||
final L2Npc ward = addSpawn(GRAIL_WARD, new Location(b.getX(), b.getY(), b.getZ()), true, 0);
|
||||
addAttackDesire(ward, _nextTarget);
|
||||
startQuestTimer("GUARD_ATTACK", 1000, ward, _nextTarget, true);
|
||||
startQuestTimer("SUICIDE", 20000, ward, null);
|
||||
ward.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, _nextTarget);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "GUARD_ATTACK":
|
||||
{
|
||||
if (_nextTarget != null)
|
||||
{
|
||||
final double distance = npc.calculateDistance(_nextTarget, false, false);
|
||||
if (distance < 100)
|
||||
{
|
||||
npc.doCast(DIVINE_NOVA.getSkill());
|
||||
}
|
||||
else if (distance > 2000)
|
||||
{
|
||||
npc.doDie(null);
|
||||
cancelQuestTimer("GUARD_ATTACK", npc, player);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SUICIDE":
|
||||
{
|
||||
npc.doCast(DIVINE_NOVA.getSkill());
|
||||
cancelQuestTimer("GUARD_ATTACK", npc, _nextTarget);
|
||||
if (_current != null)
|
||||
{
|
||||
_current.setDisplayEffect(2);
|
||||
_current.setIsRunning(false);
|
||||
_current = null;
|
||||
}
|
||||
npc.doDie(null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (_pot == 0)
|
||||
{
|
||||
burnerOnAttack(0, npc);
|
||||
}
|
||||
else if ((npc.getCurrentHp() <= (npc.getMaxRecoverableHp() * 0.75)) && (_pot == 1))
|
||||
{
|
||||
burnerOnAttack(1, npc);
|
||||
}
|
||||
else if ((npc.getCurrentHp() <= (npc.getMaxRecoverableHp() * 0.5)) && (_pot == 2))
|
||||
{
|
||||
burnerOnAttack(2, npc);
|
||||
}
|
||||
else if ((npc.getCurrentHp() <= (npc.getMaxRecoverableHp() * 0.25)) && (_pot == 3))
|
||||
{
|
||||
burnerOnAttack(3, npc);
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
_divineBurners.add(npc);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
npc.doCast(DIVINE_NOVA.getSkill());
|
||||
cancelQuestTimer("GUARD_ATTACK", npc, _nextTarget);
|
||||
cancelQuestTimer("CHECK", npc, null);
|
||||
if (_current != null)
|
||||
{
|
||||
_current.setDisplayEffect(2);
|
||||
_current.setIsRunning(false);
|
||||
_current = null;
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Anais();
|
||||
}
|
||||
}
|
||||
8
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/13001-01.html
vendored
Normal file
8
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/13001-01.html
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<html><body>Heart of Warding:<br>
|
||||
You are overcome by a voice, a voice so powerful you are helpless as it speaks.<br>
|
||||
<font color="LEVEL">Do not expect Shilen's authority will diminish<br>
|
||||
while false gods freely roam.<br>
|
||||
Leave, and<br>
|
||||
prepare to face the return of Antharas.</font><br>
|
||||
(Challenging Antharas is not currently available.)
|
||||
</body></html>
|
||||
6
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/13001-02.html
vendored
Normal file
6
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/13001-02.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Heart of Warding:<br>
|
||||
You are overcome by a voice, a voice so powerful you are helpless as it speaks:<br>
|
||||
<font color="LEVEL">Do not expect that you might challenge Antharas at your own convenience.<br>
|
||||
When the time is right, Shilen's authority will judge you.</font><br>
|
||||
(Currently, other members are challenging Antharas.)
|
||||
</body></html>
|
||||
6
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/13001-03.html
vendored
Normal file
6
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/13001-03.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Heart of Warding:<br>
|
||||
A voice that can shatter your entire body is resonating in your head:<br>
|
||||
<font color="LEVEL">Do not dare to face Shilen's authority<br>
|
||||
without the most determined preparation.</font><br>
|
||||
(Only those who have the Portal Stone can challenge Antharas.)
|
||||
</body></html>
|
||||
6
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/13001-04.html
vendored
Normal file
6
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/13001-04.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Heart of Warding:<br>
|
||||
You are overcome by a voice, a voice so powerful you are helpless as it speaks:<br>
|
||||
<font color="LEVEL">No matter how many gather to follow false gods,<br>
|
||||
Shilen's authority is too great.</font><br>
|
||||
(The number of participants are above the allowed number in challenging Antharas.)
|
||||
</body></html>
|
||||
6
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/13001-05.html
vendored
Normal file
6
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/13001-05.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<html><body>Heart of Warding:<br>
|
||||
You are overcome by a voice, a voice so powerful you are helpless as it speaks:<br>
|
||||
<font color="LEVEL">You seek death and defeat by coming here without your leader! You appear before Shilen's authority<br>
|
||||
and you tempt Shilen's wrath!</font><br>
|
||||
(The players who belong to an association can only enter through the Association Leader.)
|
||||
</body></html>
|
||||
12
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/13001.html
vendored
Normal file
12
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/13001.html
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<html><body>Heart of Warding:<br>
|
||||
You are overcome by a voice, a voice so powerful you are helpless as it speaks:<br>
|
||||
<font color="LEVEL">A terrible creature <br>
|
||||
fell to the earth from above <br>
|
||||
in order to vent a mother's spite,<br>
|
||||
cursed and forsaken by her own children.<br>
|
||||
Dark Pilgrim of the Holy Land,<br>
|
||||
Do you dare face the Land Dragon Antharas?</font><br>
|
||||
(A maximum of 200 people can challenge Antharas.)<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Antharas enter">Move to Antharas' Nest</Button>
|
||||
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
|
||||
</body></html>
|
||||
1042
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/Antharas.java
vendored
Normal file
1042
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Antharas/Antharas.java
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Baium/31862-01.html
vendored
Normal file
3
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Baium/31862-01.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><head><body>Angelic Vortex:<br>
|
||||
The Angelic Vortex emits a faint light which twinkles out. The vortex becomes inactive. It seems like, in order to go to the place where the Angelic Vortex is leading, you will need some special object.
|
||||
</body></html>
|
||||
5
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Baium/31862-02.html
vendored
Normal file
5
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Baium/31862-02.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Angelic Vortex:<br>
|
||||
The Angelic Vortex emits a faint light, in the midst of which an image appears. A giant that normally appears as a stone statue has come alive and is fighting with many people. Even angels have joined the fray. It seems that the angels are angry at the humans who have broken the seal of the stone statue.<br>
|
||||
It appears impossible to cross over to that place right now. You have no choice but to wait until the fight is over.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Baium 31862-04.html">Ask about the stone statue that has come alive.</Button>
|
||||
</body></html>
|
||||
5
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Baium/31862-03.html
vendored
Normal file
5
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Baium/31862-03.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Angelic Vortex:<br>
|
||||
The Angelic Vortex emits a faint light, in the midst of which an image appears. A large, open space... but the gigantic, human-like stone statue is no longer there.<br>
|
||||
It seems that while the statue is not visible, one could cross over to that place.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Baium 31862-04.html">Ask about the stone statue.</Button>
|
||||
</body></html>
|
||||
7
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Baium/31862-04.html
vendored
Normal file
7
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Baium/31862-04.html
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<html><body>Angelic Vortex:<br>
|
||||
In ancient times a mighty emperor named Baium became so enamored of his own power that he began to fancy himself a god. He conscripted all of his people to build an awesome tower that reached almost to heaven.<br>
|
||||
The gods were not amused. They struck him down, cursed him with immortality and imprisoned him in his own tower for eternity! A statue of the foolish emperor stands there to this day.<br>
|
||||
Occasionally, the old emperor himself is woken up by those who seek his power. Unfortunately, when Baium is disturbed, so are the angels who guard him.<br>
|
||||
Although the angels are certainly no friend of Baium, they regard Humans with equal disdain.<font color="LEVEL"> Ultimate success against Baium depends upon the defeat of the guardian angels.</font><br>
|
||||
This is all I can tell you. Good luck!
|
||||
</body></html>
|
||||
4
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Baium/31862.html
vendored
Normal file
4
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Baium/31862.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Angelic Vortex:<br>
|
||||
The Angelic Vortex emits a faint light, and in the midst of the light an image appears. In the deepest part of a spacious area, a gigantic stone statue is visible. The statue has a human-like appearance and is in a seated position, as though it was being held by some invisible force against its will.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Baium enter">Go where the Angelic Vortex leads.</Button>
|
||||
</body></html>
|
||||
793
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Baium/Baium.java
vendored
Normal file
793
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Baium/Baium.java
vendored
Normal file
@@ -0,0 +1,793 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual.Baium;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.enums.CategoryType;
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.enums.MountType;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.StatsSet;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.model.variables.NpcVariables;
|
||||
import com.l2jmobius.gameserver.model.zone.type.L2NoRestartZone;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||
import com.l2jmobius.gameserver.util.Util;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Baium AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
public final class Baium extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int BAIUM = 29020; // Baium
|
||||
private static final int BAIUM_STONE = 29025; // Baium
|
||||
private static final int ANG_VORTEX = 31862; // Angelic Vortex
|
||||
private static final int ARCHANGEL = 29021; // Archangel
|
||||
private static final int TELE_CUBE = 31842; // Teleportation Cubic
|
||||
// Skills
|
||||
private static final SkillHolder BAIUM_ATTACK = new SkillHolder(4127, 1); // Baium: General Attack
|
||||
private static final SkillHolder ENERGY_WAVE = new SkillHolder(4128, 1); // Wind Of Force
|
||||
private static final SkillHolder EARTH_QUAKE = new SkillHolder(4129, 1); // Earthquake
|
||||
private static final SkillHolder THUNDERBOLT = new SkillHolder(4130, 1); // Striking of Thunderbolt
|
||||
private static final SkillHolder GROUP_HOLD = new SkillHolder(4131, 1); // Stun
|
||||
private static final SkillHolder SPEAR_ATTACK = new SkillHolder(4132, 1); // Spear: Pound the Ground
|
||||
private static final SkillHolder ANGEL_HEAL = new SkillHolder(4133, 1); // Angel Heal
|
||||
private static final SkillHolder HEAL_OF_BAIUM = new SkillHolder(4135, 1); // Baium Heal
|
||||
private static final SkillHolder BAIUM_PRESENT = new SkillHolder(4136, 1); // Baium's Gift
|
||||
private static final SkillHolder ANTI_STRIDER = new SkillHolder(4258, 1); // Hinder Strider
|
||||
// Items
|
||||
private static final int FABRIC = 4295; // Blooded Fabric
|
||||
// Zone
|
||||
private static final L2NoRestartZone zone = ZoneManager.getInstance().getZoneById(70051, L2NoRestartZone.class); // Baium zone
|
||||
// Status
|
||||
private static final int ALIVE = 0;
|
||||
private static final int WAITING = 1;
|
||||
private static final int IN_FIGHT = 2;
|
||||
private static final int DEAD = 3;
|
||||
// Locations
|
||||
private static final Location BAIUM_GIFT_LOC = new Location(115910, 17337, 10105);
|
||||
private static final Location BAIUM_LOC = new Location(116033, 17447, 10107, -25348);
|
||||
private static final Location TELEPORT_CUBIC_LOC = new Location(115017, 15549, 10090);
|
||||
private static final Location TELEPORT_IN_LOC = new Location(114077, 15882, 10078);
|
||||
private static final Location[] TELEPORT_OUT_LOC =
|
||||
{
|
||||
new Location(108784, 16000, -4928),
|
||||
new Location(113824, 10448, -5164),
|
||||
new Location(115488, 22096, -5168),
|
||||
};
|
||||
private static final Location[] ARCHANGEL_LOC =
|
||||
{
|
||||
new Location(115792, 16608, 10136, 0),
|
||||
new Location(115168, 17200, 10136, 0),
|
||||
new Location(115780, 15564, 10136, 13620),
|
||||
new Location(114880, 16236, 10136, 5400),
|
||||
new Location(114239, 17168, 10136, -1992)
|
||||
};
|
||||
// Misc
|
||||
private L2GrandBossInstance _baium = null;
|
||||
private static long _lastAttack = 0;
|
||||
|
||||
private Baium()
|
||||
{
|
||||
super(Baium.class.getSimpleName(), "ai/individual");
|
||||
addFirstTalkId(ANG_VORTEX);
|
||||
addTalkId(ANG_VORTEX, TELE_CUBE, BAIUM_STONE);
|
||||
addStartNpc(ANG_VORTEX, TELE_CUBE, BAIUM_STONE);
|
||||
addAttackId(BAIUM, ARCHANGEL);
|
||||
addKillId(BAIUM);
|
||||
addSeeCreatureId(BAIUM);
|
||||
addSpellFinishedId(BAIUM);
|
||||
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(BAIUM);
|
||||
final int curr_hp = info.getInt("currentHP");
|
||||
final int curr_mp = info.getInt("currentMP");
|
||||
final int loc_x = info.getInt("loc_x");
|
||||
final int loc_y = info.getInt("loc_y");
|
||||
final int loc_z = info.getInt("loc_z");
|
||||
final int heading = info.getInt("heading");
|
||||
final long respawnTime = info.getLong("respawn_time");
|
||||
|
||||
switch (getStatus())
|
||||
{
|
||||
case WAITING:
|
||||
{
|
||||
setStatus(ALIVE);
|
||||
}
|
||||
case ALIVE:
|
||||
{
|
||||
addSpawn(BAIUM_STONE, BAIUM_LOC, false, 0);
|
||||
break;
|
||||
}
|
||||
case IN_FIGHT:
|
||||
{
|
||||
_baium = (L2GrandBossInstance) addSpawn(BAIUM, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
_baium.setCurrentHpMp(curr_hp, curr_mp);
|
||||
_lastAttack = System.currentTimeMillis();
|
||||
addBoss(_baium);
|
||||
|
||||
for (Location loc : ARCHANGEL_LOC)
|
||||
{
|
||||
final L2Npc archangel = addSpawn(ARCHANGEL, loc, false, 0, true);
|
||||
startQuestTimer("SELECT_TARGET", 5000, archangel, null);
|
||||
}
|
||||
startQuestTimer("CHECK_ATTACK", 60000, _baium, null);
|
||||
break;
|
||||
}
|
||||
case DEAD:
|
||||
{
|
||||
final long remain = respawnTime - System.currentTimeMillis();
|
||||
if (remain > 0)
|
||||
{
|
||||
startQuestTimer("CLEAR_STATUS", remain, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
notifyEvent("CLEAR_STATUS", null, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "31862-04.html":
|
||||
{
|
||||
return event;
|
||||
}
|
||||
case "enter":
|
||||
{
|
||||
String htmltext = null;
|
||||
if (getStatus() == DEAD)
|
||||
{
|
||||
htmltext = "31862-03.html";
|
||||
}
|
||||
else if (getStatus() == IN_FIGHT)
|
||||
{
|
||||
htmltext = "31862-02.html";
|
||||
}
|
||||
else if (!hasQuestItems(player, FABRIC))
|
||||
{
|
||||
htmltext = "31862-01.html";
|
||||
}
|
||||
else
|
||||
{
|
||||
takeItems(player, FABRIC, 1);
|
||||
player.teleToLocation(TELEPORT_IN_LOC);
|
||||
}
|
||||
return htmltext;
|
||||
}
|
||||
case "teleportOut":
|
||||
{
|
||||
final Location destination = TELEPORT_OUT_LOC[getRandom(TELEPORT_OUT_LOC.length)];
|
||||
player.teleToLocation(destination.getX() + getRandom(100), destination.getY() + getRandom(100), destination.getZ());
|
||||
break;
|
||||
}
|
||||
case "wakeUp":
|
||||
{
|
||||
if (getStatus() == ALIVE)
|
||||
{
|
||||
npc.deleteMe();
|
||||
setStatus(IN_FIGHT);
|
||||
_baium = (L2GrandBossInstance) addSpawn(BAIUM, BAIUM_LOC, false, 0);
|
||||
_baium.disableCoreAI(true);
|
||||
addBoss(_baium);
|
||||
_lastAttack = System.currentTimeMillis();
|
||||
startQuestTimer("WAKEUP_ACTION", 50, _baium, null);
|
||||
startQuestTimer("MANAGE_EARTHQUAKE", 2000, _baium, null);
|
||||
startQuestTimer("SOCIAL_ACTION", 10000, _baium, player);
|
||||
startQuestTimer("CHECK_ATTACK", 60000, _baium, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "WAKEUP_ACTION":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
zone.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "MANAGE_EARTHQUAKE":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
zone.broadcastPacket(new Earthquake(npc.getX(), npc.getY(), npc.getZ(), 40, 10));
|
||||
zone.broadcastPacket(new PlaySound("BS02_A"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SOCIAL_ACTION":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
zone.broadcastPacket(new SocialAction(npc.getObjectId(), 3));
|
||||
startQuestTimer("PLAYER_PORT", 6000, npc, player);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "PLAYER_PORT":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
if ((player != null) && player.isInsideRadius(npc, 16000, true, false))
|
||||
{
|
||||
player.teleToLocation(BAIUM_GIFT_LOC);
|
||||
startQuestTimer("PLAYER_KILL", 3000, npc, player);
|
||||
}
|
||||
else
|
||||
{
|
||||
final L2PcInstance randomPlayer = getRandomPlayer(npc);
|
||||
if (randomPlayer != null)
|
||||
{
|
||||
randomPlayer.teleToLocation(BAIUM_GIFT_LOC);
|
||||
startQuestTimer("PLAYER_KILL", 3000, npc, randomPlayer);
|
||||
}
|
||||
else
|
||||
{
|
||||
startQuestTimer("PLAYER_KILL", 3000, npc, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "PLAYER_KILL":
|
||||
{
|
||||
if ((player != null) && player.isInsideRadius(npc, 16000, true, false))
|
||||
{
|
||||
zone.broadcastPacket(new SocialAction(npc.getObjectId(), 1));
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.HOW_DARE_YOU_WAKE_ME_NOW_YOU_SHALL_DIE, player.getName());
|
||||
npc.setTarget(player);
|
||||
npc.doCast(BAIUM_PRESENT.getSkill());
|
||||
}
|
||||
|
||||
for (L2PcInstance insidePlayer : zone.getPlayersInside())
|
||||
{
|
||||
if (insidePlayer.isHero())
|
||||
{
|
||||
zone.broadcastPacket(new ExShowScreenMessage(NpcStringId.NOT_EVEN_THE_GODS_THEMSELVES_COULD_TOUCH_ME_BUT_YOU_S1_YOU_DARE_CHALLENGE_ME_IGNORANT_MORTAL, 2, 4000, insidePlayer.getName()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
startQuestTimer("SPAWN_ARCHANGEL", 8000, npc, player);
|
||||
break;
|
||||
}
|
||||
case "SPAWN_ARCHANGEL":
|
||||
{
|
||||
_baium.disableCoreAI(false);
|
||||
|
||||
for (Location loc : ARCHANGEL_LOC)
|
||||
{
|
||||
final L2Npc archangel = addSpawn(ARCHANGEL, loc, false, 0, true);
|
||||
startQuestTimer("SELECT_TARGET", 5000, archangel, null);
|
||||
}
|
||||
|
||||
if ((player != null) && !player.isDead())
|
||||
{
|
||||
addAttackDesire(npc, player);
|
||||
}
|
||||
else
|
||||
{
|
||||
final L2PcInstance randomPlayer = getRandomPlayer(npc);
|
||||
if (randomPlayer != null)
|
||||
{
|
||||
addAttackDesire(npc, randomPlayer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SELECT_TARGET":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
final L2Attackable mob = (L2Attackable) npc;
|
||||
final L2Character mostHated = mob.getMostHated();
|
||||
|
||||
if ((_baium == null) || _baium.isDead())
|
||||
{
|
||||
mob.deleteMe();
|
||||
break;
|
||||
}
|
||||
|
||||
if ((mostHated != null) && mostHated.isPlayer() && zone.isInsideZone(mostHated))
|
||||
{
|
||||
if (mob.getTarget() != mostHated)
|
||||
{
|
||||
mob.clearAggroList();
|
||||
}
|
||||
addAttackDesire(mob, mostHated);
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean found = false;
|
||||
for (L2Character creature : mob.getKnownList().getKnownCharactersInRadius(1000))
|
||||
{
|
||||
if ((creature != null) && creature.isPlayable() && zone.isInsideZone(creature) && !creature.isDead())
|
||||
{
|
||||
if (mob.getTarget() != creature)
|
||||
{
|
||||
mob.clearAggroList();
|
||||
}
|
||||
addAttackDesire(mob, creature);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
if (mob.isInsideRadius(_baium, 40, true, false))
|
||||
{
|
||||
if (mob.getTarget() != _baium)
|
||||
{
|
||||
mob.clearAggroList();
|
||||
}
|
||||
addAttackDesire(mob, _baium);
|
||||
}
|
||||
else
|
||||
{
|
||||
mob.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _baium);
|
||||
}
|
||||
}
|
||||
}
|
||||
startQuestTimer("SELECT_TARGET", 5000, npc, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "CHECK_ATTACK":
|
||||
{
|
||||
if ((npc != null) && ((_lastAttack + 1800000) < System.currentTimeMillis()))
|
||||
{
|
||||
cancelQuestTimers("SELECT_TARGET");
|
||||
notifyEvent("CLEAR_ZONE", null, null);
|
||||
addSpawn(BAIUM_STONE, BAIUM_LOC, false, 0);
|
||||
setStatus(ALIVE);
|
||||
}
|
||||
else if (npc != null)
|
||||
{
|
||||
if (((_lastAttack + 300000) < System.currentTimeMillis()) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.75)))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(HEAL_OF_BAIUM.getSkill());
|
||||
}
|
||||
startQuestTimer("CHECK_ATTACK", 60000, npc, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "CLEAR_STATUS":
|
||||
{
|
||||
setStatus(ALIVE);
|
||||
addSpawn(BAIUM_STONE, BAIUM_LOC, false, 0);
|
||||
break;
|
||||
}
|
||||
case "CLEAR_ZONE":
|
||||
{
|
||||
for (L2Character charInside : zone.getCharactersInside())
|
||||
{
|
||||
if (charInside != null)
|
||||
{
|
||||
if (charInside.isNpc())
|
||||
{
|
||||
charInside.deleteMe();
|
||||
}
|
||||
else if (charInside.isPlayer())
|
||||
{
|
||||
notifyEvent("teleportOut", null, (L2PcInstance) charInside);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "RESPAWN_BAIUM":
|
||||
{
|
||||
if (getStatus() == DEAD)
|
||||
{
|
||||
setRespawn(0);
|
||||
cancelQuestTimer("CLEAR_STATUS", null, null);
|
||||
notifyEvent("CLEAR_STATUS", null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendMessage(getClass().getSimpleName() + ": You cant respawn Baium while Baium is alive!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "ABORT_FIGHT":
|
||||
{
|
||||
if (getStatus() == IN_FIGHT)
|
||||
{
|
||||
_baium = null;
|
||||
notifyEvent("CLEAR_ZONE", null, null);
|
||||
notifyEvent("CLEAR_STATUS", null, null);
|
||||
player.sendMessage(getClass().getSimpleName() + ": Aborting fight!");
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendMessage(getClass().getSimpleName() + ": You cant abort attack right now!");
|
||||
}
|
||||
cancelQuestTimers("CHECK_ATTACK");
|
||||
cancelQuestTimers("SELECT_TARGET");
|
||||
break;
|
||||
}
|
||||
case "DESPAWN_MINIONS":
|
||||
{
|
||||
if (getStatus() == IN_FIGHT)
|
||||
{
|
||||
for (L2Character charInside : zone.getCharactersInside())
|
||||
{
|
||||
if ((charInside != null) && charInside.isNpc() && (charInside.getId() == ARCHANGEL))
|
||||
{
|
||||
charInside.deleteMe();
|
||||
}
|
||||
}
|
||||
if (player != null)
|
||||
{
|
||||
player.sendMessage(getClass().getSimpleName() + ": All archangels has been deleted!");
|
||||
}
|
||||
}
|
||||
else if (player != null)
|
||||
{
|
||||
player.sendMessage(getClass().getSimpleName() + ": You cant despawn archangels right now!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "MANAGE_SKILLS":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
manageSkills(npc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
|
||||
{
|
||||
_lastAttack = System.currentTimeMillis();
|
||||
|
||||
if (npc.getId() == BAIUM)
|
||||
{
|
||||
if ((attacker.getMountType() == MountType.STRIDER) && !attacker.isAffectedBySkill(ANTI_STRIDER.getSkillId()) && !npc.isSkillDisabled(ANTI_STRIDER.getSkill()))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(ANTI_STRIDER.getSkill());
|
||||
}
|
||||
|
||||
if (skill == null)
|
||||
{
|
||||
refreshAiParams(attacker, npc, damage * 1000);
|
||||
}
|
||||
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
|
||||
{
|
||||
refreshAiParams(attacker, npc, (damage / 3) * 100);
|
||||
}
|
||||
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
|
||||
{
|
||||
refreshAiParams(attacker, npc, damage * 20);
|
||||
}
|
||||
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
|
||||
{
|
||||
refreshAiParams(attacker, npc, damage * 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
refreshAiParams(attacker, npc, (damage / 3) * 20);
|
||||
}
|
||||
manageSkills(npc);
|
||||
}
|
||||
else
|
||||
{
|
||||
final L2Attackable mob = (L2Attackable) npc;
|
||||
final L2Character mostHated = mob.getMostHated();
|
||||
|
||||
if ((getRandom(100) < 10) && mob.checkDoCastConditions(SPEAR_ATTACK.getSkill()))
|
||||
{
|
||||
if ((mostHated != null) && (npc.calculateDistance(mostHated, true, false) < 1000) && zone.isCharacterInZone(mostHated))
|
||||
{
|
||||
mob.setTarget(mostHated);
|
||||
mob.doCast(SPEAR_ATTACK.getSkill());
|
||||
}
|
||||
else if (zone.isCharacterInZone(attacker))
|
||||
{
|
||||
mob.setTarget(attacker);
|
||||
mob.doCast(SPEAR_ATTACK.getSkill());
|
||||
}
|
||||
}
|
||||
|
||||
if ((getRandom(100) < 5) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.5)) && mob.checkDoCastConditions(ANGEL_HEAL.getSkill()))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(ANGEL_HEAL.getSkill());
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon, skill);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (zone.isCharacterInZone(killer))
|
||||
{
|
||||
setStatus(DEAD);
|
||||
addSpawn(TELE_CUBE, TELEPORT_CUBIC_LOC, false, 900000);
|
||||
zone.broadcastPacket(new PlaySound("BS01_D"));
|
||||
final long respawnTime = (Config.BAIUM_SPAWN_INTERVAL + getRandom(-Config.BAIUM_SPAWN_RANDOM, Config.BAIUM_SPAWN_RANDOM)) * 3600000;
|
||||
setRespawn(respawnTime);
|
||||
startQuestTimer("CLEAR_STATUS", respawnTime, null, null);
|
||||
startQuestTimer("CLEAR_ZONE", 900000, null, null);
|
||||
cancelQuestTimer("CHECK_ATTACK", npc, null);
|
||||
cancelQuestTimers("SELECT_TARGET");
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSeeCreature(L2Npc npc, L2Character creature, boolean isSummon)
|
||||
{
|
||||
if (!zone.isInsideZone(creature) || (creature.isNpc() && (creature.getId() == BAIUM_STONE)))
|
||||
{
|
||||
return super.onSeeCreature(npc, creature, isSummon);
|
||||
}
|
||||
|
||||
if (creature.isInCategory(CategoryType.CLERIC_GROUP))
|
||||
{
|
||||
if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
|
||||
{
|
||||
refreshAiParams(creature, npc, 10000);
|
||||
}
|
||||
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
|
||||
{
|
||||
refreshAiParams(creature, npc, 10000, 6000);
|
||||
}
|
||||
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
|
||||
{
|
||||
refreshAiParams(creature, npc, 10000, 3000);
|
||||
}
|
||||
else
|
||||
{
|
||||
refreshAiParams(creature, npc, 10000, 2000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
refreshAiParams(creature, npc, 10000, 1000);
|
||||
}
|
||||
manageSkills(npc);
|
||||
return super.onSeeCreature(npc, creature, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
|
||||
{
|
||||
startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
|
||||
|
||||
if (!zone.isCharacterInZone(npc) && (_baium != null))
|
||||
{
|
||||
_baium.teleToLocation(BAIUM_LOC);
|
||||
}
|
||||
return super.onSpellFinished(npc, player, skill);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unload(boolean removeFromList)
|
||||
{
|
||||
if (_baium != null)
|
||||
{
|
||||
_baium.deleteMe();
|
||||
}
|
||||
return super.unload(removeFromList);
|
||||
}
|
||||
|
||||
private final void refreshAiParams(L2Character attacker, L2Npc npc, int damage)
|
||||
{
|
||||
refreshAiParams(attacker, npc, damage, damage);
|
||||
}
|
||||
|
||||
private final void refreshAiParams(L2Character attacker, L2Npc npc, int damage, int aggro)
|
||||
{
|
||||
final int newAggroVal = damage + getRandom(3000);
|
||||
final int aggroVal = aggro + 1000;
|
||||
final NpcVariables vars = npc.getVariables();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (attacker == vars.getObject("c_quest" + i, L2Character.class))
|
||||
{
|
||||
if (vars.getInt("i_quest" + i) < aggroVal)
|
||||
{
|
||||
vars.set("i_quest" + i, newAggroVal);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
final int index = Util.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
|
||||
vars.set("i_quest" + index, newAggroVal);
|
||||
vars.set("c_quest" + index, attacker);
|
||||
}
|
||||
|
||||
private int getStatus()
|
||||
{
|
||||
return GrandBossManager.getInstance().getBossStatus(BAIUM);
|
||||
}
|
||||
|
||||
private void addBoss(L2GrandBossInstance grandboss)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(grandboss);
|
||||
}
|
||||
|
||||
private void setStatus(int status)
|
||||
{
|
||||
GrandBossManager.getInstance().setBossStatus(BAIUM, status);
|
||||
}
|
||||
|
||||
private void setRespawn(long respawnTime)
|
||||
{
|
||||
GrandBossManager.getInstance().getStatsSet(BAIUM).set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
}
|
||||
|
||||
private void manageSkills(L2Npc npc)
|
||||
{
|
||||
if (npc.isCastingNow() || npc.isCoreAIDisabled() || !npc.isInCombat())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final NpcVariables vars = npc.getVariables();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
final L2Character attacker = vars.getObject("c_quest" + i, L2Character.class);
|
||||
if ((attacker == null) || (npc.calculateDistance(attacker, true, false) > 9000) || attacker.isDead())
|
||||
{
|
||||
vars.set("i_quest" + i, 0);
|
||||
}
|
||||
}
|
||||
final int index = Util.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
|
||||
final L2Character player = vars.getObject("c_quest" + index, L2Character.class);
|
||||
final int i2 = vars.getInt("i_quest" + index);
|
||||
if ((i2 > 0) && (getRandom(100) < 70))
|
||||
{
|
||||
vars.set("i_quest" + index, 500);
|
||||
}
|
||||
|
||||
SkillHolder skillToCast = null;
|
||||
if ((player != null) && !player.isDead())
|
||||
{
|
||||
if (npc.getCurrentHp() > (npc.getMaxHp() * 0.75))
|
||||
{
|
||||
if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = ENERGY_WAVE;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = EARTH_QUAKE;
|
||||
}
|
||||
else
|
||||
{
|
||||
skillToCast = BAIUM_ATTACK;
|
||||
}
|
||||
}
|
||||
else if (npc.getCurrentHp() > (npc.getMaxHp() * 0.5))
|
||||
{
|
||||
if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = GROUP_HOLD;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = ENERGY_WAVE;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = EARTH_QUAKE;
|
||||
}
|
||||
else
|
||||
{
|
||||
skillToCast = BAIUM_ATTACK;
|
||||
}
|
||||
}
|
||||
else if (npc.getCurrentHp() > (npc.getMaxHp() * 0.25))
|
||||
{
|
||||
if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = THUNDERBOLT;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = GROUP_HOLD;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = ENERGY_WAVE;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = EARTH_QUAKE;
|
||||
}
|
||||
else
|
||||
{
|
||||
skillToCast = BAIUM_ATTACK;
|
||||
}
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = THUNDERBOLT;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = GROUP_HOLD;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = ENERGY_WAVE;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = EARTH_QUAKE;
|
||||
}
|
||||
else
|
||||
{
|
||||
skillToCast = BAIUM_ATTACK;
|
||||
}
|
||||
}
|
||||
|
||||
if ((skillToCast != null) && npc.checkDoCastConditions(skillToCast.getSkill()))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(skillToCast.getSkill());
|
||||
}
|
||||
}
|
||||
|
||||
private L2PcInstance getRandomPlayer(L2Npc npc)
|
||||
{
|
||||
for (L2Character creature : npc.getKnownList().getKnownCharactersInRadius(2000))
|
||||
{
|
||||
if ((creature != null) && creature.isPlayer() && zone.isInsideZone(creature) && !creature.isDead())
|
||||
{
|
||||
return (L2PcInstance) creature;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Baium();
|
||||
}
|
||||
}
|
||||
99
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Ballista.java
vendored
Normal file
99
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Ballista.java
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.network.SystemMessageId;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Ballista AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
final class Ballista extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int[] BALLISTA =
|
||||
{
|
||||
35685, // Shanty Fortress
|
||||
35723, // Southern Fortress
|
||||
35754, // Hive Fortress
|
||||
35792, // Valley Fortress
|
||||
35823, // Ivory Fortress
|
||||
35854, // Narsell Fortress
|
||||
35892, // Bayou Fortress
|
||||
35923, // White Sands Fortress
|
||||
35961, // Borderland Fortress
|
||||
35999, // Swamp Fortress
|
||||
36030, // Archaic Fortress
|
||||
36068, // Floran Fortress
|
||||
36106, // Cloud Mountain)
|
||||
36137, // Tanor Fortress
|
||||
36168, // Dragonspine Fortress
|
||||
36206, // Antharas's Fortress
|
||||
36244, // Western Fortress
|
||||
36282, // Hunter's Fortress
|
||||
36313, // Aaru Fortress
|
||||
36351, // Demon Fortress
|
||||
36389, // Monastic Fortress
|
||||
};
|
||||
// Skill
|
||||
private static final SkillHolder BOMB = new SkillHolder(2342, 1); // Ballista Bomb
|
||||
// Misc
|
||||
private static final int MIN_CLAN_LV = 5;
|
||||
|
||||
private Ballista()
|
||||
{
|
||||
super(Ballista.class.getSimpleName(), "ai/individual");
|
||||
addSkillSeeId(BALLISTA);
|
||||
addSpawnId(BALLISTA);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
|
||||
{
|
||||
if ((skill != null) && (caster.getTarget() == npc) && (getRandom(100) < 40) && (skill == BOMB.getSkill()))
|
||||
{
|
||||
if (npc.getFort().getSiege().isInProgress() && (caster.getClan() != null) && (caster.getClan().getLevel() >= MIN_CLAN_LV))
|
||||
{
|
||||
caster.getClan().addReputationScore(Config.BALLISTA_POINTS, true);
|
||||
caster.sendPacket(SystemMessageId.THE_BALLISTA_HAS_BEEN_SUCCESSFULLY_DESTROYED_THE_CLAN_REPUTATION_WILL_BE_INCREASED);
|
||||
}
|
||||
npc.doDie(caster);
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
npc.disableCoreAI(true);
|
||||
npc.setIsMortal(false);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Ballista();
|
||||
}
|
||||
}
|
||||
833
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Beleth.java
vendored
Normal file
833
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Beleth.java
vendored
Normal file
@@ -0,0 +1,833 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.cache.HtmCache;
|
||||
import com.l2jmobius.gameserver.data.xml.impl.DoorData;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.instancemanager.MapRegionManager;
|
||||
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.StatsSet;
|
||||
import com.l2jmobius.gameserver.model.TeleportWhereType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.effects.L2EffectType;
|
||||
import com.l2jmobius.gameserver.model.holders.ItemHolder;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.DoorStatusUpdate;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.StaticObject;
|
||||
import com.l2jmobius.gameserver.util.Util;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Beleth's AI.
|
||||
* @author Treat, Sahar
|
||||
*/
|
||||
final class Beleth extends AbstractNpcAI
|
||||
{
|
||||
// Status
|
||||
private static final int ALIVE = 0;
|
||||
private static final int INIT = 1;
|
||||
private static final int FIGHT = 2;
|
||||
private static final int DEAD = 3;
|
||||
// NPCs
|
||||
private static final int REAL_BELETH = 29118;
|
||||
private static final int FAKE_BELETH = 29119;
|
||||
private static final int STONE_COFFIN = 32470;
|
||||
private static final int ELF = 29128;
|
||||
private static final int WHIRPOOL = 29125;
|
||||
// Zones
|
||||
private static final L2ZoneType ZONE = ZoneManager.getInstance().getZoneById(12018);
|
||||
private static final Location BELETH_SPAWN = new Location(16323, 213059, -9357, 49152);
|
||||
// Skills
|
||||
private static final SkillHolder BLEED = new SkillHolder(5495, 1);
|
||||
private static final SkillHolder FIREBALL = new SkillHolder(5496, 1);
|
||||
private static final SkillHolder HORN_OF_RISING = new SkillHolder(5497, 1);
|
||||
private static final SkillHolder LIGHTENING = new SkillHolder(5499, 1);
|
||||
// Doors
|
||||
private static final int DOOR1 = 20240001;
|
||||
private static final int DOOR2 = 20240002;
|
||||
private static final int DOOR3 = 20240003;
|
||||
// Items
|
||||
private static final ItemHolder RING = new ItemHolder(10314, 1);
|
||||
// Variables
|
||||
private L2Npc _camera1;
|
||||
private L2Npc _camera2;
|
||||
private L2Npc _camera3;
|
||||
private L2Npc _camera4;
|
||||
private L2Npc _whirpool;
|
||||
private L2Npc _beleth;
|
||||
private L2Npc _priest;
|
||||
private L2Npc _stone;
|
||||
private L2PcInstance _killer;
|
||||
private int _allowedObjId;
|
||||
private int _killedCount;
|
||||
private long _lastAttack;
|
||||
private final List<L2Npc> _minions = new CopyOnWriteArrayList<>();
|
||||
|
||||
private Beleth()
|
||||
{
|
||||
super(Beleth.class.getSimpleName(), "ai/individual");
|
||||
addEnterZoneId(ZONE.getId());
|
||||
registerMobs(REAL_BELETH, FAKE_BELETH);
|
||||
addStartNpc(STONE_COFFIN);
|
||||
addTalkId(STONE_COFFIN);
|
||||
addFirstTalkId(ELF);
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(REAL_BELETH);
|
||||
final int status = GrandBossManager.getInstance().getBossStatus(REAL_BELETH);
|
||||
if (status == DEAD)
|
||||
{
|
||||
final long time = info.getLong("respawn_time") - System.currentTimeMillis();
|
||||
if (time > 0)
|
||||
{
|
||||
startQuestTimer("BELETH_UNLOCK", time, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
GrandBossManager.getInstance().setBossStatus(REAL_BELETH, ALIVE);
|
||||
}
|
||||
}
|
||||
else if (status != ALIVE)
|
||||
{
|
||||
GrandBossManager.getInstance().setBossStatus(REAL_BELETH, ALIVE);
|
||||
}
|
||||
DoorData.getInstance().getDoor(DOOR1).openMe();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "BELETH_UNLOCK":
|
||||
{
|
||||
GrandBossManager.getInstance().setBossStatus(REAL_BELETH, ALIVE);
|
||||
DoorData.getInstance().getDoor(DOOR1).openMe();
|
||||
break;
|
||||
}
|
||||
case "CAST":
|
||||
{
|
||||
if (!npc.isDead() && !npc.isCastingNow())
|
||||
{
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
|
||||
npc.doCast(FIREBALL.getSkill());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SPAWN1":
|
||||
{
|
||||
ZONE.getCharactersInside().forEach(c ->
|
||||
{
|
||||
c.disableAllSkills();
|
||||
c.setIsInvul(true);
|
||||
c.setIsImmobilized(true);
|
||||
});
|
||||
|
||||
_camera1 = addSpawn(29120, new Location(16323, 213142, -9357));
|
||||
_camera2 = addSpawn(29121, new Location(16323, 210741, -9357));
|
||||
_camera3 = addSpawn(29122, new Location(16323, 213170, -9357));
|
||||
_camera4 = addSpawn(29123, new Location(16323, 214917, -9356));
|
||||
|
||||
ZONE.broadcastPacket(new PlaySound(1, "BS07_A", 1, _camera1.getObjectId(), _camera1.getX(), _camera1.getY(), _camera1.getZ()));
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera1, 400, 75, -25, 0, 2500, 0, 0, 1, 0, 0));
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera1, 400, 75, -25, 0, 2500, 0, 0, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN2", 300, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN2":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera1, 1800, -45, -45, 5000, 5000, 0, 0, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN3", 4900, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN3":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera1, 2500, -120, -45, 5000, 5000, 0, 0, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN4", 4900, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN4":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera2, 2200, 130, 0, 0, 1500, -20, 15, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN5", 1400, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN5":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera2, 2300, 100, 0, 2000, 4500, 0, 10, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN6", 2500, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN6":
|
||||
{
|
||||
final L2DoorInstance door = DoorData.getInstance().getDoor(DOOR1);
|
||||
door.closeMe();
|
||||
|
||||
ZONE.broadcastPacket(new StaticObject(door, false));
|
||||
ZONE.broadcastPacket(new DoorStatusUpdate(door));
|
||||
|
||||
startQuestTimer("SPAWN7", 1700, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN7":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera4, 1500, 210, 0, 0, 1500, 0, 0, 1, 0, 0));
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera4, 900, 255, 0, 5000, 6500, 0, 10, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN8", 6000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN8":
|
||||
{
|
||||
_whirpool = addSpawn(WHIRPOOL, new Location(16323, 214917, -9356));
|
||||
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera4, 900, 255, 0, 0, 1500, 0, 10, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN9", 1000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN9":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera4, 1000, 255, 0, 7000, 17000, 0, 25, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN10", 3000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN10":
|
||||
{
|
||||
_beleth = addSpawn(REAL_BELETH, new Location(16321, 214211, -9352, 49369));
|
||||
_beleth.disableAllSkills();
|
||||
_beleth.setIsInvul(true);
|
||||
_beleth.setIsImmobilized(true);
|
||||
|
||||
startQuestTimer("SPAWN11", 200, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN11":
|
||||
{
|
||||
ZONE.broadcastPacket(new SocialAction(_beleth.getObjectId(), 1));
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
final int x = (int) ((150 * Math.cos(i * 1.046666667)) + 16323);
|
||||
final int y = (int) ((150 * Math.sin(i * 1.046666667)) + 213059);
|
||||
final L2Npc minion = addSpawn(FAKE_BELETH, new Location(x, y, -9357, 49152));
|
||||
minion.setShowSummonAnimation(true);
|
||||
minion.decayMe();
|
||||
|
||||
_minions.add(minion);
|
||||
}
|
||||
|
||||
startQuestTimer("SPAWN12", 6800, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN12":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_beleth, 0, 270, -5, 0, 4000, 0, 0, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN13", 3500, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN13":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_beleth, 800, 270, 10, 3000, 6000, 0, 0, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN14", 5000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN14":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera3, 100, 270, 15, 0, 5000, 0, 0, 1, 0, 0));
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera3, 100, 270, 15, 0, 5000, 0, 0, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN15", 100, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN15":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera3, 100, 270, 15, 3000, 6000, 0, 5, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN16", 1400, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN16":
|
||||
{
|
||||
_beleth.teleToLocation(BELETH_SPAWN);
|
||||
|
||||
startQuestTimer("SPAWN17", 200, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN17":
|
||||
{
|
||||
ZONE.broadcastPacket(new MagicSkillUse(_beleth, _beleth, 5532, 1, 2000, 0));
|
||||
|
||||
startQuestTimer("SPAWN18", 2000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN18":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera3, 700, 270, 20, 1500, 8000, 0, 0, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN19", 6900, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN19":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera3, 40, 260, 0, 0, 4000, 0, 0, 1, 0, 0));
|
||||
|
||||
for (L2Npc fakeBeleth : _minions)
|
||||
{
|
||||
fakeBeleth.spawnMe();
|
||||
fakeBeleth.disableAllSkills();
|
||||
fakeBeleth.setIsInvul(true);
|
||||
fakeBeleth.setIsImmobilized(true);
|
||||
}
|
||||
|
||||
startQuestTimer("SPAWN20", 3000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN20":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera3, 40, 280, 0, 0, 4000, 5, 0, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN21", 3000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN21":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera3, 5, 250, 5, 0, 13000, 20, 15, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN22", 1000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN22":
|
||||
{
|
||||
ZONE.broadcastPacket(new SocialAction(_beleth.getObjectId(), 3));
|
||||
|
||||
startQuestTimer("SPAWN23", 4000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN23":
|
||||
{
|
||||
ZONE.broadcastPacket(new MagicSkillUse(_beleth, _beleth, 5533, 1, 2000, 0));
|
||||
|
||||
startQuestTimer("SPAWN24", 6800, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN24":
|
||||
{
|
||||
_beleth.deleteMe();
|
||||
_beleth = null;
|
||||
|
||||
for (L2Npc fakeBeleth : _minions)
|
||||
{
|
||||
fakeBeleth.deleteMe();
|
||||
}
|
||||
_minions.clear();
|
||||
|
||||
_camera1.deleteMe();
|
||||
_camera2.deleteMe();
|
||||
_camera3.deleteMe();
|
||||
_camera4.deleteMe();
|
||||
|
||||
for (L2Character c : ZONE.getCharactersInside())
|
||||
{
|
||||
c.enableAllSkills();
|
||||
c.setIsInvul(false);
|
||||
c.setIsImmobilized(false);
|
||||
}
|
||||
|
||||
_lastAttack = System.currentTimeMillis();
|
||||
|
||||
startQuestTimer("CHECK_ATTACK", 60000, null, null);
|
||||
|
||||
startQuestTimer("SPAWN25", 60000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN25":
|
||||
{
|
||||
_minions.clear();
|
||||
|
||||
int a = 0;
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
a++;
|
||||
|
||||
final int x = (int) ((650 * Math.cos(i * 0.39)) + 16323);
|
||||
final int y = (int) ((650 * Math.sin(i * 0.39)) + 213170);
|
||||
|
||||
npc = addSpawn(FAKE_BELETH, new Location(x, y, -9357, 49152));
|
||||
_minions.add(npc);
|
||||
|
||||
if (a >= 2)
|
||||
{
|
||||
npc.setIsOverloaded(true);
|
||||
a = 0;
|
||||
}
|
||||
}
|
||||
|
||||
final int[] xm = new int[16];
|
||||
final int[] ym = new int[16];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
xm[i] = (int) ((1700 * Math.cos((i * 1.57) + 0.78)) + 16323);
|
||||
ym[i] = (int) ((1700 * Math.sin((i * 1.57) + 0.78)) + 213170);
|
||||
|
||||
npc = addSpawn(FAKE_BELETH, new Location(xm[i], ym[i], -9357, 49152));
|
||||
npc.setIsImmobilized(true);
|
||||
|
||||
_minions.add(npc);
|
||||
}
|
||||
|
||||
xm[4] = (xm[0] + xm[1]) / 2;
|
||||
ym[4] = (ym[0] + ym[1]) / 2;
|
||||
npc = addSpawn(FAKE_BELETH, new Location(xm[4], ym[4], -9357, 49152));
|
||||
npc.setIsImmobilized(true);
|
||||
_minions.add(npc);
|
||||
xm[5] = (xm[1] + xm[2]) / 2;
|
||||
ym[5] = (ym[1] + ym[2]) / 2;
|
||||
npc = addSpawn(FAKE_BELETH, new Location(xm[5], ym[5], -9357, 49152));
|
||||
npc.setIsImmobilized(true);
|
||||
_minions.add(npc);
|
||||
xm[6] = (xm[2] + xm[3]) / 2;
|
||||
ym[6] = (ym[2] + ym[3]) / 2;
|
||||
npc = addSpawn(FAKE_BELETH, new Location(xm[6], ym[6], -9357, 49152));
|
||||
npc.setIsImmobilized(true);
|
||||
_minions.add(npc);
|
||||
xm[7] = (xm[3] + xm[0]) / 2;
|
||||
ym[7] = (ym[3] + ym[0]) / 2;
|
||||
npc = addSpawn(FAKE_BELETH, new Location(xm[7], ym[7], -9357, 49152));
|
||||
npc.setIsImmobilized(true);
|
||||
_minions.add(npc);
|
||||
|
||||
xm[8] = (xm[0] + xm[4]) / 2;
|
||||
ym[8] = (ym[0] + ym[4]) / 2;
|
||||
_minions.add(addSpawn(FAKE_BELETH, new Location(xm[8], ym[8], -9357, 49152)));
|
||||
xm[9] = (xm[4] + xm[1]) / 2;
|
||||
ym[9] = (ym[4] + ym[1]) / 2;
|
||||
_minions.add(addSpawn(FAKE_BELETH, new Location(xm[9], ym[9], -9357, 49152)));
|
||||
xm[10] = (xm[1] + xm[5]) / 2;
|
||||
ym[10] = (ym[1] + ym[5]) / 2;
|
||||
_minions.add(addSpawn(FAKE_BELETH, new Location(xm[10], ym[10], -9357, 49152)));
|
||||
xm[11] = (xm[5] + xm[2]) / 2;
|
||||
ym[11] = (ym[5] + ym[2]) / 2;
|
||||
_minions.add(addSpawn(FAKE_BELETH, new Location(xm[11], ym[11], -9357, 49152)));
|
||||
xm[12] = (xm[2] + xm[6]) / 2;
|
||||
ym[12] = (ym[2] + ym[6]) / 2;
|
||||
_minions.add(addSpawn(FAKE_BELETH, new Location(xm[12], ym[12], -9357, 49152)));
|
||||
xm[13] = (xm[6] + xm[3]) / 2;
|
||||
ym[13] = (ym[6] + ym[3]) / 2;
|
||||
_minions.add(addSpawn(FAKE_BELETH, new Location(xm[13], ym[13], -9357, 49152)));
|
||||
xm[14] = (xm[3] + xm[7]) / 2;
|
||||
ym[14] = (ym[3] + ym[7]) / 2;
|
||||
_minions.add(addSpawn(FAKE_BELETH, new Location(xm[14], ym[14], -9357, 49152)));
|
||||
xm[15] = (xm[7] + xm[0]) / 2;
|
||||
ym[15] = (ym[7] + ym[0]) / 2;
|
||||
_minions.add(addSpawn(FAKE_BELETH, new Location(xm[15], ym[15], -9357, 49152)));
|
||||
|
||||
_allowedObjId = _minions.get(getRandom(_minions.size())).getObjectId();
|
||||
break;
|
||||
}
|
||||
case "SPAWN_REAL":
|
||||
{
|
||||
_beleth = addSpawn(REAL_BELETH, new Location(16323, 213170, -9357, 49152));
|
||||
break;
|
||||
}
|
||||
case "SPAWN26":
|
||||
{
|
||||
_beleth.doDie(null);
|
||||
|
||||
_camera1 = addSpawn(29122, new Location(16323, 213170, -9357));
|
||||
_camera1.broadcastPacket(new PlaySound(1, "BS07_D", 1, _camera1.getObjectId(), _camera1.getX(), _camera1.getY(), _camera1.getZ()));
|
||||
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera1, 400, 290, 25, 0, 10000, 0, 0, 1, 0, 0));
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera1, 400, 290, 25, 0, 10000, 0, 0, 1, 0, 0));
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera1, 400, 110, 25, 4000, 10000, 0, 0, 1, 0, 0));
|
||||
ZONE.broadcastPacket(new SocialAction(_beleth.getObjectId(), 5));
|
||||
|
||||
startQuestTimer("SPAWN27", 4000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN27":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera1, 400, 295, 25, 4000, 5000, 0, 0, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN28", 4500, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN28":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera1, 400, 295, 10, 4000, 11000, 0, 25, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN29", 9000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN29":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera1, 250, 90, 25, 0, 1000, 0, 0, 1, 0, 0));
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera1, 250, 90, 25, 0, 10000, 0, 0, 1, 0, 0));
|
||||
|
||||
startQuestTimer("SPAWN30", 2000, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN30":
|
||||
{
|
||||
_priest.spawnMe();
|
||||
_beleth.deleteMe();
|
||||
|
||||
_camera2 = addSpawn(29121, new Location(14056, 213170, -9357));
|
||||
|
||||
startQuestTimer("SPAWN31", 3500, null, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN31":
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera2, 800, 180, 0, 0, 4000, 0, 10, 1, 0, 0));
|
||||
ZONE.broadcastPacket(new SpecialCamera(_camera2, 800, 180, 0, 0, 4000, 0, 10, 1, 0, 0));
|
||||
|
||||
final L2DoorInstance door2 = DoorData.getInstance().getDoor(DOOR2);
|
||||
door2.openMe();
|
||||
|
||||
ZONE.broadcastPacket(new StaticObject(door2, false));
|
||||
ZONE.broadcastPacket(new DoorStatusUpdate(door2));
|
||||
|
||||
DoorData.getInstance().getDoor(DOOR3).openMe();
|
||||
|
||||
_camera1.deleteMe();
|
||||
_camera2.deleteMe();
|
||||
_whirpool.deleteMe();
|
||||
|
||||
for (L2Character c : ZONE.getCharactersInside())
|
||||
{
|
||||
c.enableAllSkills();
|
||||
c.setIsInvul(false);
|
||||
c.setIsImmobilized(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "CHECK_ATTACK":
|
||||
{
|
||||
if ((_lastAttack + 900000) < System.currentTimeMillis())
|
||||
{
|
||||
GrandBossManager.getInstance().setBossStatus(REAL_BELETH, ALIVE);
|
||||
for (L2Character charInside : ZONE.getCharactersInside())
|
||||
{
|
||||
if (charInside != null)
|
||||
{
|
||||
if (charInside.isNpc())
|
||||
{
|
||||
charInside.deleteMe();
|
||||
}
|
||||
else if (charInside.isPlayer())
|
||||
{
|
||||
charInside.teleToLocation(MapRegionManager.getInstance().getTeleToLocation(charInside, TeleportWhereType.TOWN));
|
||||
}
|
||||
}
|
||||
}
|
||||
cancelQuestTimer("CHECK_ATTACK", null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
startQuestTimer("CHECK_ATTACK", 60000, null, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onEnterZone(L2Character character, L2ZoneType zone)
|
||||
{
|
||||
if (character.isPlayer() && (GrandBossManager.getInstance().getBossStatus(REAL_BELETH) == INIT))
|
||||
{
|
||||
if (_priest != null)
|
||||
{
|
||||
_priest.deleteMe();
|
||||
}
|
||||
if (_stone != null)
|
||||
{
|
||||
_stone.deleteMe();
|
||||
}
|
||||
|
||||
GrandBossManager.getInstance().setBossStatus(REAL_BELETH, FIGHT);
|
||||
startQuestTimer("SPAWN1", 300000, null, null);
|
||||
}
|
||||
|
||||
return super.onEnterZone(character, zone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2Npc npc, L2PcInstance player, Skill skill, L2Object[] targets, boolean isSummon)
|
||||
{
|
||||
if (!npc.isDead() && (npc.getId() == REAL_BELETH) && !npc.isCastingNow() && skill.hasEffectType(L2EffectType.HEAL) && (getRandom(100) < 80))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(HORN_OF_RISING.getSkill());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
if (!npc.isDead() && !npc.isCastingNow())
|
||||
{
|
||||
if ((getRandom(100) < 40) && !npc.getKnownList().getKnownPlayersInRadius(200).isEmpty())
|
||||
{
|
||||
npc.doCast(BLEED.getSkill());
|
||||
return null;
|
||||
}
|
||||
npc.setTarget(player);
|
||||
npc.doCast(FIREBALL.getSkill());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
|
||||
{
|
||||
if (!npc.isDead() && !npc.isCastingNow())
|
||||
{
|
||||
if (!player.isDead())
|
||||
{
|
||||
final double distance2 = npc.calculateDistance(player, false, false);
|
||||
if ((distance2 > 890) && !npc.isMovementDisabled())
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player);
|
||||
startQuestTimer("CAST", (int) (((distance2 - 890) / (npc.isRunning() ? npc.getRunSpeed() : npc.getWalkSpeed())) * 1000), npc, null);
|
||||
}
|
||||
else if (distance2 < 890)
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(FIREBALL.getSkill());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if ((getRandom(100) < 40) && !npc.getKnownList().getKnownPlayersInRadius(200).isEmpty())
|
||||
{
|
||||
npc.doCast(LIGHTENING.getSkill());
|
||||
return null;
|
||||
}
|
||||
for (L2PcInstance plr : npc.getKnownList().getKnownPlayersInRadius(950))
|
||||
{
|
||||
npc.setTarget(plr);
|
||||
npc.doCast(FIREBALL.getSkill());
|
||||
return null;
|
||||
}
|
||||
((L2Attackable) npc).clearAggroList();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
npc.setRunning();
|
||||
if (!npc.getKnownList().getKnownPlayersInRadius(300).isEmpty() && (getRandom(100) < 60))
|
||||
{
|
||||
npc.doCast(BLEED.getSkill());
|
||||
}
|
||||
if (npc.getId() == REAL_BELETH)
|
||||
{
|
||||
npc.getSpawn().setRespawnDelay(0);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onTalk(L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
String html;
|
||||
if ((_killer != null) && (player.getObjectId() == _killer.getObjectId()))
|
||||
{
|
||||
_killer = null;
|
||||
|
||||
giveItems(player, RING);
|
||||
|
||||
html = "32470a.htm";
|
||||
}
|
||||
else
|
||||
{
|
||||
html = "32470b.htm";
|
||||
}
|
||||
|
||||
return HtmCache.getInstance().getHtm(player.getHtmlPrefix(), "html/default/" + html);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFirstTalk(L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
return onTalk(npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (getRandom(100) < 40)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final double distance = npc.calculateDistance(attacker, false, false);
|
||||
if ((distance > 500) || (getRandom(100) < 80))
|
||||
{
|
||||
for (L2Npc beleth : _minions)
|
||||
{
|
||||
if ((beleth != null) && !beleth.isDead() && Util.checkIfInRange(900, beleth, attacker, false) && !beleth.isCastingNow())
|
||||
{
|
||||
beleth.setTarget(attacker);
|
||||
beleth.doCast(FIREBALL.getSkill());
|
||||
}
|
||||
}
|
||||
if ((_beleth != null) && !_beleth.isDead() && Util.checkIfInRange(900, _beleth, attacker, false) && !_beleth.isCastingNow())
|
||||
{
|
||||
_beleth.setTarget(attacker);
|
||||
_beleth.doCast(FIREBALL.getSkill());
|
||||
}
|
||||
}
|
||||
else if (!npc.isDead() && !npc.isCastingNow())
|
||||
{
|
||||
if (!npc.getKnownList().getKnownPlayersInRadius(200).isEmpty())
|
||||
{
|
||||
npc.doCast(LIGHTENING.getSkill());
|
||||
return null;
|
||||
}
|
||||
((L2Attackable) npc).clearAggroList();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (npc.getId() == REAL_BELETH)
|
||||
{
|
||||
cancelQuestTimer("CHECK_ATTACK", null, null);
|
||||
|
||||
setBelethKiller(killer);
|
||||
GrandBossManager.getInstance().setBossStatus(REAL_BELETH, DEAD);
|
||||
final long respawnTime = (Config.BELETH_SPAWN_INTERVAL + getRandom(-Config.BELETH_SPAWN_RANDOM, Config.BELETH_SPAWN_RANDOM)) * 3600000;
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(REAL_BELETH);
|
||||
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(REAL_BELETH, info);
|
||||
startQuestTimer("BELETH_UNLOCK", respawnTime, null, null);
|
||||
|
||||
deleteAll();
|
||||
npc.deleteMe();
|
||||
|
||||
for (L2Character c : ZONE.getCharactersInside())
|
||||
{
|
||||
c.disableAllSkills();
|
||||
c.setIsInvul(true);
|
||||
c.setIsImmobilized(true);
|
||||
}
|
||||
|
||||
_beleth = addSpawn(REAL_BELETH, new Location(16323, 213170, -9357, 49152));
|
||||
_beleth.disableAllSkills();
|
||||
_beleth.setIsInvul(true);
|
||||
_beleth.setIsImmobilized(true);
|
||||
|
||||
_priest = addSpawn(ELF, new Location(_beleth));
|
||||
_priest.setShowSummonAnimation(true);
|
||||
_priest.decayMe();
|
||||
|
||||
_stone = addSpawn(STONE_COFFIN, new Location(12470, 215607, -9381, 49152));
|
||||
|
||||
startQuestTimer("SPAWN26", 1000, null, null);
|
||||
}
|
||||
else if (npc.getObjectId() == _allowedObjId)
|
||||
{
|
||||
deleteAll();
|
||||
|
||||
_killedCount++;
|
||||
if (_killedCount >= 5)
|
||||
{
|
||||
startQuestTimer("SPAWN_REAL", 60000, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
startQuestTimer("SPAWN25", 60000, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setBelethKiller(L2PcInstance killer)
|
||||
{
|
||||
if (killer.getParty() != null)
|
||||
{
|
||||
if (killer.getParty().getCommandChannel() != null)
|
||||
{
|
||||
_killer = killer.getParty().getCommandChannel().getLeader();
|
||||
}
|
||||
else
|
||||
{
|
||||
_killer = killer.getParty().getLeader();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_killer = killer;
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteAll()
|
||||
{
|
||||
_minions.stream().filter(n -> !n.isDead()).forEach(n ->
|
||||
{
|
||||
n.abortCast();
|
||||
n.setTarget(null);
|
||||
n.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||
n.deleteMe();
|
||||
});
|
||||
_allowedObjId = 0;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Beleth();
|
||||
}
|
||||
}
|
||||
224
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Core.java
vendored
Normal file
224
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Core.java
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.model.StatsSet;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Core AI.
|
||||
* @author DrLecter, Emperorc
|
||||
*/
|
||||
final class Core extends AbstractNpcAI
|
||||
{
|
||||
private static final int CORE = 29006;
|
||||
private static final int DEATH_KNIGHT = 29007;
|
||||
private static final int DOOM_WRAITH = 29008;
|
||||
// private static final int DICOR = 29009;
|
||||
// private static final int VALIDUS = 29010;
|
||||
private static final int SUSCEPTOR = 29011;
|
||||
// private static final int PERUM = 29012;
|
||||
// private static final int PREMO = 29013;
|
||||
|
||||
// Core Status Tracking :
|
||||
private static final byte ALIVE = 0; // Core is spawned.
|
||||
private static final byte DEAD = 1; // Core has been killed.
|
||||
|
||||
private static boolean _firstAttacked;
|
||||
|
||||
private final List<L2Attackable> _minions = new CopyOnWriteArrayList<>();
|
||||
|
||||
private Core()
|
||||
{
|
||||
super(Core.class.getSimpleName(), "ai/individual");
|
||||
registerMobs(CORE, DEATH_KNIGHT, DOOM_WRAITH, SUSCEPTOR);
|
||||
|
||||
_firstAttacked = false;
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(CORE);
|
||||
if (GrandBossManager.getInstance().getBossStatus(CORE) == DEAD)
|
||||
{
|
||||
final long temp = info.getLong("respawn_time") - System.currentTimeMillis();
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("core_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
final L2GrandBossInstance core = (L2GrandBossInstance) addSpawn(CORE, 17726, 108915, -6480, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(CORE, ALIVE);
|
||||
spawnBoss(core);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final String test = loadGlobalQuestVar("Core_Attacked");
|
||||
if (test.equalsIgnoreCase("true"))
|
||||
{
|
||||
_firstAttacked = true;
|
||||
}
|
||||
final int loc_x = info.getInt("loc_x");
|
||||
final int loc_y = info.getInt("loc_y");
|
||||
final int loc_z = info.getInt("loc_z");
|
||||
final int heading = info.getInt("heading");
|
||||
final int hp = info.getInt("currentHP");
|
||||
final int mp = info.getInt("currentMP");
|
||||
final L2GrandBossInstance core = (L2GrandBossInstance) addSpawn(CORE, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
core.setCurrentHpMp(hp, mp);
|
||||
spawnBoss(core);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveGlobalData()
|
||||
{
|
||||
saveGlobalQuestVar("Core_Attacked", Boolean.toString(_firstAttacked));
|
||||
}
|
||||
|
||||
public void spawnBoss(L2GrandBossInstance npc)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
// Spawn minions
|
||||
L2Attackable mob;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
final int x = 16800 + (i * 360);
|
||||
mob = (L2Attackable) addSpawn(DEATH_KNIGHT, x, 110000, npc.getZ(), 280 + getRandom(40), false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
mob = (L2Attackable) addSpawn(DEATH_KNIGHT, x, 109000, npc.getZ(), 280 + getRandom(40), false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
final int x2 = 16800 + (i * 600);
|
||||
mob = (L2Attackable) addSpawn(DOOM_WRAITH, x2, 109300, npc.getZ(), 280 + getRandom(40), false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
final int x = 16800 + (i * 450);
|
||||
mob = (L2Attackable) addSpawn(SUSCEPTOR, x, 110300, npc.getZ(), 280 + getRandom(40), false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("core_unlock"))
|
||||
{
|
||||
final L2GrandBossInstance core = (L2GrandBossInstance) addSpawn(CORE, 17726, 108915, -6480, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(CORE, ALIVE);
|
||||
spawnBoss(core);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_minion"))
|
||||
{
|
||||
final L2Attackable mob = (L2Attackable) addSpawn(npc.getId(), npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("despawn_minions"))
|
||||
{
|
||||
_minions.forEach(m -> m.decayMe());
|
||||
_minions.clear();
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.getId() == CORE)
|
||||
{
|
||||
if (_firstAttacked)
|
||||
{
|
||||
if (getRandom(100) == 0)
|
||||
{
|
||||
npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), NpcStringId.REMOVING_INTRUDERS));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_firstAttacked = true;
|
||||
npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), NpcStringId.A_NON_PERMITTED_TARGET_HAS_BEEN_DISCOVERED));
|
||||
npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), NpcStringId.INTRUDER_REMOVAL_SYSTEM_INITIATED));
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (npc.getId() == CORE)
|
||||
{
|
||||
final int objId = npc.getObjectId();
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, objId, npc.getX(), npc.getY(), npc.getZ()));
|
||||
npc.broadcastPacket(new NpcSay(objId, ChatType.NPC_GENERAL, npc.getId(), NpcStringId.A_FATAL_ERROR_HAS_OCCURRED));
|
||||
npc.broadcastPacket(new NpcSay(objId, ChatType.NPC_GENERAL, npc.getId(), NpcStringId.SYSTEM_IS_BEING_SHUT_DOWN));
|
||||
npc.broadcastPacket(new NpcSay(objId, ChatType.NPC_GENERAL, npc.getId(), NpcStringId.EMPTY));
|
||||
_firstAttacked = false;
|
||||
|
||||
GrandBossManager.getInstance().setBossStatus(CORE, DEAD);
|
||||
// Calculate Min and Max respawn times randomly.
|
||||
final long respawnTime = (Config.CORE_SPAWN_INTERVAL + getRandom(-Config.CORE_SPAWN_RANDOM, Config.CORE_SPAWN_RANDOM)) * 3600000;
|
||||
startQuestTimer("core_unlock", respawnTime, null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(CORE);
|
||||
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(CORE, info);
|
||||
startQuestTimer("despawn_minions", 20000, null, null);
|
||||
cancelQuestTimers("spawn_minion");
|
||||
}
|
||||
else if ((GrandBossManager.getInstance().getBossStatus(CORE) == ALIVE) && _minions.contains(npc))
|
||||
{
|
||||
_minions.remove(npc);
|
||||
startQuestTimer("spawn_minion", 60000, npc, null);
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
if (npc.getId() == CORE)
|
||||
{
|
||||
npc.setIsImmobilized(true);
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Core();
|
||||
}
|
||||
}
|
||||
105
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/CrimsonHatuOtis.java
vendored
Normal file
105
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/CrimsonHatuOtis.java
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* AI for Kamaloka (33) - Crimson Hatu Otis
|
||||
* @author Gladicek
|
||||
*/
|
||||
final class CrimsonHatuOtis extends AbstractNpcAI
|
||||
{
|
||||
// Npc
|
||||
private static final int CRIMSON_HATU_OTIS = 18558;
|
||||
// Skills
|
||||
private static SkillHolder BOSS_SPINING_SLASH = new SkillHolder(4737, 1);
|
||||
private static SkillHolder BOSS_HASTE = new SkillHolder(4175, 1);
|
||||
|
||||
private CrimsonHatuOtis()
|
||||
{
|
||||
super(CrimsonHatuOtis.class.getSimpleName(), "ai/individual");
|
||||
addAttackId(CRIMSON_HATU_OTIS);
|
||||
addKillId(CRIMSON_HATU_OTIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "SKILL":
|
||||
{
|
||||
if (npc.isDead())
|
||||
{
|
||||
cancelQuestTimer("SKILL", npc, null);
|
||||
return null;
|
||||
}
|
||||
npc.setTarget(player);
|
||||
npc.doCast(BOSS_SPINING_SLASH.getSkill());
|
||||
startQuestTimer("SKILL", 60000, npc, null);
|
||||
break;
|
||||
}
|
||||
case "BUFF":
|
||||
{
|
||||
if (npc.isScriptValue(2))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(BOSS_HASTE.getSkill());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
startQuestTimer("SKILL", 5000, npc, null);
|
||||
}
|
||||
else if (npc.isScriptValue(1) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.3)))
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.I_VE_HAD_IT_UP_TO_HERE_WITH_YOU_I_LL_TAKE_CARE_OF_YOU);
|
||||
npc.setScriptValue(2);
|
||||
startQuestTimer("BUFF", 1000, npc, null);
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
cancelQuestTimer("SKILL", npc, null);
|
||||
cancelQuestTimer("BUFF", npc, null);
|
||||
return super.onKill(npc, player, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new CrimsonHatuOtis();
|
||||
}
|
||||
}
|
||||
239
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/DarkWaterDragon.java
vendored
Normal file
239
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/DarkWaterDragon.java
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.l2jmobius.gameserver.data.xml.impl.NpcData;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Dark Water Dragon's AI.
|
||||
*/
|
||||
final class DarkWaterDragon extends AbstractNpcAI
|
||||
{
|
||||
private static final int DRAGON = 22267;
|
||||
private static final int SHADE1 = 22268;
|
||||
private static final int SHADE2 = 22269;
|
||||
private static final int FAFURION = 18482;
|
||||
private static final int DETRACTOR1 = 22270;
|
||||
private static final int DETRACTOR2 = 22271;
|
||||
private static final Set<Integer> SECOND_SPAWN = ConcurrentHashMap.newKeySet(); // Used to track if second Shades were already spawned
|
||||
private static Set<Integer> MY_TRACKING_SET = ConcurrentHashMap.newKeySet(); // Used to track instances of npcs
|
||||
private static Map<Integer, L2PcInstance> ID_MAP = new ConcurrentHashMap<>(); // Used to track instances of npcs
|
||||
|
||||
private DarkWaterDragon()
|
||||
{
|
||||
super(DarkWaterDragon.class.getSimpleName(), "ai/individual");
|
||||
final int[] mobs =
|
||||
{
|
||||
DRAGON,
|
||||
SHADE1,
|
||||
SHADE2,
|
||||
FAFURION,
|
||||
DETRACTOR1,
|
||||
DETRACTOR2
|
||||
};
|
||||
addKillId(mobs);
|
||||
addAttackId(mobs);
|
||||
addSpawnId(mobs);
|
||||
MY_TRACKING_SET.clear();
|
||||
SECOND_SPAWN.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
if (event.equalsIgnoreCase("first_spawn")) // timer to start timer "1"
|
||||
{
|
||||
startQuestTimer("1", 40000, npc, null, true); // spawns detractor every 40 seconds
|
||||
}
|
||||
else if (event.equalsIgnoreCase("second_spawn")) // timer to start timer "2"
|
||||
{
|
||||
startQuestTimer("2", 40000, npc, null, true); // spawns detractor every 40 seconds
|
||||
}
|
||||
else if (event.equalsIgnoreCase("third_spawn")) // timer to start timer "3"
|
||||
{
|
||||
startQuestTimer("3", 40000, npc, null, true); // spawns detractor every 40 seconds
|
||||
}
|
||||
else if (event.equalsIgnoreCase("fourth_spawn")) // timer to start timer "4"
|
||||
{
|
||||
startQuestTimer("4", 40000, npc, null, true); // spawns detractor every 40 seconds
|
||||
}
|
||||
else if (event.equalsIgnoreCase("1")) // spawns a detractor
|
||||
{
|
||||
addSpawn(DETRACTOR1, npc.getX() + 100, npc.getY() + 100, npc.getZ(), 0, false, 40000);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("2")) // spawns a detractor
|
||||
{
|
||||
addSpawn(DETRACTOR2, npc.getX() + 100, npc.getY() - 100, npc.getZ(), 0, false, 40000);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("3")) // spawns a detractor
|
||||
{
|
||||
addSpawn(DETRACTOR1, npc.getX() - 100, npc.getY() + 100, npc.getZ(), 0, false, 40000);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("4")) // spawns a detractor
|
||||
{
|
||||
addSpawn(DETRACTOR2, npc.getX() - 100, npc.getY() - 100, npc.getZ(), 0, false, 40000);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("fafurion_despawn")) // Fafurion Kindred disappears and drops reward
|
||||
{
|
||||
cancelQuestTimer("fafurion_poison", npc, null);
|
||||
cancelQuestTimer("1", npc, null);
|
||||
cancelQuestTimer("2", npc, null);
|
||||
cancelQuestTimer("3", npc, null);
|
||||
cancelQuestTimer("4", npc, null);
|
||||
|
||||
MY_TRACKING_SET.remove(npc.getObjectId());
|
||||
player = ID_MAP.remove(npc.getObjectId());
|
||||
if (player != null)
|
||||
{
|
||||
((L2Attackable) npc).doItemDrop(NpcData.getInstance().getTemplate(18485), player);
|
||||
}
|
||||
|
||||
npc.deleteMe();
|
||||
}
|
||||
else if (event.equalsIgnoreCase("fafurion_poison")) // Reduces Fafurions hp like it is poisoned
|
||||
{
|
||||
if (npc.getCurrentHp() <= 500)
|
||||
{
|
||||
cancelQuestTimer("fafurion_despawn", npc, null);
|
||||
cancelQuestTimer("first_spawn", npc, null);
|
||||
cancelQuestTimer("second_spawn", npc, null);
|
||||
cancelQuestTimer("third_spawn", npc, null);
|
||||
cancelQuestTimer("fourth_spawn", npc, null);
|
||||
cancelQuestTimer("1", npc, null);
|
||||
cancelQuestTimer("2", npc, null);
|
||||
cancelQuestTimer("3", npc, null);
|
||||
cancelQuestTimer("4", npc, null);
|
||||
MY_TRACKING_SET.remove(npc.getObjectId());
|
||||
ID_MAP.remove(npc.getObjectId());
|
||||
}
|
||||
npc.reduceCurrentHp(500, npc, null); // poison kills Fafurion if he is not healed
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
final int npcId = npc.getId();
|
||||
final int npcObjId = npc.getObjectId();
|
||||
if (npcId == DRAGON)
|
||||
{
|
||||
if (!MY_TRACKING_SET.contains(npcObjId)) // this allows to handle multiple instances of npc
|
||||
{
|
||||
MY_TRACKING_SET.add(npcObjId);
|
||||
// Spawn first 5 shades on first attack on Dark Water Dragon
|
||||
final L2Character originalAttacker = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : attacker;
|
||||
spawnShade(originalAttacker, SHADE1, npc.getX() + 100, npc.getY() + 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE2, npc.getX() + 100, npc.getY() - 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE1, npc.getX() - 100, npc.getY() + 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE2, npc.getX() - 100, npc.getY() - 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE1, npc.getX() - 150, npc.getY() + 150, npc.getZ());
|
||||
}
|
||||
else if ((npc.getCurrentHp() < (npc.getMaxHp() / 2.0)) && !SECOND_SPAWN.contains(npcObjId))
|
||||
{
|
||||
SECOND_SPAWN.add(npcObjId);
|
||||
// Spawn second 5 shades on half hp of on Dark Water Dragon
|
||||
final L2Character originalAttacker = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : attacker;
|
||||
spawnShade(originalAttacker, SHADE2, npc.getX() + 100, npc.getY() + 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE1, npc.getX() + 100, npc.getY() - 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE2, npc.getX() - 100, npc.getY() + 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE1, npc.getX() - 100, npc.getY() - 100, npc.getZ());
|
||||
spawnShade(originalAttacker, SHADE2, npc.getX() - 150, npc.getY() + 150, npc.getZ());
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
final int npcId = npc.getId();
|
||||
final int npcObjId = npc.getObjectId();
|
||||
if (npcId == DRAGON)
|
||||
{
|
||||
MY_TRACKING_SET.remove(npcObjId);
|
||||
SECOND_SPAWN.remove(npcObjId);
|
||||
final L2Attackable faf = (L2Attackable) addSpawn(FAFURION, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0); // spawns Fafurion Kindred when Dard Water Dragon is dead
|
||||
ID_MAP.put(faf.getObjectId(), killer);
|
||||
}
|
||||
else if (npcId == FAFURION)
|
||||
{
|
||||
cancelQuestTimer("fafurion_poison", npc, null);
|
||||
cancelQuestTimer("fafurion_despawn", npc, null);
|
||||
cancelQuestTimer("first_spawn", npc, null);
|
||||
cancelQuestTimer("second_spawn", npc, null);
|
||||
cancelQuestTimer("third_spawn", npc, null);
|
||||
cancelQuestTimer("fourth_spawn", npc, null);
|
||||
cancelQuestTimer("1", npc, null);
|
||||
cancelQuestTimer("2", npc, null);
|
||||
cancelQuestTimer("3", npc, null);
|
||||
cancelQuestTimer("4", npc, null);
|
||||
MY_TRACKING_SET.remove(npcObjId);
|
||||
ID_MAP.remove(npcObjId);
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
final int npcId = npc.getId();
|
||||
final int npcObjId = npc.getObjectId();
|
||||
if ((npcId == FAFURION) && !MY_TRACKING_SET.contains(npcObjId))
|
||||
{
|
||||
MY_TRACKING_SET.add(npcObjId);
|
||||
// Spawn 4 Detractors on spawn of Fafurion
|
||||
final int x = npc.getX();
|
||||
final int y = npc.getY();
|
||||
addSpawn(DETRACTOR2, x + 100, y + 100, npc.getZ(), 0, false, 40000);
|
||||
addSpawn(DETRACTOR1, x + 100, y - 100, npc.getZ(), 0, false, 40000);
|
||||
addSpawn(DETRACTOR2, x - 100, y + 100, npc.getZ(), 0, false, 40000);
|
||||
addSpawn(DETRACTOR1, x - 100, y - 100, npc.getZ(), 0, false, 40000);
|
||||
startQuestTimer("first_spawn", 2000, npc, null);
|
||||
startQuestTimer("second_spawn", 4000, npc, null);
|
||||
startQuestTimer("third_spawn", 8000, npc, null);
|
||||
startQuestTimer("fourth_spawn", 10000, npc, null);
|
||||
startQuestTimer("fafurion_poison", 3000, npc, null, true);
|
||||
startQuestTimer("fafurion_despawn", 120000, npc, null);
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public void spawnShade(L2Character attacker, int npcId, int x, int y, int z)
|
||||
{
|
||||
final L2Npc shade = addSpawn(npcId, x, y, z, 0, false, 0);
|
||||
addAttackDesire(shade, attacker);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new DarkWaterDragon();
|
||||
}
|
||||
}
|
||||
67
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/DivineBeast.java
vendored
Normal file
67
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/DivineBeast.java
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Summon;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Simple AI that manages special conditions for Divine Beast summon.
|
||||
* @author UnAfraid
|
||||
*/
|
||||
final class DivineBeast extends AbstractNpcAI
|
||||
{
|
||||
private static final int DIVINE_BEAST = 14870;
|
||||
private static final int TRANSFORMATION_ID = 258;
|
||||
private static final int CHECK_TIME = 2 * 1000;
|
||||
|
||||
private DivineBeast()
|
||||
{
|
||||
super(DivineBeast.class.getSimpleName(), "ai");
|
||||
addSummonSpawnId(DIVINE_BEAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSummonSpawn(L2Summon summon)
|
||||
{
|
||||
startQuestTimer("VALIDATE_TRANSFORMATION", CHECK_TIME, null, summon.getActingPlayer(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if ((player == null) || !player.hasServitors())
|
||||
{
|
||||
cancelQuestTimer(event, npc, player);
|
||||
}
|
||||
else if (player.getTransformationId() != TRANSFORMATION_ID)
|
||||
{
|
||||
cancelQuestTimer(event, npc, player);
|
||||
player.getServitors().values().forEach(summon -> summon.unSummon(player));
|
||||
}
|
||||
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new DivineBeast();
|
||||
}
|
||||
}
|
||||
143
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Epidos.java
vendored
Normal file
143
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Epidos.java
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.util.MinionList;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Manages minion's spawn, idle despawn and Teleportation Cube spawn.
|
||||
* @author GKR
|
||||
*/
|
||||
final class Epidos extends AbstractNpcAI
|
||||
{
|
||||
private static final int[] EPIDOSES =
|
||||
{
|
||||
25609,
|
||||
25610,
|
||||
25611,
|
||||
25612
|
||||
};
|
||||
|
||||
private static final int[] MINIONS =
|
||||
{
|
||||
25605,
|
||||
25606,
|
||||
25607,
|
||||
25608
|
||||
};
|
||||
|
||||
private static final int[] MINIONS_COUNT =
|
||||
{
|
||||
3,
|
||||
6,
|
||||
11
|
||||
};
|
||||
|
||||
private final Map<Integer, Double> _lastHp = new ConcurrentHashMap<>();
|
||||
|
||||
private Epidos()
|
||||
{
|
||||
super(Epidos.class.getSimpleName(), "ai/individual");
|
||||
addKillId(EPIDOSES);
|
||||
addSpawnId(EPIDOSES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("check_minions"))
|
||||
{
|
||||
if ((getRandom(1000) > 250) && _lastHp.containsKey(npc.getObjectId()))
|
||||
{
|
||||
final int hpDecreasePercent = (int) (((_lastHp.get(npc.getObjectId()) - npc.getCurrentHp()) * 100) / npc.getMaxHp());
|
||||
int minionsCount = 0;
|
||||
final int spawnedMinions = ((L2MonsterInstance) npc).getMinionList().countSpawnedMinions();
|
||||
|
||||
if ((hpDecreasePercent > 5) && (hpDecreasePercent <= 15) && (spawnedMinions <= 9))
|
||||
{
|
||||
minionsCount = MINIONS_COUNT[0];
|
||||
}
|
||||
else if ((((hpDecreasePercent > 1) && (hpDecreasePercent <= 5)) || ((hpDecreasePercent > 15) && (hpDecreasePercent <= 30))) && (spawnedMinions <= 6))
|
||||
{
|
||||
minionsCount = MINIONS_COUNT[1];
|
||||
}
|
||||
else if (spawnedMinions == 0)
|
||||
{
|
||||
minionsCount = MINIONS_COUNT[2];
|
||||
}
|
||||
|
||||
for (int i = 0; i < minionsCount; i++)
|
||||
{
|
||||
MinionList.spawnMinion((L2MonsterInstance) npc, MINIONS[Arrays.binarySearch(EPIDOSES, npc.getId())]);
|
||||
}
|
||||
|
||||
_lastHp.put(npc.getObjectId(), npc.getCurrentHp());
|
||||
}
|
||||
|
||||
startQuestTimer("check_minions", 10000, npc, null);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("check_idle"))
|
||||
{
|
||||
if (npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_ACTIVE)
|
||||
{
|
||||
npc.deleteMe();
|
||||
}
|
||||
else
|
||||
{
|
||||
startQuestTimer("check_idle", 600000, npc, null);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (npc.isInsideRadius(-45474, 247450, -13994, 2000, true, false))
|
||||
{
|
||||
addSpawn(32376, -45482, 246277, -14184, 0, false, 0, false);
|
||||
}
|
||||
|
||||
_lastHp.remove(npc.getObjectId());
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String onSpawn(L2Npc npc)
|
||||
{
|
||||
startQuestTimer("check_minions", 10000, npc, null);
|
||||
startQuestTimer("check_idle", 600000, npc, null);
|
||||
_lastHp.put(npc.getObjectId(), (double) npc.getMaxHp());
|
||||
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Epidos();
|
||||
}
|
||||
}
|
||||
75
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/EvasGiftBox.java
vendored
Normal file
75
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/EvasGiftBox.java
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.ItemHolder;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Eva's Gift Box AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
final class EvasGiftBox extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int BOX = 32342; // Eva's Gift Box
|
||||
// Skill
|
||||
private static final int BUFF = 1073; // Kiss of Eva
|
||||
// Items
|
||||
private static final ItemHolder CORAL = new ItemHolder(9692, 1); // Red Coral
|
||||
private static final ItemHolder CRYSTAL = new ItemHolder(9693, 1); // Crystal Fragment
|
||||
|
||||
private EvasGiftBox()
|
||||
{
|
||||
super(EvasGiftBox.class.getSimpleName(), "ai/individual");
|
||||
addKillId(BOX);
|
||||
addSpawnId(BOX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (killer.isAffectedBySkill(BUFF))
|
||||
{
|
||||
if (getRandomBoolean())
|
||||
{
|
||||
npc.dropItem(killer, CRYSTAL);
|
||||
}
|
||||
|
||||
if (getRandom(100) < 33)
|
||||
{
|
||||
npc.dropItem(killer, CORAL);
|
||||
}
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
npc.setIsNoRndWalk(true);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new EvasGiftBox();
|
||||
}
|
||||
}
|
||||
146
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/FrightenedRagnaOrc.java
vendored
Normal file
146
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/FrightenedRagnaOrc.java
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Frightened Ragna Orc AI.
|
||||
* @author Gladicek, malyelfik
|
||||
*/
|
||||
final class FrightenedRagnaOrc extends AbstractNpcAI
|
||||
{
|
||||
// NPC ID
|
||||
private static final int MOB_ID = 18807;
|
||||
// Chances
|
||||
private static final int ADENA = 10000;
|
||||
private static final int CHANCE = 1000;
|
||||
private static final int ADENA2 = 1000000;
|
||||
private static final int CHANCE2 = 10;
|
||||
// Skill
|
||||
private static final SkillHolder SKILL = new SkillHolder(6234, 1);
|
||||
|
||||
private FrightenedRagnaOrc()
|
||||
{
|
||||
super(FrightenedRagnaOrc.class.getSimpleName(), "ai/individual");
|
||||
addAttackId(MOB_ID);
|
||||
addKillId(MOB_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.isScriptValue(0))
|
||||
{
|
||||
npc.setScriptValue(1);
|
||||
startQuestTimer("say", (getRandom(5) + 3) * 1000, npc, null, true);
|
||||
}
|
||||
else if ((npc.getCurrentHp() < (npc.getMaxHp() * 0.2)) && npc.isScriptValue(1))
|
||||
{
|
||||
startQuestTimer("reward", 10000, npc, attacker);
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.WAIT_WAIT_STOP_SAVE_ME_AND_I_LL_GIVE_YOU_10_000_000_ADENA);
|
||||
npc.setScriptValue(2);
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
final NpcStringId msg = getRandomBoolean() ? NpcStringId.UGH_A_CURSE_UPON_YOU : NpcStringId.I_REALLY_DIDN_T_WANT_TO_FIGHT;
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, msg);
|
||||
cancelQuestTimer("say", npc, null);
|
||||
cancelQuestTimer("reward", npc, player);
|
||||
return super.onKill(npc, player, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "say":
|
||||
{
|
||||
if (npc.isDead() || !npc.isScriptValue(1))
|
||||
{
|
||||
cancelQuestTimer("say", npc, null);
|
||||
return null;
|
||||
}
|
||||
final NpcStringId msg = getRandomBoolean() ? NpcStringId.I_DON_T_WANT_TO_FIGHT : NpcStringId.IS_THIS_REALLY_NECESSARY;
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, msg);
|
||||
break;
|
||||
}
|
||||
case "reward":
|
||||
{
|
||||
if (!npc.isDead() && npc.isScriptValue(2))
|
||||
{
|
||||
if (getRandom(100000) < CHANCE2)
|
||||
{
|
||||
final NpcStringId msg = getRandomBoolean() ? NpcStringId.TH_THANKS_I_COULD_HAVE_BECOME_GOOD_FRIENDS_WITH_YOU : NpcStringId.I_LL_GIVE_YOU_10_000_000_ADENA_LIKE_I_PROMISED_I_MIGHT_BE_AN_ORC_WHO_KEEPS_MY_PROMISES;
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, msg);
|
||||
npc.setScriptValue(3);
|
||||
npc.doCast(SKILL.getSkill());
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
npc.dropItem(player, Inventory.ADENA_ID, ADENA2);
|
||||
}
|
||||
}
|
||||
else if (getRandom(100000) < CHANCE)
|
||||
{
|
||||
final NpcStringId msg = getRandomBoolean() ? NpcStringId.TH_THANKS_I_COULD_HAVE_BECOME_GOOD_FRIENDS_WITH_YOU : NpcStringId.SORRY_BUT_THIS_IS_ALL_I_HAVE_GIVE_ME_A_BREAK;
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, msg);
|
||||
npc.setScriptValue(3);
|
||||
npc.doCast(SKILL.getSkill());
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
((L2Attackable) npc).dropItem(player, Inventory.ADENA_ID, ADENA);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, getRandomBoolean() ? NpcStringId.THANKS_BUT_THAT_THING_ABOUT_10_000_000_ADENA_WAS_A_LIE_SEE_YA : NpcStringId.YOU_RE_PRETTY_DUMB_TO_BELIEVE_ME);
|
||||
}
|
||||
startQuestTimer("despawn", 1000, npc, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "despawn":
|
||||
{
|
||||
npc.setRunning();
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location((npc.getX() + getRandom(-800, 800)), (npc.getY() + getRandom(-800, 800)), npc.getZ(), npc.getHeading()));
|
||||
npc.deleteMe();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new FrightenedRagnaOrc();
|
||||
}
|
||||
}
|
||||
62
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Gordon.java
vendored
Normal file
62
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Gordon.java
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Gordon AI
|
||||
* @author TOFIZ, malyelfik
|
||||
*/
|
||||
final class Gordon extends AbstractNpcAI
|
||||
{
|
||||
private static final int GORDON = 29095;
|
||||
|
||||
private Gordon()
|
||||
{
|
||||
super(Gordon.class.getSimpleName(), "ai/individual");
|
||||
addSpawnId(GORDON);
|
||||
addSeeCreatureId(GORDON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSeeCreature(L2Npc npc, L2Character creature, boolean isSummon)
|
||||
{
|
||||
if (creature.isPlayer() && ((L2PcInstance) creature).isCursedWeaponEquipped())
|
||||
{
|
||||
addAttackDesire(npc, creature);
|
||||
}
|
||||
return super.onSeeCreature(npc, creature, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
((L2Attackable) npc).setCanReturnToSpawnPoint(false);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Gordon();
|
||||
}
|
||||
}
|
||||
53
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/GraveRobbers.java
vendored
Normal file
53
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/GraveRobbers.java
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Grove Robber's AI.<br>
|
||||
* <ul>
|
||||
* <li>Grove Robber Summoner</li>
|
||||
* <li>Grove Robber Megician</li>
|
||||
* </ul>
|
||||
* @author Zealar
|
||||
*/
|
||||
final class GraveRobbers extends AbstractNpcAI
|
||||
{
|
||||
private static final int GRAVE_ROBBER_SUMMONER = 22678;
|
||||
private static final int GRAVE_ROBBER_MEGICIAN = 22679;
|
||||
|
||||
private GraveRobbers()
|
||||
{
|
||||
super(GraveRobbers.class.getSimpleName(), "ai/individual");
|
||||
addSpawnId(GRAVE_ROBBER_SUMMONER, GRAVE_ROBBER_MEGICIAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
spawnMinions(npc, "Privates" + getRandom(1, 2));
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new GraveRobbers();
|
||||
}
|
||||
}
|
||||
350
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Orfen.java
vendored
Normal file
350
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Orfen.java
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.datatables.SkillData;
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.L2Spawn;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.StatsSet;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.model.zone.type.L2BossZone;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Orfen's AI
|
||||
* @author Emperorc
|
||||
*/
|
||||
final class Orfen extends AbstractNpcAI
|
||||
{
|
||||
private static final Location[] POS =
|
||||
{
|
||||
new Location(43728, 17220, -4342),
|
||||
new Location(55024, 17368, -5412),
|
||||
new Location(53504, 21248, -5486),
|
||||
new Location(53248, 24576, -5262)
|
||||
};
|
||||
|
||||
private static final NpcStringId[] TEXT =
|
||||
{
|
||||
NpcStringId.S1_STOP_KIDDING_YOURSELF_ABOUT_YOUR_OWN_POWERLESSNESS,
|
||||
NpcStringId.S1_I_LL_MAKE_YOU_FEEL_WHAT_TRUE_FEAR_IS,
|
||||
NpcStringId.YOU_RE_REALLY_STUPID_TO_HAVE_CHALLENGED_ME_S1_GET_READY,
|
||||
NpcStringId.S1_DO_YOU_THINK_THAT_S_GOING_TO_WORK
|
||||
};
|
||||
|
||||
private static final int ORFEN = 29014;
|
||||
// private static final int RAIKEL = 29015;
|
||||
private static final int RAIKEL_LEOS = 29016;
|
||||
// private static final int RIBA = 29017;
|
||||
private static final int RIBA_IREN = 29018;
|
||||
|
||||
private static boolean _IsTeleported;
|
||||
private static final List<L2Attackable> MINIONS = new CopyOnWriteArrayList<>();
|
||||
private static L2BossZone ZONE;
|
||||
|
||||
private static final byte ALIVE = 0;
|
||||
private static final byte DEAD = 1;
|
||||
|
||||
private Orfen()
|
||||
{
|
||||
super(Orfen.class.getSimpleName(), "ai/individual");
|
||||
final int[] mobs =
|
||||
{
|
||||
ORFEN,
|
||||
RAIKEL_LEOS,
|
||||
RIBA_IREN
|
||||
};
|
||||
registerMobs(mobs);
|
||||
_IsTeleported = false;
|
||||
ZONE = GrandBossManager.getInstance().getZone(POS[0]);
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN);
|
||||
if (GrandBossManager.getInstance().getBossStatus(ORFEN) == DEAD)
|
||||
{
|
||||
// load the unlock date and time for Orfen from DB
|
||||
final long temp = info.getLong("respawn_time") - System.currentTimeMillis();
|
||||
// if Orfen is locked until a certain time, mark it so and start the unlock timer
|
||||
// the unlock time has not yet expired.
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("orfen_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the time has already expired while the server was offline. Immediately spawn Orfen.
|
||||
final int i = getRandom(10);
|
||||
Location loc;
|
||||
if (i < 4)
|
||||
{
|
||||
loc = POS[1];
|
||||
}
|
||||
else if (i < 7)
|
||||
{
|
||||
loc = POS[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
loc = POS[3];
|
||||
}
|
||||
final L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE);
|
||||
spawnBoss(orfen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final int loc_x = info.getInt("loc_x");
|
||||
final int loc_y = info.getInt("loc_y");
|
||||
final int loc_z = info.getInt("loc_z");
|
||||
final int heading = info.getInt("heading");
|
||||
final int hp = info.getInt("currentHP");
|
||||
final int mp = info.getInt("currentMP");
|
||||
final L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
orfen.setCurrentHpMp(hp, mp);
|
||||
spawnBoss(orfen);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSpawnPoint(L2Npc npc, int index)
|
||||
{
|
||||
((L2Attackable) npc).clearAggroList();
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
final L2Spawn spawn = npc.getSpawn();
|
||||
spawn.setLocation(POS[index]);
|
||||
npc.teleToLocation(POS[index], false);
|
||||
}
|
||||
|
||||
public void spawnBoss(L2GrandBossInstance npc)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
startQuestTimer("check_orfen_pos", 10000, npc, null, true);
|
||||
// Spawn minions
|
||||
final int x = npc.getX();
|
||||
final int y = npc.getY();
|
||||
L2Attackable mob;
|
||||
mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x + 100, y + 100, npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
MINIONS.add(mob);
|
||||
mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x + 100, y - 100, npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
MINIONS.add(mob);
|
||||
mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x - 100, y + 100, npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
MINIONS.add(mob);
|
||||
mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x - 100, y - 100, npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
MINIONS.add(mob);
|
||||
startQuestTimer("check_minion_loc", 10000, npc, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("orfen_unlock"))
|
||||
{
|
||||
final int i = getRandom(10);
|
||||
Location loc;
|
||||
if (i < 4)
|
||||
{
|
||||
loc = POS[1];
|
||||
}
|
||||
else if (i < 7)
|
||||
{
|
||||
loc = POS[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
loc = POS[3];
|
||||
}
|
||||
final L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE);
|
||||
spawnBoss(orfen);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("check_orfen_pos"))
|
||||
{
|
||||
if ((_IsTeleported && (npc.getCurrentHp() > (npc.getMaxHp() * 0.95))) || (!ZONE.isInsideZone(npc) && !_IsTeleported))
|
||||
{
|
||||
setSpawnPoint(npc, getRandom(3) + 1);
|
||||
_IsTeleported = false;
|
||||
}
|
||||
else if (_IsTeleported && !ZONE.isInsideZone(npc))
|
||||
{
|
||||
setSpawnPoint(npc, 0);
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("check_minion_loc"))
|
||||
{
|
||||
for (int i = 0; i < MINIONS.size(); i++)
|
||||
{
|
||||
final L2Attackable mob = MINIONS.get(i);
|
||||
if (!npc.isInsideRadius(mob, 3000, false, false))
|
||||
{
|
||||
mob.teleToLocation(npc.getLocation());
|
||||
((L2Attackable) npc).clearAggroList();
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("despawn_minions"))
|
||||
{
|
||||
for (int i = 0; i < MINIONS.size(); i++)
|
||||
{
|
||||
final L2Attackable mob = MINIONS.get(i);
|
||||
if (mob != null)
|
||||
{
|
||||
mob.decayMe();
|
||||
}
|
||||
}
|
||||
MINIONS.clear();
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_minion"))
|
||||
{
|
||||
final L2Attackable mob = (L2Attackable) addSpawn(RAIKEL_LEOS, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
MINIONS.add(mob);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
|
||||
{
|
||||
if (npc.getId() == ORFEN)
|
||||
{
|
||||
final L2Character originalCaster = isSummon ? caster.getServitors().values().stream().findFirst().orElse(caster.getPet()) : caster;
|
||||
if ((skill.getEffectPoint() > 0) && (getRandom(5) == 0) && npc.isInsideRadius(originalCaster, 1000, false, false))
|
||||
{
|
||||
final NpcSay packet = new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), TEXT[getRandom(4)]);
|
||||
packet.addStringParameter(caster.getName().toString());
|
||||
npc.broadcastPacket(packet);
|
||||
originalCaster.teleToLocation(npc.getLocation());
|
||||
npc.setTarget(originalCaster);
|
||||
npc.doCast(SkillData.getInstance().getSkill(4064, 1));
|
||||
}
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFactionCall(L2Npc npc, L2Npc caller, L2PcInstance attacker, boolean isSummon)
|
||||
{
|
||||
if ((caller == null) || (npc == null) || npc.isCastingNow())
|
||||
{
|
||||
return super.onFactionCall(npc, caller, attacker, isSummon);
|
||||
}
|
||||
final int npcId = npc.getId();
|
||||
final int callerId = caller.getId();
|
||||
if ((npcId == RAIKEL_LEOS) && (getRandom(20) == 0))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SkillData.getInstance().getSkill(4067, 4));
|
||||
}
|
||||
else if (npcId == RIBA_IREN)
|
||||
{
|
||||
int chance = 1;
|
||||
if (callerId == ORFEN)
|
||||
{
|
||||
chance = 9;
|
||||
}
|
||||
if ((callerId != RIBA_IREN) && (caller.getCurrentHp() < (caller.getMaxHp() / 2.0)) && (getRandom(10) < chance))
|
||||
{
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
npc.setTarget(caller);
|
||||
npc.doCast(SkillData.getInstance().getSkill(4516, 1));
|
||||
}
|
||||
}
|
||||
return super.onFactionCall(npc, caller, attacker, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
final int npcId = npc.getId();
|
||||
if (npcId == ORFEN)
|
||||
{
|
||||
if (!_IsTeleported && ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2)))
|
||||
{
|
||||
_IsTeleported = true;
|
||||
setSpawnPoint(npc, 0);
|
||||
}
|
||||
else if (npc.isInsideRadius(attacker, 1000, false, false) && !npc.isInsideRadius(attacker, 300, false, false) && (getRandom(10) == 0))
|
||||
{
|
||||
final NpcSay packet = new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npcId, TEXT[getRandom(3)]);
|
||||
packet.addStringParameter(attacker.getName().toString());
|
||||
npc.broadcastPacket(packet);
|
||||
attacker.teleToLocation(npc.getLocation());
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SkillData.getInstance().getSkill(4064, 1));
|
||||
}
|
||||
}
|
||||
else if ((npcId == RIBA_IREN) && !npc.isCastingNow() && ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2.0)))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SkillData.getInstance().getSkill(4516, 1));
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (npc.getId() == ORFEN)
|
||||
{
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
GrandBossManager.getInstance().setBossStatus(ORFEN, DEAD);
|
||||
// Calculate Min and Max respawn times randomly.
|
||||
final long respawnTime = (Config.ORFEN_SPAWN_INTERVAL + getRandom(-Config.ORFEN_SPAWN_RANDOM, Config.ORFEN_SPAWN_RANDOM)) * 3600000;
|
||||
startQuestTimer("orfen_unlock", respawnTime, null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN);
|
||||
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(ORFEN, info);
|
||||
cancelQuestTimer("check_minion_loc", npc, null);
|
||||
cancelQuestTimer("check_orfen_pos", npc, null);
|
||||
startQuestTimer("despawn_minions", 20000, null, null);
|
||||
cancelQuestTimers("spawn_minion");
|
||||
}
|
||||
else if ((GrandBossManager.getInstance().getBossStatus(ORFEN) == ALIVE) && (npc.getId() == RAIKEL_LEOS))
|
||||
{
|
||||
MINIONS.remove(npc);
|
||||
startQuestTimer("spawn_minion", 360000, npc, null);
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Orfen();
|
||||
}
|
||||
}
|
||||
403
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/QueenAnt.java
vendored
Normal file
403
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/QueenAnt.java
vendored
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.ThreadPoolManager;
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.StatsSet;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Playable;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.CommonSkill;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.model.zone.type.L2BossZone;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Queen Ant's AI
|
||||
* @author Emperorc
|
||||
*/
|
||||
final class QueenAnt extends AbstractNpcAI
|
||||
{
|
||||
private static final int QUEEN = 29001;
|
||||
private static final int LARVA = 29002;
|
||||
private static final int NURSE = 29003;
|
||||
private static final int GUARD = 29004;
|
||||
private static final int ROYAL = 29005;
|
||||
|
||||
private static final int[] MOBS =
|
||||
{
|
||||
QUEEN,
|
||||
LARVA,
|
||||
NURSE,
|
||||
GUARD,
|
||||
ROYAL
|
||||
};
|
||||
|
||||
private static final Location OUST_LOC_1 = new Location(-19480, 187344, -5600);
|
||||
private static final Location OUST_LOC_2 = new Location(-17928, 180912, -5520);
|
||||
private static final Location OUST_LOC_3 = new Location(-23808, 182368, -5600);
|
||||
|
||||
private static final int QUEEN_X = -21610;
|
||||
private static final int QUEEN_Y = 181594;
|
||||
private static final int QUEEN_Z = -5734;
|
||||
|
||||
// QUEEN Status Tracking :
|
||||
private static final byte ALIVE = 0; // Queen Ant is spawned.
|
||||
private static final byte DEAD = 1; // Queen Ant has been killed.
|
||||
|
||||
private static L2BossZone _zone;
|
||||
|
||||
private static SkillHolder HEAL1 = new SkillHolder(4020, 1);
|
||||
private static SkillHolder HEAL2 = new SkillHolder(4024, 1);
|
||||
|
||||
L2MonsterInstance _queen = null;
|
||||
private L2MonsterInstance _larva = null;
|
||||
private final List<L2MonsterInstance> _nurses = new CopyOnWriteArrayList<>();
|
||||
ScheduledFuture<?> _task = null;
|
||||
|
||||
private QueenAnt()
|
||||
{
|
||||
super(QueenAnt.class.getSimpleName(), "ai/individual");
|
||||
addSpawnId(MOBS);
|
||||
addKillId(MOBS);
|
||||
addAggroRangeEnterId(MOBS);
|
||||
addFactionCallId(NURSE);
|
||||
|
||||
_zone = GrandBossManager.getInstance().getZone(QUEEN_X, QUEEN_Y, QUEEN_Z);
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
|
||||
if (GrandBossManager.getInstance().getBossStatus(QUEEN) == DEAD)
|
||||
{
|
||||
// load the unlock date and time for queen ant from DB
|
||||
final long temp = info.getLong("respawn_time") - System.currentTimeMillis();
|
||||
// if queen ant is locked until a certain time, mark it so and start the unlock timer
|
||||
// the unlock time has not yet expired.
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("queen_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the time has already expired while the server was offline. Immediately spawn queen ant.
|
||||
final L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN, QUEEN_X, QUEEN_Y, QUEEN_Z, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(QUEEN, ALIVE);
|
||||
spawnBoss(queen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final int loc_x = QUEEN_X;
|
||||
final int loc_y = QUEEN_Y;
|
||||
final int loc_z = QUEEN_Z;
|
||||
final int heading = info.getInt("heading");
|
||||
final int hp = info.getInt("currentHP");
|
||||
final int mp = info.getInt("currentMP");
|
||||
final L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
queen.setCurrentHpMp(hp, mp);
|
||||
spawnBoss(queen);
|
||||
}
|
||||
}
|
||||
|
||||
private void spawnBoss(L2GrandBossInstance npc)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
if (getRandom(100) < 33)
|
||||
{
|
||||
_zone.movePlayersTo(OUST_LOC_1);
|
||||
}
|
||||
else if (getRandom(100) < 50)
|
||||
{
|
||||
_zone.movePlayersTo(OUST_LOC_2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_zone.movePlayersTo(OUST_LOC_3);
|
||||
}
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
startQuestTimer("action", 10000, npc, null, true);
|
||||
startQuestTimer("heal", 1000, null, null, true);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
_queen = npc;
|
||||
_larva = (L2MonsterInstance) addSpawn(LARVA, -21600, 179482, -5846, getRandom(360), false, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("heal"))
|
||||
{
|
||||
boolean notCasting;
|
||||
final boolean larvaNeedHeal = (_larva != null) && (_larva.getCurrentHp() < _larva.getMaxHp());
|
||||
final boolean queenNeedHeal = (_queen != null) && (_queen.getCurrentHp() < _queen.getMaxHp());
|
||||
for (L2MonsterInstance nurse : _nurses)
|
||||
{
|
||||
if ((nurse == null) || nurse.isDead() || nurse.isCastingNow())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
notCasting = nurse.getAI().getIntention() != CtrlIntention.AI_INTENTION_CAST;
|
||||
if (larvaNeedHeal)
|
||||
{
|
||||
if ((nurse.getTarget() != _larva) || notCasting)
|
||||
{
|
||||
nurse.setTarget(_larva);
|
||||
nurse.useMagic(getRandomBoolean() ? HEAL1.getSkill() : HEAL2.getSkill());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (queenNeedHeal)
|
||||
{
|
||||
if (nurse.getLeader() == _larva)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((nurse.getTarget() != _queen) || notCasting)
|
||||
{
|
||||
nurse.setTarget(_queen);
|
||||
nurse.useMagic(HEAL1.getSkill());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// if nurse not casting - remove target
|
||||
if (notCasting && (nurse.getTarget() != null))
|
||||
{
|
||||
nurse.setTarget(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("action") && (npc != null))
|
||||
{
|
||||
if (getRandom(3) == 0)
|
||||
{
|
||||
if (getRandom(2) == 0)
|
||||
{
|
||||
npc.broadcastSocialAction(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.broadcastSocialAction(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("queen_unlock"))
|
||||
{
|
||||
final L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN, QUEEN_X, QUEEN_Y, QUEEN_Z, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(QUEEN, ALIVE);
|
||||
spawnBoss(queen);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
final L2MonsterInstance mob = (L2MonsterInstance) npc;
|
||||
switch (npc.getId())
|
||||
{
|
||||
case LARVA:
|
||||
{
|
||||
mob.setIsImmobilized(true);
|
||||
mob.setIsMortal(false);
|
||||
mob.setIsRaidMinion(true);
|
||||
break;
|
||||
}
|
||||
case NURSE:
|
||||
{
|
||||
mob.disableCoreAI(true);
|
||||
mob.setIsRaidMinion(true);
|
||||
_nurses.add(mob);
|
||||
break;
|
||||
}
|
||||
case ROYAL:
|
||||
case GUARD:
|
||||
{
|
||||
mob.setIsRaidMinion(true);
|
||||
break;
|
||||
}
|
||||
case QUEEN:
|
||||
{
|
||||
_task = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new QueenAntTask(), 5 * 1000, 5 * 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFactionCall(L2Npc npc, L2Npc caller, L2PcInstance attacker, boolean isSummon)
|
||||
{
|
||||
if ((caller == null) || (npc == null))
|
||||
{
|
||||
return super.onFactionCall(npc, caller, attacker, isSummon);
|
||||
}
|
||||
|
||||
if (!npc.isCastingNow() && (npc.getAI().getIntention() != CtrlIntention.AI_INTENTION_CAST) && (caller.getCurrentHp() < caller.getMaxHp()))
|
||||
{
|
||||
npc.setTarget(caller);
|
||||
((L2Attackable) npc).useMagic(HEAL1.getSkill());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
if ((npc == null) || (player.isGM() && player.isInvisible()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final boolean isMage;
|
||||
final L2Playable character;
|
||||
if (isSummon)
|
||||
{
|
||||
isMage = false;
|
||||
character = player.getServitors().values().stream().findFirst().orElse(player.getPet());
|
||||
}
|
||||
else
|
||||
{
|
||||
isMage = player.isMageClass();
|
||||
character = player;
|
||||
}
|
||||
|
||||
if (character == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!Config.RAID_DISABLE_CURSE && ((character.getLevel() - npc.getLevel()) > 8))
|
||||
{
|
||||
Skill curse = null;
|
||||
if (isMage)
|
||||
{
|
||||
if (!character.isMuted() && (getRandom(4) == 0))
|
||||
{
|
||||
curse = CommonSkill.RAID_CURSE.getSkill();
|
||||
}
|
||||
}
|
||||
else if (!character.isParalyzed() && (getRandom(4) == 0))
|
||||
{
|
||||
curse = CommonSkill.RAID_CURSE2.getSkill();
|
||||
}
|
||||
|
||||
if (curse != null)
|
||||
{
|
||||
npc.broadcastPacket(new MagicSkillUse(npc, character, curse.getId(), curse.getLevel(), 300, 0));
|
||||
curse.applyEffects(npc, character);
|
||||
}
|
||||
|
||||
((L2Attackable) npc).stopHating(character); // for calling again
|
||||
return null;
|
||||
}
|
||||
|
||||
return super.onAggroRangeEnter(npc, player, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
final int npcId = npc.getId();
|
||||
if (npcId == QUEEN)
|
||||
{
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
GrandBossManager.getInstance().setBossStatus(QUEEN, DEAD);
|
||||
// Calculate Min and Max respawn times randomly.
|
||||
final long respawnTime = (Config.QUEEN_ANT_SPAWN_INTERVAL + getRandom(-Config.QUEEN_ANT_SPAWN_RANDOM, Config.QUEEN_ANT_SPAWN_RANDOM)) * 3600000;
|
||||
startQuestTimer("queen_unlock", respawnTime, null, null);
|
||||
cancelQuestTimer("action", npc, null);
|
||||
cancelQuestTimer("heal", null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
|
||||
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(QUEEN, info);
|
||||
_nurses.clear();
|
||||
_larva.deleteMe();
|
||||
_larva = null;
|
||||
_queen = null;
|
||||
if (_task != null)
|
||||
{
|
||||
_task.cancel(false);
|
||||
_task = null;
|
||||
}
|
||||
}
|
||||
else if ((_queen != null) && !_queen.isAlikeDead())
|
||||
{
|
||||
if (npcId == ROYAL)
|
||||
{
|
||||
if (((L2MonsterInstance) npc).getLeader() != null)
|
||||
{
|
||||
((L2MonsterInstance) npc).getLeader().getMinionList().onMinionDie((L2MonsterInstance) npc, (280 + getRandom(40)) * 1000);
|
||||
}
|
||||
}
|
||||
else if (npcId == NURSE)
|
||||
{
|
||||
final L2MonsterInstance mob = (L2MonsterInstance) npc;
|
||||
_nurses.remove(mob);
|
||||
if (mob.getLeader() != null)
|
||||
{
|
||||
mob.getLeader().getMinionList().onMinionDie(mob, 10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
private class QueenAntTask implements Runnable
|
||||
{
|
||||
public QueenAntTask()
|
||||
{
|
||||
// Constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if ((_queen == null) || _queen.isDead())
|
||||
{
|
||||
_task.cancel(false);
|
||||
_task = null;
|
||||
}
|
||||
else if (_queen.calculateDistance(QUEEN_X, QUEEN_Y, QUEEN_Z, false, false) > 2000.)
|
||||
{
|
||||
_queen.clearAggroList();
|
||||
_queen.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(QUEEN_X, QUEEN_Y, QUEEN_Z, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new QueenAnt();
|
||||
}
|
||||
}
|
||||
116
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/QueenShyeed.java
vendored
Normal file
116
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/QueenShyeed.java
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.zone.type.L2EffectZone;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Queen Shyeed AI
|
||||
* @author malyelfik
|
||||
*/
|
||||
final class QueenShyeed extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int SHYEED = 25671;
|
||||
private static final Location SHYEED_LOC = new Location(79634, -55428, -6104, 0);
|
||||
|
||||
// Respawn
|
||||
private static final int RESPAWN = 86400000; // 24 h
|
||||
private static final int RANDOM_RESPAWN = 43200000; // 12 h
|
||||
|
||||
// Zones
|
||||
private static final L2EffectZone MOB_BUFF_ZONE = ZoneManager.getInstance().getZoneById(200103, L2EffectZone.class);
|
||||
private static final L2EffectZone MOB_BUFF_DISPLAY_ZONE = ZoneManager.getInstance().getZoneById(200104, L2EffectZone.class);
|
||||
private static final L2EffectZone PC_BUFF_ZONE = ZoneManager.getInstance().getZoneById(200105, L2EffectZone.class);
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "respawn":
|
||||
{
|
||||
spawnShyeed();
|
||||
break;
|
||||
}
|
||||
case "despawn":
|
||||
{
|
||||
if (!npc.isDead())
|
||||
{
|
||||
npc.deleteMe();
|
||||
startRespawn();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.SHYEED_S_CRY_IS_STEADILY_DYING_DOWN);
|
||||
startRespawn();
|
||||
PC_BUFF_ZONE.setEnabled(true);
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
private QueenShyeed()
|
||||
{
|
||||
super(QueenShyeed.class.getSimpleName(), "ai/individual");
|
||||
addKillId(SHYEED);
|
||||
spawnShyeed();
|
||||
}
|
||||
|
||||
private void spawnShyeed()
|
||||
{
|
||||
final String respawn = loadGlobalQuestVar("Respawn");
|
||||
final long remain = !respawn.isEmpty() ? Long.parseLong(respawn) - System.currentTimeMillis() : 0;
|
||||
if (remain > 0)
|
||||
{
|
||||
startQuestTimer("respawn", remain, null, null);
|
||||
return;
|
||||
}
|
||||
final L2Npc npc = addSpawn(SHYEED, SHYEED_LOC, false, 0);
|
||||
startQuestTimer("despawn", 10800000, npc, null);
|
||||
PC_BUFF_ZONE.setEnabled(false);
|
||||
MOB_BUFF_ZONE.setEnabled(true);
|
||||
MOB_BUFF_DISPLAY_ZONE.setEnabled(true);
|
||||
}
|
||||
|
||||
private void startRespawn()
|
||||
{
|
||||
final int respawnTime = RESPAWN - getRandom(RANDOM_RESPAWN);
|
||||
saveGlobalQuestVar("Respawn", Long.toString(System.currentTimeMillis() + respawnTime));
|
||||
startQuestTimer("respawn", respawnTime, null, null);
|
||||
MOB_BUFF_ZONE.setEnabled(false);
|
||||
MOB_BUFF_DISPLAY_ZONE.setEnabled(false);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new QueenShyeed();
|
||||
}
|
||||
}
|
||||
49
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/RagnaOrcCommander.java
vendored
Normal file
49
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/RagnaOrcCommander.java
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Ragna Orc Commander AI.
|
||||
* @author Zealar
|
||||
*/
|
||||
final class RagnaOrcCommander extends AbstractNpcAI
|
||||
{
|
||||
private static final int RAGNA_ORC_COMMANDER = 22694;
|
||||
|
||||
private RagnaOrcCommander()
|
||||
{
|
||||
super(RagnaOrcCommander.class.getSimpleName(), "ai/individual");
|
||||
addSpawnId(RAGNA_ORC_COMMANDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
spawnMinions(npc, "Privates1");
|
||||
spawnMinions(npc, getRandomBoolean() ? "Privates2" : "Privates3");
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new RagnaOrcCommander();
|
||||
}
|
||||
}
|
||||
48
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/RagnaOrcHero.java
vendored
Normal file
48
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/RagnaOrcHero.java
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Ragna Orc Hero AI.
|
||||
* @author Zealar
|
||||
*/
|
||||
final class RagnaOrcHero extends AbstractNpcAI
|
||||
{
|
||||
private static final int RAGNA_ORC_HERO = 22693;
|
||||
|
||||
private RagnaOrcHero()
|
||||
{
|
||||
super(RagnaOrcHero.class.getSimpleName(), "ai/individual");
|
||||
addSpawnId(RAGNA_ORC_HERO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
spawnMinions(npc, getRandom(100) < 70 ? "Privates1" : "Privates2");
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new RagnaOrcHero();
|
||||
}
|
||||
}
|
||||
48
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/RagnaOrcSeer.java
vendored
Normal file
48
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/RagnaOrcSeer.java
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Ragna Orc Seer AI.
|
||||
* @author Zealar
|
||||
*/
|
||||
final class RagnaOrcSeer extends AbstractNpcAI
|
||||
{
|
||||
private static final int RAGNA_ORC_SEER = 22697;
|
||||
|
||||
private RagnaOrcSeer()
|
||||
{
|
||||
super(RagnaOrcSeer.class.getSimpleName(), "ai/individual");
|
||||
addSpawnId(RAGNA_ORC_SEER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
spawnMinions(npc, "Privates" + getRandom(1, 2));
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new RagnaOrcSeer();
|
||||
}
|
||||
}
|
||||
280
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/ScarletVanHalisha.java
vendored
Normal file
280
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/ScarletVanHalisha.java
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
|
||||
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
|
||||
import static com.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.l2jmobius.gameserver.GeoData;
|
||||
import com.l2jmobius.gameserver.datatables.SkillData;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2DecoyInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.util.Util;
|
||||
import com.l2jmobius.util.Rnd;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* @author Micr0, Zerox
|
||||
*/
|
||||
final class ScarletVanHalisha extends AbstractNpcAI
|
||||
{
|
||||
private L2Character _target;
|
||||
private Skill _skill;
|
||||
private long _lastRangedSkillTime;
|
||||
private final int _rangedSkillMinCoolTime = 60000; // 1 minute
|
||||
|
||||
// NPCs
|
||||
private static final int HALISHA2 = 29046;
|
||||
private static final int HALISHA3 = 29047;
|
||||
|
||||
public ScarletVanHalisha()
|
||||
{
|
||||
super(ScarletVanHalisha.class.getSimpleName(), "ai/individual");
|
||||
addAttackId(HALISHA2, HALISHA3);
|
||||
addKillId(HALISHA2, HALISHA3);
|
||||
addSpellFinishedId(HALISHA2, HALISHA3);
|
||||
registerMobs(HALISHA2, HALISHA3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "attack":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
getSkillAI(npc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "random_target":
|
||||
{
|
||||
_target = getRandomTarget(npc, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
|
||||
{
|
||||
getSkillAI(npc);
|
||||
return super.onSpellFinished(npc, player, skill);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
startQuestTimer("random_Target", 5000, npc, null, true);
|
||||
startQuestTimer("attack", 500, npc, null, true);
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
cancelQuestTimers("attack");
|
||||
cancelQuestTimers("random_Target");
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
private Skill getRndSkills(L2Npc npc)
|
||||
{
|
||||
switch (npc.getId())
|
||||
{
|
||||
case HALISHA2:
|
||||
{
|
||||
if (Rnd.get(100) < 10)
|
||||
{
|
||||
return SkillData.getInstance().getSkill(5015, 2);
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
return SkillData.getInstance().getSkill(5015, 5);
|
||||
}
|
||||
else if (Rnd.get(100) < 2)
|
||||
{
|
||||
return SkillData.getInstance().getSkill(5016, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return SkillData.getInstance().getSkill(5014, 2);
|
||||
}
|
||||
}
|
||||
case HALISHA3:
|
||||
{
|
||||
if (Rnd.get(100) < 10)
|
||||
{
|
||||
return SkillData.getInstance().getSkill(5015, 3);
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
return SkillData.getInstance().getSkill(5015, 6);
|
||||
}
|
||||
else if (Rnd.get(100) < 10)
|
||||
{
|
||||
return SkillData.getInstance().getSkill(5015, 2);
|
||||
}
|
||||
else if (((_lastRangedSkillTime + _rangedSkillMinCoolTime) < System.currentTimeMillis()) && (Rnd.get(100) < 10))
|
||||
{
|
||||
return SkillData.getInstance().getSkill(5019, 1);
|
||||
}
|
||||
else if (((_lastRangedSkillTime + _rangedSkillMinCoolTime) < System.currentTimeMillis()) && (Rnd.get(100) < 10))
|
||||
{
|
||||
return SkillData.getInstance().getSkill(5018, 1);
|
||||
}
|
||||
else if (Rnd.get(100) < 2)
|
||||
{
|
||||
return SkillData.getInstance().getSkill(5016, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return SkillData.getInstance().getSkill(5014, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SkillData.getInstance().getSkill(5014, 1);
|
||||
}
|
||||
|
||||
private synchronized void getSkillAI(L2Npc npc)
|
||||
{
|
||||
if (npc.isInvul() || npc.isCastingNow())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if ((Rnd.get(100) < 30) || (_target == null) || _target.isDead())
|
||||
{
|
||||
_skill = getRndSkills(npc);
|
||||
_target = getRandomTarget(npc, _skill);
|
||||
}
|
||||
final L2Character target = _target;
|
||||
Skill skill = _skill;
|
||||
if (skill == null)
|
||||
{
|
||||
skill = getRndSkills(npc);
|
||||
}
|
||||
|
||||
if (npc.isPhysicalMuted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((target == null) || target.isDead())
|
||||
{
|
||||
npc.setIsCastingNow(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Util.checkIfInRange(skill.getCastRange(), npc, target, true))
|
||||
{
|
||||
npc.getAI().setIntention(AI_INTENTION_IDLE);
|
||||
npc.setTarget(target);
|
||||
npc.setIsCastingNow(true);
|
||||
_target = null;
|
||||
npc.doCast(skill);
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.getAI().setIntention(AI_INTENTION_FOLLOW, target, null);
|
||||
npc.getAI().setIntention(AI_INTENTION_ATTACK, target, null);
|
||||
npc.setIsCastingNow(false);
|
||||
}
|
||||
}
|
||||
|
||||
private L2Character getRandomTarget(L2Npc npc, Skill skill)
|
||||
{
|
||||
final Collection<L2Object> objs = npc.getKnownList().getKnownObjects().values();
|
||||
final ArrayList<L2Character> result = new ArrayList<>();
|
||||
{
|
||||
for (L2Object obj : objs)
|
||||
{
|
||||
if (obj.isPlayable() || (obj instanceof L2DecoyInstance))
|
||||
{
|
||||
if (obj.isPlayer() && obj.getActingPlayer().isInvisible())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (((((L2Character) obj).getZ() < (npc.getZ() - 100)) && (((L2Character) obj).getZ() > (npc.getZ() + 100))) || !GeoData.getInstance().canSeeTarget(((L2Character) obj).getX(), ((L2Character) obj).getY(), ((L2Character) obj).getZ(), npc.getX(), npc.getY(), npc.getZ()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (obj.isPlayable() || (obj instanceof L2DecoyInstance))
|
||||
{
|
||||
int skillRange = 150;
|
||||
if (skill != null)
|
||||
{
|
||||
switch (skill.getId())
|
||||
{
|
||||
case 5014:
|
||||
{
|
||||
skillRange = 150;
|
||||
break;
|
||||
}
|
||||
case 5015:
|
||||
{
|
||||
skillRange = 400;
|
||||
break;
|
||||
}
|
||||
case 5016:
|
||||
{
|
||||
skillRange = 200;
|
||||
break;
|
||||
}
|
||||
case 5018:
|
||||
case 5019:
|
||||
{
|
||||
_lastRangedSkillTime = System.currentTimeMillis();
|
||||
skillRange = 550;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Util.checkIfInRange(skillRange, npc, obj, true) && !((L2Character) obj).isDead())
|
||||
{
|
||||
result.add((L2Character) obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result.isEmpty() && (result.size() != 0))
|
||||
{
|
||||
final Object[] characters = result.toArray();
|
||||
return (L2Character) characters[Rnd.get(characters.length)];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new ScarletVanHalisha();
|
||||
}
|
||||
}
|
||||
176
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/SinEater.java
vendored
Normal file
176
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/SinEater.java
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Summon;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.events.EventType;
|
||||
import com.l2jmobius.gameserver.model.events.ListenerRegisterType;
|
||||
import com.l2jmobius.gameserver.model.events.annotations.Id;
|
||||
import com.l2jmobius.gameserver.model.events.annotations.RegisterEvent;
|
||||
import com.l2jmobius.gameserver.model.events.annotations.RegisterType;
|
||||
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureAttacked;
|
||||
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureKill;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Sin Eater AI.
|
||||
* @author St3eT.
|
||||
*/
|
||||
final class SinEater extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int SIN_EATER = 12564;
|
||||
|
||||
private SinEater()
|
||||
{
|
||||
super(SinEater.class.getSimpleName(), "ai/individual");
|
||||
addSummonSpawnId(SIN_EATER);
|
||||
addSummonTalkId(SIN_EATER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equals("TALK") && (player != null) && (player.getPet() != null))
|
||||
{
|
||||
if (getRandom(100) < 30)
|
||||
{
|
||||
final int random = getRandom(100);
|
||||
final L2Summon summon = player.getPet();
|
||||
|
||||
if (random < 20)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.YAWWWWN_IT_S_SO_BORING_HERE_WE_SHOULD_GO_AND_FIND_SOME_ACTION);
|
||||
}
|
||||
else if (random < 40)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.HEY_IF_YOU_CONTINUE_TO_WASTE_TIME_YOU_WILL_NEVER_FINISH_YOUR_PENANCE);
|
||||
}
|
||||
else if (random < 60)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.I_KNOW_YOU_DON_T_LIKE_ME_THE_FEELING_IS_MUTUAL);
|
||||
}
|
||||
else if (random < 80)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.I_NEED_A_DRINK);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.OH_THIS_IS_DRAGGING_ON_TOO_LONG_AT_THIS_RATE_I_WON_T_MAKE_IT_HOME_BEFORE_THE_SEVEN_SEALS_ARE_BROKEN);
|
||||
}
|
||||
}
|
||||
startQuestTimer("TALK", 60000, null, player);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@RegisterEvent(EventType.ON_CREATURE_KILL)
|
||||
@RegisterType(ListenerRegisterType.NPC)
|
||||
@Id(SIN_EATER)
|
||||
public void onCreatureKill(OnCreatureKill event)
|
||||
{
|
||||
final int random = getRandom(100);
|
||||
final L2Summon summon = (L2Summon) event.getTarget();
|
||||
|
||||
if (random < 30)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.OH_THIS_IS_JUST_GREAT_WHAT_ARE_YOU_GOING_TO_DO_NOW);
|
||||
}
|
||||
else if (random < 70)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.YOU_INCONSIDERATE_MORON_CAN_T_YOU_EVEN_TAKE_CARE_OF_LITTLE_OLD_ME);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.OH_NO_THE_MAN_WHO_EATS_ONE_S_SINS_HAS_DIED_PENITENCE_IS_FURTHER_AWAY);
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterEvent(EventType.ON_CREATURE_ATTACKED)
|
||||
@RegisterType(ListenerRegisterType.NPC)
|
||||
@Id(SIN_EATER)
|
||||
public void onCreatureAttacked(OnCreatureAttacked event)
|
||||
{
|
||||
if (getRandom(100) < 30)
|
||||
{
|
||||
final int random = getRandom(100);
|
||||
final L2Summon summon = (L2Summon) event.getTarget();
|
||||
|
||||
if (random < 35)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.OH_THAT_SMARTS);
|
||||
}
|
||||
else if (random < 70)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.HEY_MASTER_PAY_ATTENTION_I_M_DYING_OVER_HERE);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.WHAT_HAVE_I_DONE_TO_DESERVE_THIS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSummonSpawn(L2Summon summon)
|
||||
{
|
||||
broadcastSummonSay(summon, getRandomBoolean() ? NpcStringId.HEY_IT_SEEMS_LIKE_YOU_NEED_MY_HELP_DOESN_T_IT : NpcStringId.ALMOST_GOT_IT_OUCH_STOP_DAMN_THESE_BLOODY_MANACLES);
|
||||
startQuestTimer("TALK", 60000, null, summon.getOwner());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSummonTalk(L2Summon summon)
|
||||
{
|
||||
if (getRandom(100) < 10)
|
||||
{
|
||||
final int random = getRandom(100);
|
||||
|
||||
if (random < 25)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.USING_A_SPECIAL_SKILL_HERE_COULD_TRIGGER_A_BLOODBATH);
|
||||
}
|
||||
else if (random < 50)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.HEY_WHAT_DO_YOU_EXPECT_OF_ME);
|
||||
}
|
||||
else if (random < 75)
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.UGGGGGH_PUSH_IT_S_NOT_COMING_OUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastSummonSay(summon, NpcStringId.AH_I_MISSED_THE_MARK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcastSummonSay(L2Summon summon, NpcStringId npcstringId)
|
||||
{
|
||||
summon.broadcastPacket(new NpcSay(summon.getObjectId(), ChatType.NPC_GENERAL, summon.getId(), npcstringId));
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new SinEater();
|
||||
}
|
||||
}
|
||||
93
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/SinWardens.java
vendored
Normal file
93
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/SinWardens.java
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Manages Sin Wardens disappearing and chat.
|
||||
* @author GKR
|
||||
*/
|
||||
final class SinWardens extends AbstractNpcAI
|
||||
{
|
||||
private static final int[] SIN_WARDEN_MINIONS =
|
||||
{
|
||||
22424,
|
||||
22425,
|
||||
22426,
|
||||
22427,
|
||||
22428,
|
||||
22429,
|
||||
22430,
|
||||
22432,
|
||||
22433,
|
||||
22434,
|
||||
22435,
|
||||
22436,
|
||||
22437,
|
||||
22438
|
||||
};
|
||||
|
||||
private final Map<Integer, Integer> killedMinionsCount = new ConcurrentHashMap<>();
|
||||
|
||||
private SinWardens()
|
||||
{
|
||||
super(SinWardens.class.getSimpleName(), "ai/individual");
|
||||
addKillId(SIN_WARDEN_MINIONS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (npc.isMinion())
|
||||
{
|
||||
final L2MonsterInstance master = ((L2MonsterInstance) npc).getLeader();
|
||||
if ((master != null) && !master.isDead())
|
||||
{
|
||||
int killedCount = killedMinionsCount.containsKey(master.getObjectId()) ? killedMinionsCount.get(master.getObjectId()) : 0;
|
||||
killedCount++;
|
||||
|
||||
if (killedCount == 5)
|
||||
{
|
||||
master.broadcastPacket(new NpcSay(master.getObjectId(), ChatType.NPC_GENERAL, master.getId(), NpcStringId.WE_MIGHT_NEED_NEW_SLAVES_I_LL_BE_BACK_SOON_SO_WAIT));
|
||||
master.doDie(killer);
|
||||
killedMinionsCount.remove(master.getObjectId());
|
||||
}
|
||||
else
|
||||
{
|
||||
killedMinionsCount.put(master.getObjectId(), killedCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new SinWardens();
|
||||
}
|
||||
}
|
||||
557
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Valakas.java
vendored
Normal file
557
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Valakas.java
vendored
Normal file
@@ -0,0 +1,557 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.GeoData;
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.datatables.SkillData;
|
||||
import com.l2jmobius.gameserver.enums.MountType;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.StatsSet;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Playable;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.BuffInfo;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.model.zone.type.L2BossZone;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
||||
import com.l2jmobius.gameserver.util.Util;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Valakas' AI.
|
||||
* @author Tryskell
|
||||
*/
|
||||
public final class Valakas extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int VALAKAS = 29028;
|
||||
// Skills
|
||||
private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1);
|
||||
private static final int VALAKAS_REGENERATION = 4691;
|
||||
|
||||
private static final SkillHolder[] VALAKAS_REGULAR_SKILLS =
|
||||
{
|
||||
new SkillHolder(4681, 1), // Valakas Trample
|
||||
new SkillHolder(4682, 1), // Valakas Trample
|
||||
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||
};
|
||||
|
||||
private static final SkillHolder[] VALAKAS_LOWHP_SKILLS =
|
||||
{
|
||||
new SkillHolder(4681, 1), // Valakas Trample
|
||||
new SkillHolder(4682, 1), // Valakas Trample
|
||||
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||
};
|
||||
|
||||
private static final SkillHolder[] VALAKAS_AOE_SKILLS =
|
||||
{
|
||||
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||
new SkillHolder(4684, 1), // Valakas Dragon Breath
|
||||
new SkillHolder(4685, 1), // Valakas Tail Stomp
|
||||
new SkillHolder(4686, 1), // Valakas Tail Stomp
|
||||
new SkillHolder(4688, 1), // Valakas Stun
|
||||
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||
};
|
||||
|
||||
// Locations
|
||||
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
||||
{
|
||||
new Location(214880, -116144, -1644),
|
||||
new Location(213696, -116592, -1644),
|
||||
new Location(212112, -116688, -1644),
|
||||
new Location(211184, -115472, -1664),
|
||||
new Location(210336, -114592, -1644),
|
||||
new Location(211360, -113904, -1644),
|
||||
new Location(213152, -112352, -1644),
|
||||
new Location(214032, -113232, -1644),
|
||||
new Location(214752, -114592, -1644),
|
||||
new Location(209824, -115568, -1421),
|
||||
new Location(210528, -112192, -1403),
|
||||
new Location(213120, -111136, -1408),
|
||||
new Location(215184, -111504, -1392),
|
||||
new Location(215456, -117328, -1392),
|
||||
new Location(213200, -118160, -1424)
|
||||
};
|
||||
private static final Location ATTACKER_REMOVE = new Location(150037, -57255, -2976);
|
||||
private static final Location VALAKAS_LAIR = new Location(212852, -114842, -1632);
|
||||
private static final Location VALAKAS_REGENERATION_LOC = new Location(-105200, -253104, -15264);
|
||||
// Valakas status.
|
||||
private static final byte DORMANT = 0; // Valakas is spawned and no one has entered yet. Entry is unlocked.
|
||||
private static final byte WAITING = 1; // Valakas is spawned and someone has entered, triggering a 30 minute window for additional people to enter. Entry is unlocked.
|
||||
private static final byte FIGHTING = 2; // Valakas is engaged in battle, annihilating his foes. Entry is locked.
|
||||
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
||||
// Misc
|
||||
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
||||
private L2Playable _actualVictim; // Actual target of Valakas.
|
||||
private static L2BossZone ZONE;
|
||||
|
||||
private Valakas()
|
||||
{
|
||||
super(Valakas.class.getSimpleName(), "ai/individual");
|
||||
registerMobs(VALAKAS);
|
||||
|
||||
ZONE = GrandBossManager.getInstance().getZone(212852, -114842, -1632);
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(VALAKAS);
|
||||
final int status = GrandBossManager.getInstance().getBossStatus(VALAKAS);
|
||||
|
||||
if (status == DEAD)
|
||||
{
|
||||
// load the unlock date and time for valakas from DB
|
||||
final long temp = info.getLong("respawn_time") - System.currentTimeMillis();
|
||||
if (temp > 0)
|
||||
{
|
||||
// The time has not yet expired. Mark Valakas as currently locked (dead).
|
||||
startQuestTimer("valakas_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The time has expired while the server was offline. Spawn valakas in his cave as DORMANT.
|
||||
final L2Npc valakas = addSpawn(VALAKAS, -105200, -253104, -15264, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(VALAKAS, DORMANT);
|
||||
GrandBossManager.getInstance().addBoss((L2GrandBossInstance) valakas);
|
||||
|
||||
valakas.setIsInvul(true);
|
||||
valakas.setRunning();
|
||||
|
||||
valakas.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final int loc_x = info.getInt("loc_x");
|
||||
final int loc_y = info.getInt("loc_y");
|
||||
final int loc_z = info.getInt("loc_z");
|
||||
final int heading = info.getInt("heading");
|
||||
final int hp = info.getInt("currentHP");
|
||||
final int mp = info.getInt("currentMP");
|
||||
|
||||
final L2Npc valakas = addSpawn(VALAKAS, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
GrandBossManager.getInstance().addBoss((L2GrandBossInstance) valakas);
|
||||
|
||||
valakas.setCurrentHpMp(hp, mp);
|
||||
valakas.setRunning();
|
||||
|
||||
// Start timers.
|
||||
if (status == FIGHTING)
|
||||
{
|
||||
// stores current time for inactivity task.
|
||||
_timeTracker = System.currentTimeMillis();
|
||||
|
||||
startQuestTimer("regen_task", 60000, valakas, null, true);
|
||||
startQuestTimer("skill_task", 2000, valakas, null, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
valakas.setIsInvul(true);
|
||||
valakas.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||
|
||||
// Start timer to lock entry after 30 minutes
|
||||
if (status == WAITING)
|
||||
{
|
||||
startQuestTimer("beginning", Config.VALAKAS_WAIT_TIME * 60000, valakas, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
if (event.equalsIgnoreCase("beginning"))
|
||||
{
|
||||
// Stores current time
|
||||
_timeTracker = System.currentTimeMillis();
|
||||
|
||||
// Teleport Valakas to his lair.
|
||||
npc.teleToLocation(VALAKAS_LAIR);
|
||||
|
||||
// Sound + socialAction.
|
||||
for (L2PcInstance plyr : ZONE.getPlayersInside())
|
||||
{
|
||||
plyr.sendPacket(new PlaySound(1, "B03_A", 0, 0, 0, 0, 0));
|
||||
plyr.sendPacket(new SocialAction(npc.getObjectId(), 3));
|
||||
}
|
||||
|
||||
// Launch the cinematic, and tasks (regen + skill).
|
||||
startQuestTimer("spawn_1", 1700, npc, null); // 1700
|
||||
startQuestTimer("spawn_2", 3200, npc, null); // 1500
|
||||
startQuestTimer("spawn_3", 6500, npc, null); // 3300
|
||||
startQuestTimer("spawn_4", 9400, npc, null); // 2900
|
||||
startQuestTimer("spawn_5", 12100, npc, null); // 2700
|
||||
startQuestTimer("spawn_6", 12430, npc, null); // 330
|
||||
startQuestTimer("spawn_7", 15430, npc, null); // 3000
|
||||
startQuestTimer("spawn_8", 16830, npc, null); // 1400
|
||||
startQuestTimer("spawn_9", 23530, npc, null); // 6700 - end of cinematic
|
||||
startQuestTimer("spawn_10", 26000, npc, null); // 2500 - AI + unlock
|
||||
}
|
||||
// Regeneration && inactivity task
|
||||
else if (event.equalsIgnoreCase("regen_task"))
|
||||
{
|
||||
// Inactivity task - 15min
|
||||
if ((GrandBossManager.getInstance().getBossStatus(VALAKAS) == FIGHTING) && ((_timeTracker + 900000) < System.currentTimeMillis()))
|
||||
{
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||
npc.teleToLocation(VALAKAS_REGENERATION_LOC);
|
||||
|
||||
GrandBossManager.getInstance().setBossStatus(VALAKAS, DORMANT);
|
||||
npc.setCurrentHpMp(npc.getMaxHp(), npc.getMaxMp());
|
||||
|
||||
// Drop all players from the zone.
|
||||
ZONE.oustAllPlayers();
|
||||
|
||||
// Cancel skill_task and regen_task.
|
||||
cancelQuestTimer("regen_task", npc, null);
|
||||
cancelQuestTimer("skill_task", npc, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Verify if "Valakas Regeneration" skill is active.
|
||||
final BuffInfo info = npc.getEffectList().getBuffInfoBySkillId(VALAKAS_REGENERATION);
|
||||
final int lvl = info != null ? info.getSkill().getLevel() : 0;
|
||||
|
||||
// Current HPs are inferior to 25% ; apply lvl 4 of regen skill.
|
||||
if ((npc.getCurrentHp() < (npc.getMaxHp() / 4)) && (lvl != 4))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(SkillData.getInstance().getSkill(VALAKAS_REGENERATION, 4));
|
||||
}
|
||||
// Current HPs are inferior to 50% ; apply lvl 3 of regen skill.
|
||||
else if ((npc.getCurrentHp() < ((npc.getMaxHp() * 2) / 4.0)) && (lvl != 3))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(SkillData.getInstance().getSkill(VALAKAS_REGENERATION, 3));
|
||||
}
|
||||
// Current HPs are inferior to 75% ; apply lvl 2 of regen skill.
|
||||
else if ((npc.getCurrentHp() < ((npc.getMaxHp() * 3) / 4.0)) && (lvl != 2))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(SkillData.getInstance().getSkill(VALAKAS_REGENERATION, 2));
|
||||
}
|
||||
// Apply lvl 1.
|
||||
else if (lvl != 1)
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(SkillData.getInstance().getSkill(VALAKAS_REGENERATION, 1));
|
||||
}
|
||||
}
|
||||
// Spawn cinematic, regen_task and choose of skill.
|
||||
else if (event.equalsIgnoreCase("spawn_1"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 1800, 180, -1, 1500, 15000, 10000, 0, 0, 1, 0, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_2"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 1300, 180, -5, 3000, 15000, 10000, 0, -5, 1, 0, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_3"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 500, 180, -8, 600, 15000, 10000, 0, 60, 1, 0, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_4"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 800, 180, -8, 2700, 15000, 10000, 0, 30, 1, 0, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_5"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 200, 250, 70, 0, 15000, 10000, 30, 80, 1, 0, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_6"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 1100, 250, 70, 2500, 15000, 10000, 30, 80, 1, 0, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_7"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 700, 150, 30, 0, 15000, 10000, -10, 60, 1, 0, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_8"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 1200, 150, 20, 2900, 15000, 10000, -10, 30, 1, 0, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_9"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 750, 170, -10, 3400, 15000, 4000, 10, -15, 1, 0, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_10"))
|
||||
{
|
||||
GrandBossManager.getInstance().setBossStatus(VALAKAS, FIGHTING);
|
||||
npc.setIsInvul(false);
|
||||
|
||||
startQuestTimer("regen_task", 60000, npc, null, true);
|
||||
startQuestTimer("skill_task", 2000, npc, null, true);
|
||||
}
|
||||
// Death cinematic, spawn of Teleport Cubes.
|
||||
else if (event.equalsIgnoreCase("die_1"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 2000, 130, -1, 0, 15000, 10000, 0, 0, 1, 1, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("die_2"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 1100, 210, -5, 3000, 15000, 10000, -13, 0, 1, 1, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("die_3"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 1300, 200, -8, 3000, 15000, 10000, 0, 15, 1, 1, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("die_4"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 1000, 190, 0, 500, 15000, 10000, 0, 10, 1, 1, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("die_5"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 1700, 120, 0, 2500, 15000, 10000, 12, 40, 1, 1, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("die_6"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 1700, 20, 0, 700, 15000, 10000, 10, 10, 1, 1, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("die_7"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 1700, 10, 0, 1000, 15000, 10000, 20, 70, 1, 1, 0));
|
||||
}
|
||||
else if (event.equalsIgnoreCase("die_8"))
|
||||
{
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 1700, 10, 0, 300, 15000, 250, 20, -20, 1, 1, 0));
|
||||
|
||||
for (Location loc : TELEPORT_CUBE_LOCATIONS)
|
||||
{
|
||||
addSpawn(31759, loc, false, 900000);
|
||||
}
|
||||
|
||||
startQuestTimer("remove_players", 900000, null, null);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("skill_task"))
|
||||
{
|
||||
callSkillAI(npc);
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("valakas_unlock"))
|
||||
{
|
||||
final L2Npc valakas = addSpawn(VALAKAS, -105200, -253104, -15264, 32768, false, 0);
|
||||
GrandBossManager.getInstance().addBoss((L2GrandBossInstance) valakas);
|
||||
GrandBossManager.getInstance().setBossStatus(VALAKAS, DORMANT);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("remove_players"))
|
||||
{
|
||||
ZONE.oustAllPlayers();
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
npc.disableCoreAI(true);
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (!ZONE.isInsideZone(attacker))
|
||||
{
|
||||
attacker.doDie(attacker);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (npc.isInvul())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (GrandBossManager.getInstance().getBossStatus(VALAKAS) != FIGHTING)
|
||||
{
|
||||
attacker.teleToLocation(ATTACKER_REMOVE);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Debuff strider-mounted players.
|
||||
if ((attacker.getMountType() == MountType.STRIDER) && !attacker.isAffectedBySkill(4258))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SkillData.getInstance().getSkill(4258, 1));
|
||||
}
|
||||
_timeTracker = System.currentTimeMillis();
|
||||
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
// Cancel skill_task and regen_task.
|
||||
cancelQuestTimer("regen_task", npc, null);
|
||||
cancelQuestTimer("skill_task", npc, null);
|
||||
|
||||
// Launch death animation.
|
||||
ZONE.broadcastPacket(new PlaySound(1, "B03_D", 0, 0, 0, 0, 0));
|
||||
ZONE.broadcastPacket(new SpecialCamera(npc, 1200, 20, -10, 0, 10000, 13000, 0, 0, 0, 0, 0));
|
||||
|
||||
startQuestTimer("die_1", 300, npc, null); // 300
|
||||
startQuestTimer("die_2", 600, npc, null); // 300
|
||||
startQuestTimer("die_3", 3800, npc, null); // 3200
|
||||
startQuestTimer("die_4", 8200, npc, null); // 4400
|
||||
startQuestTimer("die_5", 8700, npc, null); // 500
|
||||
startQuestTimer("die_6", 13300, npc, null); // 4600
|
||||
startQuestTimer("die_7", 14000, npc, null); // 700
|
||||
startQuestTimer("die_8", 16500, npc, null); // 2500
|
||||
|
||||
GrandBossManager.getInstance().setBossStatus(VALAKAS, DEAD);
|
||||
// Calculate Min and Max respawn times randomly.
|
||||
final long respawnTime = (Config.VALAKAS_SPAWN_INTERVAL + getRandom(-Config.VALAKAS_SPAWN_RANDOM, Config.VALAKAS_SPAWN_RANDOM)) * 3600000;
|
||||
startQuestTimer("valakas_unlock", respawnTime, null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(VALAKAS);
|
||||
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(VALAKAS, info);
|
||||
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private void callSkillAI(L2Npc npc)
|
||||
{
|
||||
if (npc.isInvul() || npc.isCastingNow())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target.
|
||||
if ((_actualVictim == null) || _actualVictim.isDead() || !npc.getKnownList().knowsObject(_actualVictim) || (getRandom(10) == 0))
|
||||
{
|
||||
_actualVictim = getRandomTarget(npc);
|
||||
}
|
||||
|
||||
// If result is still null, Valakas will roam. Don't go deeper in skill AI.
|
||||
if (_actualVictim == null)
|
||||
{
|
||||
if (getRandom(10) == 0)
|
||||
{
|
||||
final int x = npc.getX();
|
||||
final int y = npc.getY();
|
||||
final int z = npc.getZ();
|
||||
|
||||
final int posX = x + getRandom(-1400, 1400);
|
||||
final int posY = y + getRandom(-1400, 1400);
|
||||
|
||||
if (GeoData.getInstance().canMove(x, y, z, posX, posY, z, npc.getInstanceId()))
|
||||
{
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final Skill skill = getRandomSkill(npc).getSkill();
|
||||
|
||||
// Cast the skill or follow the target.
|
||||
if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc, _actualVictim, true))
|
||||
{
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||
npc.setIsCastingNow(true);
|
||||
npc.setTarget(_actualVictim);
|
||||
npc.doCast(skill);
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null);
|
||||
npc.setIsCastingNow(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick a random skill.<br>
|
||||
* Valakas will mostly use utility skills. If Valakas feels surrounded, he will use AoE skills.<br>
|
||||
* Lower than 50% HPs, he will begin to use Meteor skill.
|
||||
* @param npc valakas
|
||||
* @return a skill holder
|
||||
*/
|
||||
private SkillHolder getRandomSkill(L2Npc npc)
|
||||
{
|
||||
final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100);
|
||||
|
||||
// Valakas Lava Skin has priority.
|
||||
if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId()))
|
||||
{
|
||||
return VALAKAS_LAVA_SKIN;
|
||||
}
|
||||
|
||||
// Valakas will use mass spells if he feels surrounded.
|
||||
if (Util.getPlayersCountInRadius(1200, npc, false, false) >= 20)
|
||||
{
|
||||
return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)];
|
||||
}
|
||||
|
||||
if (hpRatio > 50)
|
||||
{
|
||||
return VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)];
|
||||
}
|
||||
|
||||
return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Pickup a random L2Playable from the zone, deads targets aren't included.
|
||||
* @param npc
|
||||
* @return a random L2Playable.
|
||||
*/
|
||||
private L2Playable getRandomTarget(L2Npc npc)
|
||||
{
|
||||
final List<L2Playable> result = new ArrayList<>();
|
||||
|
||||
for (L2Character obj : npc.getKnownList().getKnownCharacters())
|
||||
{
|
||||
if ((obj == null) || obj.isPet())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (!obj.isDead() && obj.isPlayable())
|
||||
{
|
||||
result.add((L2Playable) obj);
|
||||
}
|
||||
}
|
||||
|
||||
return result.isEmpty() ? null : result.get(getRandom(result.size()));
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Valakas();
|
||||
}
|
||||
}
|
||||
3
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Venom/29055.html
vendored
Normal file
3
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Venom/29055.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Teleportation Cubic:<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Venom">Leave the prison.</Button>
|
||||
</body></html>
|
||||
3
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Venom/35506-02.html
vendored
Normal file
3
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Venom/35506-02.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>
|
||||
When attacking a castle, its defenses can easily be paralyzed.... What if that demon escapes?
|
||||
</body></html>
|
||||
4
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Venom/35506.html
vendored
Normal file
4
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Venom/35506.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>
|
||||
The roar of that scary demon in the dungeon always makes me want to run away! I know the dungeon is well-built, but if its defenses are broken, it could collapse!<br><p>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Venom">Teleport to the dungeon</Button>
|
||||
</body></html>
|
||||
426
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Venom/Venom.java
vendored
Normal file
426
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/Venom/Venom.java
vendored
Normal file
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual.Venom;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.instancemanager.CastleManager;
|
||||
import com.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.TeleportWhereType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.events.impl.sieges.castle.OnCastleSiegeFinish;
|
||||
import com.l2jmobius.gameserver.model.events.impl.sieges.castle.OnCastleSiegeStart;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.model.zone.ZoneId;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Venom AI on Rune Castle.
|
||||
* @author nonom, MELERIX
|
||||
*/
|
||||
final class Venom extends AbstractNpcAI
|
||||
{
|
||||
private static final int CASTLE = 8; // Rune
|
||||
|
||||
private static final int VENOM = 29054;
|
||||
private static final int TELEPORT_CUBE = 29055;
|
||||
private static final int DUNGEON_KEEPER = 35506;
|
||||
|
||||
private static final byte ALIVE = 0;
|
||||
private static final byte DEAD = 1;
|
||||
|
||||
private static final int HOURS_BEFORE = 24;
|
||||
|
||||
private static final Location[] TARGET_TELEPORTS =
|
||||
{
|
||||
new Location(12860, -49158, 976),
|
||||
new Location(14878, -51339, 1024),
|
||||
new Location(15674, -49970, 864),
|
||||
new Location(15696, -48326, 864),
|
||||
new Location(14873, -46956, 1024),
|
||||
new Location(12157, -49135, -1088),
|
||||
new Location(12875, -46392, -288),
|
||||
new Location(14087, -46706, -288),
|
||||
new Location(14086, -51593, -288),
|
||||
new Location(12864, -51898, -288),
|
||||
new Location(15538, -49153, -1056),
|
||||
new Location(17001, -49149, -1064)
|
||||
};
|
||||
|
||||
private static final Location TRHONE = new Location(11025, -49152, -537);
|
||||
private static final Location DUNGEON = new Location(11882, -49216, -3008);
|
||||
private static final Location TELEPORT = new Location(12589, -49044, -3008);
|
||||
private static final Location CUBE = new Location(12047, -49211, -3009);
|
||||
|
||||
private static final SkillHolder VENOM_STRIKE = new SkillHolder(4993, 1);
|
||||
private static final SkillHolder SONIC_STORM = new SkillHolder(4994, 1);
|
||||
private static final SkillHolder VENOM_TELEPORT = new SkillHolder(4995, 1);
|
||||
private static final SkillHolder RANGE_TELEPORT = new SkillHolder(4996, 1);
|
||||
|
||||
private L2Npc _venom;
|
||||
private L2Npc _massymore;
|
||||
|
||||
private Location _loc;
|
||||
|
||||
private boolean _aggroMode = false;
|
||||
private boolean _prisonIsOpen = false;
|
||||
|
||||
// @formatter:off
|
||||
private static final int[] TARGET_TELEPORTS_OFFSET =
|
||||
{
|
||||
650, 100, 100, 100, 100, 650, 200, 200, 200, 200, 200, 650
|
||||
};
|
||||
// @formatter:on
|
||||
|
||||
private static List<L2PcInstance> _targets = new ArrayList<>();
|
||||
|
||||
private Venom()
|
||||
{
|
||||
super(Venom.class.getSimpleName(), "ai/individual");
|
||||
addStartNpc(DUNGEON_KEEPER, TELEPORT_CUBE);
|
||||
addFirstTalkId(DUNGEON_KEEPER, TELEPORT_CUBE);
|
||||
addTalkId(DUNGEON_KEEPER, TELEPORT_CUBE);
|
||||
addSpawnId(VENOM, DUNGEON_KEEPER);
|
||||
addSpellFinishedId(VENOM);
|
||||
addAttackId(VENOM);
|
||||
addKillId(VENOM);
|
||||
addAggroRangeEnterId(VENOM);
|
||||
setCastleSiegeStartId(this::onSiegeStart, CASTLE);
|
||||
setCastleSiegeFinishId(this::onSiegeFinish, CASTLE);
|
||||
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
final long startSiegeDate = CastleManager.getInstance().getCastleById(CASTLE).getSiegeDate().getTimeInMillis();
|
||||
if ((currentTime > (startSiegeDate - (HOURS_BEFORE * 360000))) && (currentTime < startSiegeDate))
|
||||
{
|
||||
_prisonIsOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onTalk(L2Npc npc, L2PcInstance talker)
|
||||
{
|
||||
switch (npc.getId())
|
||||
{
|
||||
case TELEPORT_CUBE:
|
||||
{
|
||||
talker.teleToLocation(TeleportWhereType.TOWN);
|
||||
break;
|
||||
}
|
||||
case DUNGEON_KEEPER:
|
||||
{
|
||||
if (_prisonIsOpen)
|
||||
{
|
||||
talker.teleToLocation(TELEPORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "35506-02.html";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onTalk(npc, talker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "tower_check":
|
||||
{
|
||||
if (CastleManager.getInstance().getCastleById(CASTLE).getSiege().getControlTowerCount() <= 1)
|
||||
{
|
||||
changeLocation(MoveTo.THRONE);
|
||||
broadcastNpcSay(_massymore, ChatType.NPC_SHOUT, NpcStringId.OH_NO_THE_DEFENSES_HAVE_FAILED_IT_IS_TOO_DANGEROUS_TO_REMAIN_INSIDE_THE_CASTLE_FLEE_EVERY_MAN_FOR_HIMSELF);
|
||||
cancelQuestTimer("tower_check", npc, null);
|
||||
startQuestTimer("raid_check", 10000, npc, null, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "raid_check":
|
||||
{
|
||||
if (!npc.isInsideZone(ZoneId.SIEGE) && !npc.isTeleporting())
|
||||
{
|
||||
npc.teleToLocation(_loc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "cube_despawn":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
npc.deleteMe();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
if (isSummon)
|
||||
{
|
||||
return super.onAggroRangeEnter(npc, player, isSummon);
|
||||
}
|
||||
|
||||
if (_aggroMode && (_targets.size() < 10) && (getRandom(3) < 1) && !player.isDead())
|
||||
{
|
||||
_targets.add(player);
|
||||
}
|
||||
return super.onAggroRangeEnter(npc, player, isSummon);
|
||||
}
|
||||
|
||||
public void onSiegeStart(OnCastleSiegeStart event)
|
||||
{
|
||||
_aggroMode = true;
|
||||
_prisonIsOpen = false;
|
||||
if ((_venom != null) && !_venom.isDead())
|
||||
{
|
||||
_venom.setCurrentHp(_venom.getMaxHp());
|
||||
_venom.setCurrentMp(_venom.getMaxMp());
|
||||
_venom.enableSkill(VENOM_TELEPORT.getSkill());
|
||||
_venom.enableSkill(RANGE_TELEPORT.getSkill());
|
||||
startQuestTimer("tower_check", 30000, _venom, null, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onSiegeFinish(OnCastleSiegeFinish event)
|
||||
{
|
||||
_aggroMode = false;
|
||||
if ((_venom != null) && !_venom.isDead())
|
||||
{
|
||||
changeLocation(MoveTo.PRISON);
|
||||
_venom.disableSkill(VENOM_TELEPORT.getSkill(), -1);
|
||||
_venom.disableSkill(RANGE_TELEPORT.getSkill(), -1);
|
||||
}
|
||||
updateStatus(ALIVE);
|
||||
cancelQuestTimer("tower_check", _venom, null);
|
||||
cancelQuestTimer("raid_check", _venom, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
|
||||
{
|
||||
switch (skill.getId())
|
||||
{
|
||||
case 4222:
|
||||
{
|
||||
npc.teleToLocation(_loc);
|
||||
break;
|
||||
}
|
||||
case 4995:
|
||||
{
|
||||
teleportTarget(player);
|
||||
((L2Attackable) npc).stopHating(player);
|
||||
break;
|
||||
}
|
||||
case 4996:
|
||||
{
|
||||
teleportTarget(player);
|
||||
((L2Attackable) npc).stopHating(player);
|
||||
if ((_targets != null) && (_targets.size() > 0))
|
||||
{
|
||||
for (L2PcInstance target : _targets)
|
||||
{
|
||||
final long x = player.getX() - target.getX();
|
||||
final long y = player.getY() - target.getY();
|
||||
final long z = player.getZ() - target.getZ();
|
||||
final long range = 250;
|
||||
if (((x * x) + (y * y) + (z * z)) <= (range * range))
|
||||
{
|
||||
teleportTarget(target);
|
||||
((L2Attackable) npc).stopHating(target);
|
||||
}
|
||||
}
|
||||
_targets.clear();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onSpellFinished(npc, player, skill);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String onSpawn(L2Npc npc)
|
||||
{
|
||||
switch (npc.getId())
|
||||
{
|
||||
case DUNGEON_KEEPER:
|
||||
{
|
||||
_massymore = npc;
|
||||
break;
|
||||
}
|
||||
case VENOM:
|
||||
{
|
||||
_venom = npc;
|
||||
|
||||
_loc = _venom.getLocation();
|
||||
_venom.disableSkill(VENOM_TELEPORT.getSkill(), -1);
|
||||
_venom.disableSkill(RANGE_TELEPORT.getSkill(), -1);
|
||||
_venom.doRevive();
|
||||
broadcastNpcSay(npc, ChatType.NPC_SHOUT, NpcStringId.WHO_DARES_TO_COVET_THE_THRONE_OF_OUR_CASTLE_LEAVE_IMMEDIATELY_OR_YOU_WILL_PAY_THE_PRICE_OF_YOUR_AUDACITY_WITH_YOUR_VERY_OWN_BLOOD);
|
||||
((L2Attackable) _venom).setCanReturnToSpawnPoint(false);
|
||||
if (checkStatus() == DEAD)
|
||||
{
|
||||
_venom.deleteMe();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (checkStatus() == DEAD)
|
||||
{
|
||||
npc.deleteMe();
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.doRevive();
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
final double distance = npc.calculateDistance(attacker, false, false);
|
||||
if (_aggroMode && (getRandom(100) < 25))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(VENOM_TELEPORT.getSkill());
|
||||
}
|
||||
else if (_aggroMode && (npc.getCurrentHp() < (npc.getMaxHp() / 3)) && (getRandom(100) < 25) && !npc.isCastingNow())
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(RANGE_TELEPORT.getSkill());
|
||||
}
|
||||
else if ((distance > 300) && (getRandom(100) < 10) && !npc.isCastingNow())
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(VENOM_STRIKE.getSkill());
|
||||
}
|
||||
else if ((getRandom(100) < 10) && !npc.isCastingNow())
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(SONIC_STORM.getSkill());
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
updateStatus(DEAD);
|
||||
broadcastNpcSay(npc, ChatType.NPC_SHOUT, NpcStringId.IT_S_NOT_OVER_YET_IT_WON_T_BE_OVER_LIKE_THIS_NEVER);
|
||||
if (!CastleManager.getInstance().getCastleById(CASTLE).getSiege().isInProgress())
|
||||
{
|
||||
final L2Npc cube = addSpawn(TELEPORT_CUBE, CUBE, false, 0);
|
||||
startQuestTimer("cube_despawn", 120000, cube, null);
|
||||
}
|
||||
cancelQuestTimer("raid_check", npc, null);
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alters the Venom location
|
||||
* @param loc enum
|
||||
*/
|
||||
private void changeLocation(MoveTo loc)
|
||||
{
|
||||
switch (loc)
|
||||
{
|
||||
case THRONE:
|
||||
{
|
||||
_venom.teleToLocation(TRHONE, false);
|
||||
break;
|
||||
}
|
||||
case PRISON:
|
||||
{
|
||||
if ((_venom == null) || _venom.isDead() || _venom.isDecayed())
|
||||
{
|
||||
_venom = addSpawn(VENOM, DUNGEON, false, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_venom.teleToLocation(DUNGEON, false);
|
||||
}
|
||||
cancelQuestTimer("raid_check", _venom, null);
|
||||
cancelQuestTimer("tower_check", _venom, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_loc.setLocation(_venom.getLocation());
|
||||
}
|
||||
|
||||
private void teleportTarget(L2PcInstance player)
|
||||
{
|
||||
if ((player != null) && !player.isDead())
|
||||
{
|
||||
final int rnd = getRandom(11);
|
||||
player.teleToLocation(TARGET_TELEPORTS[rnd], TARGET_TELEPORTS_OFFSET[rnd]);
|
||||
player.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if Venom is Alive or Dead
|
||||
* @return status
|
||||
*/
|
||||
private int checkStatus()
|
||||
{
|
||||
int checkStatus = ALIVE;
|
||||
if (GlobalVariablesManager.getInstance().hasVariable("VenomStatus"))
|
||||
{
|
||||
checkStatus = GlobalVariablesManager.getInstance().getInt("VenomStatus");
|
||||
}
|
||||
else
|
||||
{
|
||||
GlobalVariablesManager.getInstance().set("VenomStatus", 0);
|
||||
}
|
||||
return checkStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Venom status
|
||||
* @param status the new status. 0 = ALIVE, 1 = DEAD.
|
||||
*/
|
||||
private void updateStatus(int status)
|
||||
{
|
||||
GlobalVariablesManager.getInstance().set("VenomStatus", Integer.toString(status));
|
||||
}
|
||||
|
||||
private enum MoveTo
|
||||
{
|
||||
THRONE,
|
||||
PRISON
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Venom();
|
||||
}
|
||||
}
|
||||
55
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/WindVortex.java
vendored
Normal file
55
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/WindVortex.java
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.individual;
|
||||
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* @author Stayway
|
||||
*/
|
||||
final class WindVortex extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int WIND_VORTEX = 23417;
|
||||
private static final int GIANT_WINDIMA = 23419;
|
||||
private static final int IMMENSE_WINDIMA = 23420;
|
||||
|
||||
private WindVortex()
|
||||
{
|
||||
super(WindVortex.class.getSimpleName(), "ai/individual");
|
||||
addKillId(WIND_VORTEX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
final L2Npc newSpawn = addSpawn(getRandomBoolean() ? IMMENSE_WINDIMA : GIANT_WINDIMA, npc.getLocation(), false, 300000); // 5 minute despawn time
|
||||
addAttackDesire(newSpawn, killer);
|
||||
showOnScreenMsg(killer, NpcStringId.A_POWERFUL_MONSTER_HAS_COME_TO_FACE_YOU, ExShowScreenMessage.TOP_CENTER, 4500);
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new WindVortex();
|
||||
}
|
||||
}
|
||||
13
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/documentation.txt
vendored
Normal file
13
L2J_Mobius_Test/dist/game/data/scripts/ai/individual/documentation.txt
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
Individual AI:
|
||||
This folder contains AI scripts for single npc templates (one npc ID, but possibly many instances).
|
||||
That is, if a particular NPC/mob has a unique AI or something slightly different from all other generic NPCs,
|
||||
an individual AI script can be created for all occurences of that npc/mob. Such individual scripts ought to be here.
|
||||
|
||||
Individual AI scripts can be subclassed. In other words, an individual may inherit from a group or other individual.
|
||||
For example, one group template might define mobs that cast spells. A particular mob may cast spells but may also
|
||||
talk whenever it gets attacked. In that case, instead of writing all the AI for attacking and casting spells, it may
|
||||
inherit from a group template that defines AI for ALL mobs that cast spells, then add behaviours for talking onAttack.
|
||||
|
||||
"NPC registrations" refers to the addition of NPCs in the various events of the scripts, such as onAttack, onKill, etc
|
||||
Those are done by using keywords such as "addKillId" etc. For more details on registrations, see
|
||||
"scripts/quests/documentation.txt"
|
||||
5
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Acateo/33905-1.html
vendored
Normal file
5
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Acateo/33905-1.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Acateo:<br>
|
||||
So you've joined the Academy! Here, this Academy Circlet will be useful to you.<br>
|
||||
Don't thank me too much. Ho ho!<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Acateo give_circlet">"Uh, sure?"</Button>
|
||||
</body></html>
|
||||
4
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Acateo/33905-2.html
vendored
Normal file
4
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Acateo/33905-2.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Acateo:<br>
|
||||
Good! Put on your Academy Circlet and take off for adventures.<br>
|
||||
Now that you've joined the Academy, don't be shy about asking for help from your clan members. In fact, if you don't have a Mentor yet, ask a clan member to be one and you'll reap even greater benefits!
|
||||
</body></html>
|
||||
3
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Acateo/33905-3.html
vendored
Normal file
3
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Acateo/33905-3.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Acateo:<br>
|
||||
You already have an Academy Circlet, don't you?
|
||||
</body></html>
|
||||
7
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Acateo/33905.html
vendored
Normal file
7
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Acateo/33905.html
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<html><body>Acateo:<br>
|
||||
Greetings friend, my name is Acateo.<br>
|
||||
Pray tell, have you heard of the Academy? Please, Allow me to educate you on what we have to offer.<br>
|
||||
First, characters who join the Academy receive an additional 10% XP until they graduate. Second, if you use the mentoring system while in the Academy, the number of Mentee Marks given to the mentee increases. Lastly, when academy members of level 40 or above level up, they receive additional clan fame points.<br>
|
||||
Someone of your stature must appreciate what the Academy has to offer.<br>
|
||||
Spread the word and direct anyone who wishes to join to me. Each person who joins the Academy receives a welcoming gift of Academy Circlets.<br>
|
||||
</body></html>
|
||||
68
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Acateo/Acateo.java
vendored
Normal file
68
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Acateo/Acateo.java
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.npc.Acateo;
|
||||
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Acateo AI.
|
||||
* @author Gladicek
|
||||
*/
|
||||
final class Acateo extends AbstractNpcAI
|
||||
{
|
||||
// NPC
|
||||
private static final int ACATEO = 33905;
|
||||
// Item
|
||||
private static final int ACADEMY_CIRCLET = 8181;
|
||||
|
||||
private Acateo()
|
||||
{
|
||||
super(Acateo.class.getSimpleName(), "ai/npc");
|
||||
addStartNpc(ACATEO);
|
||||
addFirstTalkId(ACATEO);
|
||||
addTalkId(ACATEO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equals("give_circlet"))
|
||||
{
|
||||
if (hasQuestItems(player, ACADEMY_CIRCLET))
|
||||
{
|
||||
return "33905-3.html";
|
||||
}
|
||||
giveItems(player, ACADEMY_CIRCLET, 1);
|
||||
return "33905-2.html";
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFirstTalk(L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
return player.isAcademyMember() ? "33905-1.html" : "33905.html";
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Acateo();
|
||||
}
|
||||
}
|
||||
10
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/32327.html
vendored
Normal file
10
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/32327.html
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<html><body>Adventurers' Guide:<br>
|
||||
Greetings, traveler! How may I be of assistance?<br>
|
||||
My job is to offer what little assistance I can as you charge into all this endless evil and intense fighting!<br>
|
||||
Even now, the monster attacks on this village grow stronger each day; it is only due to your tireless efforts that we have remained safe this long.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide guide-01.html"><font color="LEVEL">"Can I see the list of available buffs?"</font></Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide blessing_list003.html">"I'd like to exchange for a Special Appearance Stone"</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 902">"Here, I have some Steel Door Guild Coins..."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide weakenBreath">"I heard you could weaken Shilen's Breath Lv.3 or above."</Button>
|
||||
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
|
||||
</body></html>
|
||||
10
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/33454.html
vendored
Normal file
10
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/33454.html
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<html><body>Adventurers' Guide:<br>
|
||||
Greetings, traveler! How may I be of assistance?<br>
|
||||
My job is to offer what little assistance I can as you charge into all this endless evil and intense fighting!<br>
|
||||
Even now, the monster attacks on this village grow stronger each day; it is only due to your tireless efforts that we have remained safe this long.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide guide-01.html"><font color="LEVEL">"Can I see the list of available buffs?"</font></Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_link blessing_list003.html">"I’d like to exchange for a Special Appearance Stone"</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 902">"Here, I have some Steel Door Guild Coins..."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide weakenBreath">"I heard you could weaken Shilen's Breath Lv.3 or above."</Button>
|
||||
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
|
||||
</body></html>
|
||||
10
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/33950.html
vendored
Normal file
10
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/33950.html
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<html><body>Adventurers' Guide:<br>
|
||||
Greetings, traveler! How may I be of assistance?<br>
|
||||
My job is to offer what little assistance I can as you charge into all this endless evil and intense fighting!<br>
|
||||
Even now, the monster attacks on this village grow stronger each day; it is only due to your tireless efforts that we have remained safe this long.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide guide-01.html"><font color="LEVEL">"Can I see the list of available buffs?"</font></Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_link blessing_list003.html">"I’d like to exchange for a Special Appearance Stone"</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 902">"Here, I have some Steel Door Guild Coins..."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide weakenBreath">"I heard you could weaken Shilen's Breath Lv.3 or above."</Button>
|
||||
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
|
||||
</body></html>
|
||||
144
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/AdventurersGuide.java
vendored
Normal file
144
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/AdventurersGuide.java
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ai.npc.AdventurersGuide;
|
||||
|
||||
import com.l2jmobius.gameserver.enums.QuestSound;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Adventurers Guide AI.
|
||||
* @author St3eT, Stayway, Mobius
|
||||
*/
|
||||
final class AdventurersGuide extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int[] ADVENTURER_GUIDES =
|
||||
{
|
||||
32327,
|
||||
33454, // Newbie Helper
|
||||
33950, // Apprentice
|
||||
};
|
||||
// Skills
|
||||
private static final SkillHolder BLESS_PROTECTION = new SkillHolder(5182, 1); // Blessing of Protection
|
||||
private static final SkillHolder KNIGHT = new SkillHolder(15648, 1); // Knight's Harmony (Adventurer)
|
||||
private static final SkillHolder WARRIOR = new SkillHolder(15649, 1); // Warrior's Harmony (Adventurer)
|
||||
private static final SkillHolder WIZARD = new SkillHolder(15650, 1); // Wizard's Harmony (Adventurer)
|
||||
private static final SkillHolder[] GROUP_BUFFS =
|
||||
{
|
||||
new SkillHolder(15642, 1), // Horn Melody (Adventurer)
|
||||
new SkillHolder(15643, 1), // Drum Melody (Adventurer)
|
||||
new SkillHolder(15644, 1), // Pipe Organ Melody (Adventurer)
|
||||
new SkillHolder(15645, 1), // Guitar Melody (Adventurer)
|
||||
new SkillHolder(15646, 1), // Harp Melody (Adventurer)
|
||||
new SkillHolder(15647, 1), // Lute Melody (Adventurer)
|
||||
new SkillHolder(15651, 1), // Prevailing Sonata (Adventurer)
|
||||
new SkillHolder(15652, 1), // Daring Sonata (Adventurer)
|
||||
new SkillHolder(15653, 1), // Refreshing Sonata (Adventurer)
|
||||
};
|
||||
|
||||
private AdventurersGuide()
|
||||
{
|
||||
super(AdventurersGuide.class.getSimpleName(), "ai/npc");
|
||||
addStartNpc(ADVENTURER_GUIDES);
|
||||
addTalkId(ADVENTURER_GUIDES);
|
||||
addFirstTalkId(ADVENTURER_GUIDES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
String htmltext = null;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case "blessing_list003.html":
|
||||
case "guide-01.html":
|
||||
case "guide-02.html":
|
||||
case "guide-03.html":
|
||||
case "guide-04.html":
|
||||
{
|
||||
htmltext = event;
|
||||
break;
|
||||
}
|
||||
case "weakenBreath":
|
||||
{
|
||||
if (player.getShilensBreathDebuffLevel() < 3)
|
||||
{
|
||||
htmltext = "guide-noBreath.html";
|
||||
break;
|
||||
}
|
||||
|
||||
player.setShilensBreathDebuffLevel(2);
|
||||
htmltext = ""; // TODO: Any success html?
|
||||
break;
|
||||
}
|
||||
case "knight":
|
||||
{
|
||||
htmltext = applyBuffs(npc, player, KNIGHT.getSkill());
|
||||
break;
|
||||
}
|
||||
case "warrior":
|
||||
{
|
||||
htmltext = applyBuffs(npc, player, WARRIOR.getSkill());
|
||||
break;
|
||||
}
|
||||
case "wizard":
|
||||
{
|
||||
htmltext = applyBuffs(npc, player, WIZARD.getSkill());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return htmltext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFirstTalk(L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
playSound(player, QuestSound.DIALOG_GUIDE_FOR_ADVENTURER_GREETING_1);
|
||||
return npc.getId() + ".html";
|
||||
}
|
||||
|
||||
private String applyBuffs(L2Npc npc, L2PcInstance player, Skill skill)
|
||||
{
|
||||
if (player.getLevel() > 90)
|
||||
{
|
||||
return "guide-noBuffs.html";
|
||||
}
|
||||
|
||||
for (SkillHolder holder : GROUP_BUFFS)
|
||||
{
|
||||
holder.getSkill().applyEffects(npc, player);
|
||||
}
|
||||
skill.applyEffects(npc, player);
|
||||
|
||||
if ((player.getLevel() < 40) && (player.getClassId().level() <= 1))
|
||||
{
|
||||
BLESS_PROTECTION.getSkill().applyEffects(npc, player);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new AdventurersGuide();
|
||||
}
|
||||
}
|
||||
5
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/blessing_list003.html
vendored
Normal file
5
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/blessing_list003.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Adventurer's Guide:<br>
|
||||
You can exchange the Special Appearance Stone Coupon from the L2Store for a variety of Appearance Stones.<br><br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 2066">"I'll trade for a Special Appearance Stone."</Button>
|
||||
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h npc_%objectId%_Quest AdventurersGuide guide-01.html">"Back"</Button>
|
||||
</body></html>
|
||||
10
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/guide-01.html
vendored
Normal file
10
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/guide-01.html
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<html><body>I can offer you the following buffs, if you're below Lv. 91.<br>
|
||||
Horn Melody / Drum Melody / Pipe Organ Melody<br1>
|
||||
Guitar Melody / Harp Melody / Lute Melody<br1>
|
||||
Prevailing Sonata / Daring Sonata / Refreshing Sonata<br1>
|
||||
You can receive the above buffs as a group.<br>
|
||||
For Knight's Harmony / Warrior's Harmony / Wizard's Harmony, you will have to choose one.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide knight">"I want the Knight's Harmony."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide warrior">"Warrior's Harmony, please."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide wizard">"Wizard's Harmony, of course!"</Button>
|
||||
</body></html>
|
||||
5
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/guide-02.html
vendored
Normal file
5
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/guide-02.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>The Steel Door Guild tops all Dwarven guilds in power and prestige. As such, it is our duty to aid adventurers who work to restore peace unto this war-torn land. We will be happy to offer special assistance if you have Steel Door Guild Coins.<br>
|
||||
Well?<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide guide-03.html">"How do I use Steel Door Guild Coins?"</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest AdventurersGuide guide-04.html">"Here, I have some Steel Door Guild Coins..."</Button>
|
||||
</body></html>
|
||||
4
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/guide-03.html
vendored
Normal file
4
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/guide-03.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>You can use Steel Door Guild Coins to purchase <font color="LEVEL">weapons, armor, and accessories of each grade</font>. These items may be restricted in terms of augmentations or attribute options, but they will be more than enough to help you on your journey.<br>
|
||||
Once you outgrow the equipment, <font color="LEVEL">you can trade them back for Steel Door Guild Coins again</font>! You can also invest in the Aden Reconstruction project if it suits your fancy, or even gamble. Don't forget that Steel Weapon Packs and Steel Armor Packs have a chance of yielding Requiem, Apocalypse, or Specter equipment!<br>
|
||||
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h npc_%objectId%_Quest AdventurersGuide guide-02.html">Back</Button>
|
||||
</body></html>
|
||||
13
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/guide-04.html
vendored
Normal file
13
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/guide-04.html
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<html><body>You can use Steel Door Guild Coins to receive equipment, and trade them back for coins again. Just remember, <font color="LEVEL">you cannot bring us junk to exchange for coins!</font><br>
|
||||
So, what would you like to do?<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 893">"I'd like a weapon or a shield / Sigil."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 894">"I want to buy a top."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 895">"I am looking for some pants."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 896">"Do you have any good helmets?"</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 897">"Gloves would be nice."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 898">"Give me the best boots you got."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 899">"Can I take a look at your necklaces?"</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 900">"I'm up for a ring..."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 901">"I want some earrings."</Button>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_exc_multisell 903">"I want to return my Steel equipment."</Button>
|
||||
</body></html>
|
||||
3
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/guide-noBreath.html
vendored
Normal file
3
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/guide-noBreath.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>I can only weaken Shilen's Breath Lv. 3 or above.<br>
|
||||
There is nothing I can do for you.
|
||||
</body></html>
|
||||
2
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/guide-noBuffs.html
vendored
Normal file
2
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/AdventurersGuide/guide-noBuffs.html
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
<html><body>Characters who are Lv. 91 or above cannot receive Newbie Buffs.
|
||||
</body></html>
|
||||
4
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Alarm/32367-01.html
vendored
Normal file
4
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Alarm/32367-01.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Alarm System:<br>
|
||||
As the alarm rings, a window for the passcode pops up. On the screen you see the number 120, which begins counting down. It looks like the alarm system will be activated in about 2 minutes unless the passcode is successfully entered.<br>
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 2">Enter the passcode.</Button>
|
||||
</body></html>
|
||||
4
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Alarm/32367-02.html
vendored
Normal file
4
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Alarm/32367-02.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Alarm System:<br>
|
||||
The alarm is ringing loudly. You should leave here immediately.<br>
|
||||
(Another person has already undertaken the quest.)
|
||||
</body></html>
|
||||
42
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Alarm/32367-184_02.html
vendored
Normal file
42
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Alarm/32367-184_02.html
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<html><body>Alarm System:<br>
|
||||
########################<br>
|
||||
Enter the passcode for communication.<br>
|
||||
Passcode :|<br>
|
||||
########################<br>
|
||||
The first number is...
|
||||
<table border="0" border color="white" width="65" height="65">
|
||||
<tr>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_04.html">1</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_04.html">2</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 3">3</Button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_04.html">4</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_04.html">5</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_04.html">6</Button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_04.html">7</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_04.html">8</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_04.html">9</Button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body></html>
|
||||
42
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Alarm/32367-184_04.html
vendored
Normal file
42
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Alarm/32367-184_04.html
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<html><body>Alarm System:<br>
|
||||
########################<br>
|
||||
Enter the passcode for communication.<br>
|
||||
Passcode : *|<br>
|
||||
########################<br>
|
||||
The second number is...
|
||||
<table border="0" border color="white" width="65" height="65">
|
||||
<tr>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 4">1</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_06.html">2</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_06.html">3</Button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_06.html">4</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_06.html">5</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_06.html">6</Button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_06.html">7</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_06.html">8</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_06.html">9</Button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body></html>
|
||||
42
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Alarm/32367-184_06.html
vendored
Normal file
42
L2J_Mobius_Test/dist/game/data/scripts/ai/npc/Alarm/32367-184_06.html
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<html><body>Alarm System:<br>
|
||||
########################<br>
|
||||
Enter the passcode for communication.<br>
|
||||
Passcode : **|<br>
|
||||
########################<br>
|
||||
The third number is...
|
||||
<table border="0" border color="white" width="65" height="65">
|
||||
<tr>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_08.html">1</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_08.html">2</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_08.html">3</Button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_08.html">4</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_08.html">5</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_08.html">6</Button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_08.html">7</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 32367-184_08.html">8</Button>
|
||||
</td>
|
||||
<td width="20" height="20" align="center">
|
||||
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Alarm 5">9</Button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body></html>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user