/* * 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 . */ package instances.Kimerian; import com.l2jmobius.gameserver.enums.CategoryType; import com.l2jmobius.gameserver.enums.ChatType; 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.L2MonsterInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureDeath; import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureSee; import com.l2jmobius.gameserver.model.holders.SkillHolder; import com.l2jmobius.gameserver.model.instancezone.Instance; import com.l2jmobius.gameserver.network.NpcStringId; import com.l2jmobius.gameserver.util.Util; import instances.AbstractInstance; /** * Kimerian Common instance zone. * @author St3eT, Gladicek */ public final class KimerianCommon extends AbstractInstance { // NPCs private static final int KIMERIAN = 25745; private static final int KIMERIAN_GHOST = 25746; private static final int KIMERIAN_DEAD = 25747; private static final int NOETI_KASHERON = 32896; private static final int NOETI_KASHERON_ENTRANCE = 33098; private static final int NOETI_KASHERON_LEAVE = 33131; private static final int NEOMI_KASHERON = 32914; private static final int FAIRY_REBEL = 32913; private static final int INVISIBLE_NPC = 33137; private static final int KIMERIAN_HOLLOW = 25745; private static final int KIMERIAN_HOLLOW_2 = 25746; private static final int FAIRY_WARRIOR = 25735; private static final int SATYR_WITCH = 25740; private static final int FAIRY_ROGUE = 25736; // Skills private static final SkillHolder INVUL_SKILL = new SkillHolder(14190, 1); // Items private static final int GLIMMER = 17374; private static final int FLUTE = 17378; // Fairy's Leaf Flute // Misc private static final NpcStringId[] KIMERIAN_MSG = { NpcStringId.THEY_ARE_ROOKIE_REBELLIONS, NpcStringId.RESISTANCE_UNDERLINGS, NpcStringId.TREASON_IS_PUNISHABLE_BY_DEATH, NpcStringId.WHO_DO_YOU_THINK_YOU_ARE_TO_TRY_MY_AUTHORITY, }; private static final int TEMPLATE_ID = 161; public KimerianCommon() { addStartNpc(NOETI_KASHERON); addTalkId(NOETI_KASHERON, NOETI_KASHERON_ENTRANCE); addFirstTalkId(NOETI_KASHERON_ENTRANCE, NOETI_KASHERON_LEAVE); addSpawnId(FAIRY_REBEL, NEOMI_KASHERON, INVISIBLE_NPC, KIMERIAN); addAttackId(KIMERIAN); addKillId(KIMERIAN_GHOST, KIMERIAN); setCreatureSeeId(this::onCreatureSee, FAIRY_REBEL, NEOMI_KASHERON, INVISIBLE_NPC, KIMERIAN); setCreatureKillId(this::onCreatureKill, FAIRY_REBEL, NEOMI_KASHERON); } @Override public void onTimerEvent(String event, StatsSet params, L2Npc npc, L2PcInstance player) { final Instance instance = npc.getInstanceWorld(); if (isKimerianInstance(instance)) { switch (event) { case "HELPER_TIME_ACTION": { player = npc.getVariables().getObject("PC_INSTANCE", L2PcInstance.class); if (player != null) { final double distance = npc.calculateDistance(player, false, false); if (distance > 1000) { npc.teleToLocation(new Location(player.getX() + getRandom(-100, 100), player.getY() + getRandom(-100, 100), player.getZ() + 50)); } else if (!npc.isAttackingNow() && (distance > 250)) { npc.setIsRunning(true); addMoveToDesire(npc, new Location(player.getX() + getRandom(-100, 100), player.getY() + getRandom(-100, 100), player.getZ() + 50), 23); } else if (!npc.isInCombat() || !npc.isAttackingNow() || (npc.getTarget() == null)) { final L2Character monster = (L2Character) player.getTarget(); if ((monster != null) && (monster instanceof L2MonsterInstance) && player.isInCombat()) { addAttackDesire(npc, monster); } } } else { getTimers().cancelTimersOf(npc); } break; } case "KIMERIAN_INVUL_END": { if (npc.getVariables().getBoolean("INVUL_CAN_BE_CANCELLED", true)) { npc.getVariables().set("INVUL_CAN_BE_CANCELLED", false); npc.getEffectList().stopSkillEffects(true, INVUL_SKILL.getSkillId()); npc.disableCoreAI(false); npc.setTargetable(true); addAttackPlayerDesire(npc, player, 23); } break; } } } } @Override public String onAdvEvent(String event, L2Npc npc, L2PcInstance player) { String htmltext = null; final Instance instance = npc.getInstanceWorld(); if (isKimerianInstance(instance)) { switch (event) { case "giveFlute": { if (npc.getVariables().getBoolean("CAN_SPAWN_SUPPORT", true)) { if (hasQuestItems(player, FLUTE)) { if (player.isInCategory(CategoryType.AEORE_GROUP)) { addSpawn(FAIRY_REBEL, player.getX() + 60, player.getY(), player.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_REBEL, player.getX() - 60, player.getY(), player.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_REBEL, player.getX(), player.getY() + 60, player.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_REBEL, player.getX(), player.getY() - 60, player.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_REBEL, player.getX() + 120, player.getY(), player.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_REBEL, player.getX() - 120, player.getY(), player.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_REBEL, player.getX(), player.getY() + 120, player.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_REBEL, player.getX(), player.getY() - 120, player.getZ(), 0, false, 0, false, instance.getId()); takeItems(player, FLUTE, 1); npc.getVariables().set("CAN_SPAWN_SUPPORT", false); } else { addSpawn(FAIRY_REBEL, player.getX() + 60, player.getY(), player.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_REBEL, player.getX() - 60, player.getY(), player.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_REBEL, player.getX(), player.getY() + 60, player.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_REBEL, player.getX(), player.getY() - 60, player.getZ(), 0, false, 0, false, instance.getId()); takeItems(player, FLUTE, 1); npc.getVariables().set("CAN_SPAWN_SUPPORT", false); } } else { htmltext = "33098-02.html"; } } else { htmltext = "33098-03.html"; } break; } case "zdrhamCus": { instance.destroy(); break; } } } else if (instance == null) { if (event.equals("enterInstance")) { enterInstance(player, npc, TEMPLATE_ID); } } return htmltext; } @Override public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon) { final Instance instance = npc.getInstanceWorld(); if (isKimerianInstance(instance)) { if (npc.getId() == KIMERIAN) { if ((npc.getCurrentHpPercent() <= 50) && npc.getVariables().getBoolean("CAN_ACTIVATE_INVUL", true)) { npc.getVariables().set("CAN_ACTIVATE_INVUL", false); npc.setTargetable(false); npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.PHANTOM_IMAGE); getTimers().addRepeatingTimer("KIMERIAN_INVUL_END", 60000, npc, player); for (int i = 0; i < 5; i++) { final L2Npc ghost = addSpawn(KIMERIAN_GHOST, npc.getX(), npc.getY(), npc.getZ(), Util.calculateHeadingFrom(npc, player), false, 0, false, instance.getId()); addAttackPlayerDesire(ghost, player, 23); } npc.disableCoreAI(true); npc.breakAttack(); npc.breakCast(); ((L2Attackable) npc).clearAggroList(); getTimers().addTimer("KIMERIAN_INVUL_START", 6000, n -> { addSkillCastDesire(npc, npc, INVUL_SKILL, 23); npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.FOOLISH_INSIGNIFICANT_CREATURES_HOW_DARE_YOU_CHALLENGE_ME); }); } } } return super.onAttack(npc, player, damage, isSummon); } @Override public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) { final Instance instance = npc.getInstanceWorld(); if (isKimerianInstance(instance)) { switch (npc.getId()) { case KIMERIAN_GHOST: { final int killedCount = instance.getParameters().getInt("GHOST_KILLED_COUNT", 0) + 1; instance.getParameters().set("GHOST_KILLED_COUNT", killedCount); if (killedCount >= 5) { onTimerEvent("KIMERIAN_INVUL_END", null, npc, killer); } break; } case KIMERIAN: { instance.finishInstance(5); final L2Npc kimerian = addSpawn(KIMERIAN_DEAD, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0, false, instance.getId()); final Location loc = Util.getRandomPosition(kimerian, 500, 500); kimerian.setInvisible(true); playSound(killer, "RM01_S"); getTimers().addTimer("KIMERIAN_VISIBLE", 4000, t -> kimerian.setInvisible(false)); getTimers().addTimer("KIMERIAN_CHAT_1", 5000, t -> kimerian.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.I_WILL_COME_BACK_ALIVE_WITH_ROTTING_AURA)); getTimers().addTimer("KIMERIAN_RUN", 6000, t -> { kimerian.setIsRunning(true); addMoveToDesire(kimerian, loc, 23); kimerian.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.HA_HA_HA_HA); }); getTimers().addTimer("KIMERIAN_SPAWN_DEFKA", 7000, t -> { kimerian.deleteMe(); final L2Npc noeti = addSpawn(NOETI_KASHERON_LEAVE, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0, false, instance.getId()); getTimers().addTimer("NOETI_SAY2", 3000, n -> noeti.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.UNFORTUNATELY_THEY_RAN_AWAY)); }); break; } } } return super.onKill(npc, killer, isSummon); } public void onCreatureKill(OnCreatureDeath event) { final L2Npc npc = (L2Npc) event.getTarget(); final Instance instance = npc.getInstanceWorld(); if (isKimerianInstance(instance)) { getTimers().cancelTimersOf(npc); } } @Override public String onSpawn(L2Npc npc) { final Instance instance = npc.getInstanceWorld(); if (isKimerianInstance(instance)) { switch (npc.getId()) { case FAIRY_REBEL: case NEOMI_KASHERON: { npc.initSeenCreatures(); npc.setIsRunning(true); break; } case INVISIBLE_NPC: case KIMERIAN: { npc.initSeenCreatures(); break; } } } return super.onSpawn(npc); } @Override public String onFirstTalk(L2Npc npc, L2PcInstance player) { String htmltext = null; switch (npc.getId()) { case NOETI_KASHERON_ENTRANCE: { if (npc.getVariables().getBoolean("CAN_GET_GLIMMER", true)) { giveItems(player, GLIMMER, 10); npc.getVariables().set("CAN_GET_GLIMMER", false); } htmltext = "33098-01.html"; break; } case NOETI_KASHERON_LEAVE: { htmltext = " 33131-01.html"; break; } } return htmltext; } public void onCreatureSee(OnCreatureSee event) { final L2Character creature = event.getSeen(); final L2Npc npc = (L2Npc) event.getSeer(); final StatsSet npcParams = npc.getParameters(); final StatsSet npcVars = npc.getVariables(); final Instance instance = npc.getInstanceWorld(); if (isKimerianInstance(instance)) { switch (npc.getId()) { case FAIRY_REBEL: case NEOMI_KASHERON: { if (creature.isPlayer() && (npcVars.getObject("PC_INSTANCE", L2PcInstance.class) == null)) { npcVars.set("PC_INSTANCE", creature.getActingPlayer()); getTimers().addRepeatingTimer("HELPER_TIME_ACTION", 2000, npc, null); } break; } case INVISIBLE_NPC: { final int hollow = npcParams.getInt("hollow", -1); final int trap = npcParams.getInt("trap", -1); if (creature.isPlayer() && npc.isScriptValue(0)) { if (hollow == 1) { spawnHollow(npc, creature.getActingPlayer(), true); } else { switch (trap) { case 1: { spawnHollow(npc, creature.getActingPlayer(), false); addSpawn(FAIRY_WARRIOR, npc.getX() + 80, npc.getY(), npc.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_WARRIOR, npc.getX(), npc.getY() + 80, npc.getZ(), 0, false, 0, false, instance.getId()); addSpawn(SATYR_WITCH, npc.getX() + 50, npc.getY() + 50, npc.getZ(), 0, false, 0, false, instance.getId()); break; } case 2: { spawnHollow(npc, creature.getActingPlayer(), false); addSpawn(SATYR_WITCH, npc.getX() + 80, npc.getY(), npc.getZ(), 0, false, 0, false, instance.getId()); addSpawn(SATYR_WITCH, npc.getX(), npc.getY() + 80, npc.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_ROGUE, npc.getX() + 50, npc.getY() + 50, npc.getZ(), 0, false, 0, false, instance.getId()); break; } case 3: { spawnHollow(npc, creature.getActingPlayer(), false); addSpawn(FAIRY_WARRIOR, npc.getX() + 80, npc.getY(), npc.getZ(), 0, false, 0, false, instance.getId()); addSpawn(SATYR_WITCH, npc.getX(), npc.getY() + 80, npc.getZ(), 0, false, 0, false, instance.getId()); addSpawn(FAIRY_ROGUE, npc.getX() + 50, npc.getY() + 50, npc.getZ(), 0, false, 0, false, instance.getId()); break; } } } } break; } case KIMERIAN: { if (creature.isPlayer() && npcVars.getBoolean("FIGHT_CAN_START", true)) { npc.broadcastSay(ChatType.NPC_GENERAL, KIMERIAN_MSG[getRandom(KIMERIAN_MSG.length)]); addAttackPlayerDesire(npc, creature.getActingPlayer(), 23); npcVars.set("FIGHT_CAN_START", false); } break; } } } } private void spawnHollow(L2Npc npc, L2PcInstance player, boolean isHollow) { final Instance instance = npc.getInstanceWorld(); if (isKimerianInstance(instance)) { if (isHollow) { final L2Npc kimerian = addSpawn(KIMERIAN_HOLLOW, npc.getX(), npc.getY(), npc.getZ(), Util.calculateHeadingFrom(npc, player), false, 0, false, instance.getId()); kimerian.setTargetable(false); kimerian.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.HOW_RIDICULOUS_YOU_THINK_YOU_CAN_FIND_ME); getTimers().addTimer("KIMERIAN_HOLLOW_SAY_2", 3000, n -> kimerian.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.THEN_TRY_HA_HA_HA)); getTimers().addTimer("KIMERIAN_HOLLOW_DELETE", 6000, n -> kimerian.deleteMe()); } else { final L2Npc kimerian = addSpawn(KIMERIAN_HOLLOW_2, npc.getX(), npc.getY(), npc.getZ(), Util.calculateHeadingFrom(npc, player), false, 0, false, instance.getId()); kimerian.setTargetable(false); kimerian.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.YOU_RE_STILL_TRYING); getTimers().addTimer("KIMERIAN_HOLLOW_SAY_2", 3000, n -> kimerian.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.HA_HA_HA_HA)); getTimers().addTimer("KIMERIAN_HOLLOW_DELETE", 6000, n -> kimerian.deleteMe()); } npc.setScriptValue(1); } } private boolean isKimerianInstance(Instance instance) { return ((instance != null) && (instance.getTemplateId() == TEMPLATE_ID)); } public static void main(String[] args) { new KimerianCommon(); } }