Organized boss scripts to separate folder.

This commit is contained in:
MobiusDev
2016-12-16 10:59:46 +00:00
parent 3afe0d648b
commit 294f0cc600
124 changed files with 69 additions and 54 deletions

View File

@@ -33,7 +33,7 @@ import ai.AbstractNpcAI;
* Lindvior Scene AI.
* @author nonom
*/
public final class Lindvior extends AbstractNpcAI
public final class LindviorScene extends AbstractNpcAI
{
private static final int LINDVIOR_CAMERA = 18669;
private static final int TOMARIS = 32552;
@@ -51,7 +51,7 @@ public final class Lindvior extends AbstractNpcAI
private L2Npc _tomaris = null;
private L2Npc _artius = null;
public Lindvior()
public LindviorScene()
{
scheduleNextLindviorVisit();
}
@@ -135,6 +135,6 @@ public final class Lindvior extends AbstractNpcAI
public static void main(String[] args)
{
new Lindvior();
new LindviorScene();
}
}

View File

@@ -14,7 +14,7 @@
* 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.areas.MonasteryOfSilence;
package ai.bosses.Anais;
import java.util.ArrayList;
@@ -159,10 +159,6 @@ public final class Anais extends AbstractNpcAI
return super.onAttack(npc, attacker, damage, isSummon);
}
/*
* (non-Javadoc)
* @see com.l2jmobius.gameserver.model.quest.Quest#onSpawn(com.l2jmobius.gameserver.model.actor.L2Npc)
*/
@Override
public String onSpawn(L2Npc npc)
{

View File

@@ -14,7 +14,7 @@
* 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.areas.LairOfAntharas.Antharas;
package ai.bosses.Antharas;
import java.util.HashMap;
import java.util.List;

View File

@@ -14,7 +14,7 @@
* 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.areas.TowerOfInsolence.Baium;
package ai.bosses.Baium;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.CommonUtil;

View File

@@ -0,0 +1,333 @@
/*
* 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.bosses.Baylor;
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.L2DoorInstance;
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.model.skills.Skill;
import instances.AbstractInstance;
/**
* Baylor Warzone instance zone.
* @author St3eT
*/
public final class BaylorWarzone extends AbstractInstance
{
// NPCs
private static final int BAYLOR = 29213;
private static final int PRISON_GUARD = 29104;
private static final int ENTRANCE_PORTAL = 33523;
private static final int INVISIBLE_NPC_1 = 29106;
private static final int INVISIBLE_NPC_2 = 29108;
private static final int INVISIBLE_NPC_3 = 29109;
// Skills
private static final SkillHolder INVIS_NPC_SOCIAL_SKILL = new SkillHolder(5401, 1);
private static final SkillHolder BAYLOR_SOCIAL_SKILL = new SkillHolder(5402, 1);
// Locations
private static final Location BATTLE_PORT = new Location(153567, 143319, -12736);
// Misc
private static final int TEMPLATE_ID = 166;
public BaylorWarzone()
{
super(TEMPLATE_ID);
addStartNpc(ENTRANCE_PORTAL);
addTalkId(ENTRANCE_PORTAL);
addInstanceCreatedId(TEMPLATE_ID);
addSpawnId(INVISIBLE_NPC_1);
addSpellFinishedId(INVISIBLE_NPC_1);
setCreatureSeeId(this::onCreatureSee, INVISIBLE_NPC_1);
setCreatureKillId(this::onBossKill, BAYLOR);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("enterInstance"))
{
enterInstance(player, npc, TEMPLATE_ID);
}
return super.onAdvEvent(event, npc, player);
}
@Override
public void onTimerEvent(String event, StatsSet params, L2Npc npc, L2PcInstance player)
{
final Instance world = npc.getInstanceWorld();
if (isInInstance(world))
{
switch (event)
{
case "START_SCENE_01":
{
specialCamera(world, npc, 2300, 0, 90, 2000, 3000, 2500, 0, 180, 1, 0, 1);
playSound(world, "BS06_A");
getTimers().addTimer("START_SCENE_02", 2000, npc, null);
break;
}
case "START_SCENE_02":
{
specialCamera(world, npc, 10, 180, 0, 17000, 3000, 30000, 0, 20, 1, 0, 0);
getTimers().addTimer("START_SCENE_03", 17000, npc, null);
break;
}
case "START_SCENE_03":
{
specialCamera(world, npc, 15, 15, 0, 6000, 3000, 9000, 0, 10, 1, 0, 0);
getTimers().addTimer("START_SCENE_04", 6000, npc, null);
break;
}
case "START_SCENE_04":
{
specialCamera(world, npc, 5, 200, 0, 6000, 3000, 9000, 0, 10, 1, 0, 0);
getTimers().addTimer("START_SCENE_05", 6000, npc, null);
break;
}
case "START_SCENE_05":
{
specialCamera(world, npc, 5, 70, 0, 4000, 3000, 9000, 0, 10, 1, 0, 0);
getTimers().addTimer("START_SCENE_06", 4000, npc, null);
break;
}
case "START_SCENE_06":
{
specialCamera(world, npc, 200, 60, 0, 1000, 3000, 4000, 0, 6, 1, 0, 0);
getTimers().addTimer("START_SCENE_07", 1000, npc, null);
break;
}
case "START_SCENE_07":
{
specialCamera(world, npc, 500, 260, 0, 8000, 3000, 9000, 0, 10, 1, 0, 0);
getTimers().addTimer("SPAWN_GUARD_1", 100, e -> world.spawnGroup("PRISON_GUARD_GROUP_1"));
getTimers().addTimer("SPAWN_GUARD_2", 2100, e -> world.spawnGroup("PRISON_GUARD_GROUP_2"));
getTimers().addTimer("SPAWN_GUARD_3", 4100, e -> world.spawnGroup("PRISON_GUARD_GROUP_3"));
getTimers().addTimer("SPAWN_GUARD_4", 6100, e -> world.spawnGroup("PRISON_GUARD_GROUP_4"));
getTimers().addTimer("START_SCENE_08", 8000, npc, null);
break;
}
case "START_SCENE_08":
{
specialCamera(world, npc, 850, 260, 70, 2000, 3000, 5000, 0, 0, 1, 0, 0);
getTimers().addTimer("START_SCENE_09", 2000, npc, null);
break;
}
case "START_SCENE_09":
{
specialCamera(world, npc, 0, 260, 70, 1800, 3000, 2000, 0, 0, 1, 0, 0);
getTimers().addTimer("START_SCENE_10", 1800, npc, null);
getTimers().addTimer("START_SCENE_12", 1000, npc, null);
break;
}
case "START_SCENE_10":
{
specialCamera(world, npc, 200, 20, 0, 100, 3000, 5000, 160, 15, 1, 0, 0);
getTimers().addTimer("START_SCENE_11", 2000, npc, null);
break;
}
case "START_SCENE_11":
{
specialCamera(world, npc, 100, 20, 0, 4000, 3000, 7000, 160, 10, 1, 0, 0);
getTimers().addTimer("START_SCENE_14", 6500, npc, null);
break;
}
case "START_SCENE_12":
{
int count = 0;
for (L2Npc baylor : world.spawnGroup("BAYLOR"))
{
baylor.getVariables().set("is_after_you", count);
baylor.disableCoreAI(true);
baylor.setRandomAnimation(false);
baylor.setRandomWalking(false);
((L2Attackable) baylor).setCanReturnToSpawnPoint(false);
count++;
}
getTimers().addTimer("START_SCENE_13", 300, npc, null);
break;
}
case "START_SCENE_13":
{
world.getAliveNpcs(BAYLOR).forEach(baylor ->
{
getTimers().addTimer("BAYLOR_SOCIAL_SKILL", (baylor.getVariables().getInt("is_after_you") == 0 ? 14 : 16) * 1000, baylor, null);
broadcastSocialAction(baylor, 1);
});
break;
}
case "START_SCENE_14":
{
world.getAliveNpcs(INVISIBLE_NPC_3).forEach(invisNpc ->
{
specialCamera(world, invisNpc, 45, 237, 0, 0, 3000, 5000, 0, 27, 1, 0, 1);
getTimers().addTimer("START_SCENE_15", 1500, invisNpc, null);
});
world.getAliveNpcs(PRISON_GUARD).forEach(guard ->
{
final int random = getRandom(100);
if (random >= 20)
{
broadcastSocialAction(guard, 2);
}
else if (random >= 40)
{
getTimers().addTimer("SOCIAL_ACTION", 250, e -> broadcastSocialAction(guard, 2));
}
else if (random >= 60)
{
getTimers().addTimer("SOCIAL_ACTION", 500, e -> broadcastSocialAction(guard, 2));
}
else if (random >= 80)
{
getTimers().addTimer("SOCIAL_ACTION", 700, e -> broadcastSocialAction(guard, 2));
}
else
{
getTimers().addTimer("SOCIAL_ACTION", 800, e -> broadcastSocialAction(guard, 2));
}
});
break;
}
case "START_SCENE_15":
{
world.getAliveNpcs(INVISIBLE_NPC_3).forEach(invisNpc ->
{
specialCamera(world, invisNpc, 500, 212, 0, 1500, 3000, 3000, 357, 15, 1, 0, 1);
getTimers().addTimer("START_SCENE_16", 1500, invisNpc, null);
});
getTimers().addTimer("NPC_DESPAWN", 3000, e -> npc.deleteMe());
break;
}
case "START_SCENE_16":
{
specialCamera(world, npc, 500, 212, 0, 1000, 3000, 3000, 357, 40, 1, 0, 0);
getTimers().addTimer("START_SCENE_17", 1000, npc, null);
break;
}
case "START_SCENE_17":
{
specialCamera(world, npc, 900, 212, 0, 1000, 3000, 3000, 357, 10, 1, 0, 0);
getTimers().addTimer("START_SCENE_18", 2000, npc, null);
break;
}
case "START_SCENE_18":
{
specialCamera(world, npc, 500, 212, 0, 3000, 3000, 15000, 357, 20, 1, 0, 0);
getTimers().addTimer("START_SCENE_19", 7000, npc, null);
break;
}
case "START_SCENE_19":
{
specialCamera(world, npc, 700, 212, 30, 1000, 7000, 2500, 357, 0, 1, 0, 0);
break;
}
case "BAYLOR_SOCIAL_SKILL":
{
npc.doCast(BAYLOR_SOCIAL_SKILL.getSkill());
npc.disableCoreAI(false);
world.getAliveNpcs(INVISIBLE_NPC_1).forEach(invisNpc -> getTimers().addTimer("INVIS_NPC_SOCIAL_SKILL", 1300, invisNpc, null));
break;
}
case "INVIS_NPC_SOCIAL_SKILL":
{
npc.doCast(INVIS_NPC_SOCIAL_SKILL.getSkill());
break;
}
}
}
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
final Instance world = npc.getInstanceWorld();
if (isInInstance(world))
{
world.getAliveNpcs(INVISIBLE_NPC_1, INVISIBLE_NPC_2, INVISIBLE_NPC_3).forEach(L2Npc::deleteMe);
world.getAliveNpcs(PRISON_GUARD).forEach(guard -> guard.doDie(null));
npc.deleteMe();
}
return super.onSpellFinished(npc, player, skill);
}
@Override
public void onInstanceCreated(Instance instance, L2PcInstance player)
{
getTimers().addTimer("BATTLE_PORT", 3000, e ->
{
instance.getPlayers().forEach(p -> p.teleToLocation(BATTLE_PORT));
instance.getDoors().forEach(L2DoorInstance::closeMe);
});
}
public void onBossKill(OnCreatureDeath event)
{
final L2Npc npc = (L2Npc) event.getTarget();
final Instance world = npc.getInstanceWorld();
if (isInInstance(world))
{
if (world.getAliveNpcs(BAYLOR).isEmpty())
{
world.finishInstance();
}
else
{
world.setReenterTime();
}
}
}
public void onCreatureSee(OnCreatureSee event)
{
final L2Character creature = event.getSeen();
final L2Npc npc = (L2Npc) event.getSeer();
final Instance world = npc.getInstanceWorld();
if (isInInstance(world) && creature.isPlayer() && npc.isScriptValue(0))
{
npc.setScriptValue(1);
getTimers().addTimer("START_SCENE_01", 5000, npc, null);
}
}
@Override
public String onSpawn(L2Npc npc)
{
if (npc.getId() == INVISIBLE_NPC_1)
{
npc.initSeenCreatures();
}
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new BaylorWarzone();
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Crystal Prison Entrance Portal:<br>
You must be in a party to enter.
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Crystal Prison Entrance Portal:<br>
The leader of the party should try to enter.
</body></html>

View File

@@ -14,7 +14,7 @@
* 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.areas.CrumaTower;
package ai.bosses.Core;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

View File

@@ -14,7 +14,7 @@
* 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.areas.FrostLake.FreyasSteward;
package ai.bosses.Freya.FreyasSteward;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Npc;

View File

@@ -0,0 +1,183 @@
/*
* 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.bosses.Freya.IceQueensCastle;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.enums.Movie;
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.L2Character;
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.instancezone.Instance;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.NpcStringId;
import instances.AbstractInstance;
import quests.Q10285_MeetingSirra.Q10285_MeetingSirra;
/**
* Ice Queen's Castle instance zone.
* @author Adry_85
*/
public final class IceQueensCastle extends AbstractInstance
{
// NPCs
private static final int FREYA = 18847;
private static final int BATTALION_LEADER = 18848;
private static final int LEGIONNAIRE = 18849;
private static final int MERCENARY_ARCHER = 18926;
private static final int ARCHERY_KNIGHT = 22767;
private static final int JINIA = 32781;
// Locations
private static final Location FREYA_LOC = new Location(114730, -114805, -11200, 50);
// Skill
private static SkillHolder ETHERNAL_BLIZZARD = new SkillHolder(6276, 1);
// Misc
private static final int TEMPLATE_ID = 137;
public IceQueensCastle()
{
super(TEMPLATE_ID);
addStartNpc(JINIA);
addTalkId(JINIA);
addSeeCreatureId(BATTALION_LEADER, LEGIONNAIRE, MERCENARY_ARCHER);
addSpawnId(FREYA);
addSpellFinishedId(FREYA);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "ATTACK_KNIGHT":
{
L2World.getInstance().forEachVisibleObject(npc, L2Npc.class, mob ->
{
if ((mob.getId() == ARCHERY_KNIGHT) && !mob.isDead() && !mob.isDecayed())
{
npc.setIsRunning(true);
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, mob);
((L2Attackable) npc).addDamageHate(mob, 0, 999999);
}
});
startQuestTimer("ATTACK_KNIGHT", 3000, npc, null);
break;
}
case "TIMER_MOVING":
{
if (npc != null)
{
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, FREYA_LOC);
}
break;
}
case "TIMER_BLIZZARD":
{
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.I_CAN_NO_LONGER_STAND_BY);
npc.stopMove(null);
npc.setTarget(player);
npc.doCast(ETHERNAL_BLIZZARD.getSkill());
break;
}
case "TIMER_SCENE_21":
{
if (npc != null)
{
playMovie(player, Movie.SC_BOSS_FREYA_FORCED_DEFEAT);
npc.deleteMe();
startQuestTimer("TIMER_PC_LEAVE", 24000, npc, player);
}
break;
}
case "TIMER_PC_LEAVE":
{
final QuestState qs = player.getQuestState(Q10285_MeetingSirra.class.getSimpleName());
if (qs != null)
{
qs.setMemoState(3);
qs.setCond(10, true);
finishInstance(player, 0);
}
break;
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onTalk(L2Npc npc, L2PcInstance talker)
{
enterInstance(talker, npc, TEMPLATE_ID);
return super.onTalk(npc, talker);
}
@Override
public final String onSpawn(L2Npc npc)
{
startQuestTimer("TIMER_MOVING", 60000, npc, null);
startQuestTimer("TIMER_BLIZZARD", 180000, npc, null);
return super.onSpawn(npc);
}
@Override
public String onSeeCreature(L2Npc npc, L2Character creature, boolean isSummon)
{
if (creature.isPlayer() && npc.isScriptValue(0))
{
npc.setScriptValue(1);
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.S1_MAY_THE_PROTECTION_OF_THE_GODS_BE_UPON_YOU, creature.getName());
L2World.getInstance().forEachVisibleObject(npc, L2Npc.class, mob ->
{
if ((mob.getId() == ARCHERY_KNIGHT) && !mob.isDead() && !mob.isDecayed())
{
npc.setIsRunning(true);
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, mob);
((L2Attackable) npc).addDamageHate(mob, 0, 999999);
}
});
startQuestTimer("ATTACK_KNIGHT", 5000, npc, null);
}
return super.onSeeCreature(npc, creature, isSummon);
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
final Instance world = npc.getInstanceWorld();
if ((world != null) && (skill == ETHERNAL_BLIZZARD.getSkill()))
{
final L2PcInstance playerInside = world.getFirstPlayer();
if (playerInside != null)
{
startQuestTimer("TIMER_SCENE_21", 1000, npc, playerInside);
}
}
return super.onSpellFinished(npc, player, skill);
}
public static void main(String[] args)
{
new IceQueensCastle();
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Kegor:<br>
I'd entrust your associate with this mission, but..
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Kegor:<br>
Without you, we would have failed. I can't thank you enough.<br>
Freya's last breath will flutter against your blade, I can feel it!<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest IceQueensCastleBattle killFreya">Rest in peace!</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest IceQueensCastleBattle 18851-01.html">Can I have a second with you?</Button>
</body></html>

View File

@@ -14,7 +14,7 @@
* 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.areas.FreyasGarden.Jinia;
package ai.bosses.Freya.Jinia;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;

View File

@@ -14,7 +14,7 @@
* 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.areas.FreyasGarden.Sirra;
package ai.bosses.Freya.Sirra;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;

View File

@@ -0,0 +1,909 @@
/*
* 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.bosses.Frintezza;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.l2jmobius.commons.util.CommonUtil;
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.L2MonsterInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.skills.Skill;
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.IClientOutgoingPacket;
import com.l2jmobius.gameserver.network.serverpackets.MagicSkillCanceld;
import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
import com.l2jmobius.gameserver.network.serverpackets.NpcInfo;
import com.l2jmobius.gameserver.network.serverpackets.SocialAction;
import com.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
import instances.AbstractInstance;
/**
* Last Imperial Tomb AI
* @author Mobius (reworked from L2J version)
*/
public final class LastImperialTomb extends AbstractInstance
{
// NPCs
private static final int GUIDE = 32011;
private static final int CUBE = 29061;
private static final int HALL_ALARM = 18328;
private static final int HALL_KEEPER_SUICIDAL_SOLDIER = 18333;
private static final int DUMMY = 29052;
private static final int DUMMY2 = 29053;
private static final int[] PORTRAITS =
{
29048,
29049
};
private static final int[] DEMONS =
{
29050,
29051
};
private static final int FRINTEZZA = 29045;
private static final int SCARLET1 = 29046;
private static final int SCARLET2 = 29047;
private static final int[] ON_KILL_MONSTERS =
{
HALL_ALARM,
HALL_KEEPER_SUICIDAL_SOLDIER,
18329,
18330,
18331,
18334,
18335,
18336,
18337,
18338,
18339
};
// Items
private static final int DEWDROP_OF_DESTRUCTION_ITEM_ID = 8556;
private static final int FIRST_SCARLET_WEAPON = 8204;
private static final int SECOND_SCARLET_WEAPON = 7903;
// Doors
private static final int[] FIRST_ROOM_DOORS =
{
17130051,
17130052,
17130053,
17130054,
17130055,
17130056,
17130057,
17130058
};
private static final int[] SECOND_ROOM_DOORS =
{
17130061,
17130062,
17130063,
17130064,
17130065,
17130066,
17130067,
17130068,
17130069,
17130070
};
private static final int[] FIRST_ROUTE_DOORS =
{
17130042,
17130043
};
private static final int[] SECOND_ROUTE_DOORS =
{
17130045,
17130046
};
// Skills
private static final int DEWDROP_OF_DESTRUCTION_SKILL_ID = 2276;
private static final SkillHolder INTRO_SKILL = new SkillHolder(5004, 1);
private static final SkillHolder FIRST_MORPH_SKILL = new SkillHolder(5017, 1);
private static final Map<Integer, NpcStringId> SKILL_MSG = new HashMap<>();
static
{
SKILL_MSG.put(1, NpcStringId.REQUIEM_OF_HATRED);
SKILL_MSG.put(2, NpcStringId.RONDO_OF_SOLITUDE);
SKILL_MSG.put(3, NpcStringId.FRENETIC_TOCCATA);
SKILL_MSG.put(4, NpcStringId.FUGUE_OF_JUBILATION);
SKILL_MSG.put(5, NpcStringId.HYPNOTIC_MAZURKA);
}
// Spawns
// @formatter:off
static final int[][] PORTRAIT_SPAWNS =
{
{29048, -89381, -153981, -9168, 3368, -89378, -153968, -9168, 3368},
{29048, -86234, -152467, -9168, 37656, -86261, -152492, -9168, 37656},
{29049, -89342, -152479, -9168, -5152, -89311, -152491, -9168, -5152},
{29049, -86189, -153968, -9168, 29456, -86217, -153956, -9168, 29456},
};
// @formatter:on
// Misc
private static final int TEMPLATE_ID = 136;
private static final int FRINTEZZA_WAIT_TIME = 10; // minutes
private static final int RANDOM_SONG_INTERVAL = 90; // seconds
private static final int TIME_BETWEEN_DEMON_SPAWNS = 20; // seconds
private static final int MAX_DEMONS = 24;
public LastImperialTomb()
{
super(TEMPLATE_ID);
addTalkId(GUIDE, CUBE);
addAttackId(SCARLET1);
addKillId(ON_KILL_MONSTERS);
addKillId(HALL_ALARM, SCARLET2);
addKillId(PORTRAITS);
addKillId(DEMONS);
addSpawnId(HALL_ALARM, DUMMY, DUMMY2);
addSpellFinishedId(HALL_KEEPER_SUICIDAL_SOLDIER);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "FRINTEZZA_INTRO_START":
{
final Instance world = player.getInstanceWorld();
startQuestTimer("FRINTEZZA_INTRO_1", 17000, null, player, false);
startQuestTimer("FRINTEZZA_INTRO_2", 20000, null, player, false);
broadCastPacket(world, new Earthquake(-87784, -155083, -9087, 45, 27));
break;
}
case "FRINTEZZA_INTRO_1":
{
final Instance world = player.getInstanceWorld();
for (int doorId : FIRST_ROOM_DOORS)
{
world.openCloseDoor(doorId, false);
}
for (int doorId : FIRST_ROUTE_DOORS)
{
world.openCloseDoor(doorId, false);
}
for (int doorId : SECOND_ROOM_DOORS)
{
world.openCloseDoor(doorId, false);
}
for (int doorId : SECOND_ROUTE_DOORS)
{
world.openCloseDoor(doorId, false);
}
addSpawn(CUBE, -87904, -141296, -9168, 0, false, 0, false, world.getId());
break;
}
case "FRINTEZZA_INTRO_2":
{
final Instance world = player.getInstanceWorld();
final L2Npc frintezzaDummy = addSpawn(DUMMY, -87784, -155083, -9087, 16048, false, 0, false, world.getId());
world.setParameter("frintezzaDummy", frintezzaDummy);
final L2Npc overheadDummy = addSpawn(DUMMY, -87784, -153298, -9175, 16384, false, 0, false, world.getId());
overheadDummy.setCollisionHeight(600);
broadCastPacket(world, new NpcInfo(overheadDummy));
world.setParameter("overheadDummy", overheadDummy);
final L2Npc portraitDummy1 = addSpawn(DUMMY, -89566, -153168, -9165, 16048, false, 0, false, world.getId());
world.setParameter("portraitDummy1", portraitDummy1);
final L2Npc portraitDummy3 = addSpawn(DUMMY, -86004, -153168, -9165, 16048, false, 0, false, world.getId());
world.setParameter("portraitDummy3", portraitDummy3);
final L2Npc scarletDummy = addSpawn(DUMMY2, -87784, -153298, -9175, 16384, false, 0, false, world.getId());
world.setParameter("scarletDummy", scarletDummy);
disablePlayers(world);
broadCastPacket(world, new SpecialCamera(overheadDummy, 0, 75, -89, 0, 100, 0, 0, 1, 0, 0));
broadCastPacket(world, new SpecialCamera(overheadDummy, 0, 75, -89, 0, 100, 0, 0, 1, 0, 0));
broadCastPacket(world, new SpecialCamera(overheadDummy, 300, 90, -10, 6500, 7000, 0, 0, 1, 0, 0));
final L2Npc frintezza = addSpawn(FRINTEZZA, -87780, -155086, -9080, 16384, false, 0, false, world.getId());
frintezza.setIsImmobilized(true);
frintezza.setIsInvul(true);
frintezza.disableAllSkills();
world.setParameter("frintezza", frintezza);
final List<L2Npc> demons = new ArrayList<>();
for (int[] element : PORTRAIT_SPAWNS)
{
final L2MonsterInstance demon = (L2MonsterInstance) addSpawn(element[0] + 2, element[5], element[6], element[7], element[8], false, 0, false, world.getId());
demon.setIsImmobilized(true);
demon.disableAllSkills();
demons.add(demon);
}
world.setParameter("demons", demons);
startQuestTimer("FRINTEZZA_INTRO_3", 6500, null, player, false);
break;
}
case "FRINTEZZA_INTRO_3":
{
final Instance world = player.getInstanceWorld();
final L2Npc frintezzaDummy = world.getParameters().getObject("frintezzaDummy", L2Npc.class);
broadCastPacket(world, new SpecialCamera(frintezzaDummy, 1800, 90, 8, 6500, 7000, 0, 0, 1, 0, 0));
startQuestTimer("FRINTEZZA_INTRO_4", 900, null, player, false);
break;
}
case "FRINTEZZA_INTRO_4":
{
final Instance world = player.getInstanceWorld();
final L2Npc frintezzaDummy = world.getParameters().getObject("frintezzaDummy", L2Npc.class);
broadCastPacket(world, new SpecialCamera(frintezzaDummy, 140, 90, 10, 2500, 4500, 0, 0, 1, 0, 0));
startQuestTimer("FRINTEZZA_INTRO_5", 4000, null, player, false);
break;
}
case "FRINTEZZA_INTRO_5":
{
final Instance world = player.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new SpecialCamera(frintezza, 40, 75, -10, 0, 1000, 0, 0, 1, 0, 0));
broadCastPacket(world, new SpecialCamera(frintezza, 40, 75, -10, 0, 12000, 0, 0, 1, 0, 0));
startQuestTimer("FRINTEZZA_INTRO_6", 1350, null, player, false);
break;
}
case "FRINTEZZA_INTRO_6":
{
final Instance world = player.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new SocialAction(frintezza.getObjectId(), 2));
final L2Npc frintezzaDummy = world.getParameters().getObject("frintezzaDummy", L2Npc.class);
frintezzaDummy.deleteMe();
startQuestTimer("FRINTEZZA_INTRO_7", 8000, null, player, false);
break;
}
case "FRINTEZZA_INTRO_7":
{
final Instance world = player.getInstanceWorld();
final List<L2Npc> demons = world.getParameters().getList("demons", L2Npc.class);
broadCastPacket(world, new SocialAction(demons.get(1).getObjectId(), 1));
broadCastPacket(world, new SocialAction(demons.get(2).getObjectId(), 1));
startQuestTimer("FRINTEZZA_INTRO_8", 400, null, player, false);
break;
}
case "FRINTEZZA_INTRO_8":
{
final Instance world = player.getInstanceWorld();
final List<L2Npc> demons = world.getParameters().getList("demons", L2Npc.class);
final L2Npc portraitDummy1 = world.getParameters().getObject("portraitDummy1", L2Npc.class);
final L2Npc portraitDummy3 = world.getParameters().getObject("portraitDummy3", L2Npc.class);
broadCastPacket(world, new SocialAction(demons.get(0).getObjectId(), 1));
broadCastPacket(world, new SocialAction(demons.get(3).getObjectId(), 1));
sendPacketX(world, new SpecialCamera(portraitDummy1, 1000, 118, 0, 0, 1000, 0, 0, 1, 0, 0), new SpecialCamera(portraitDummy3, 1000, 62, 0, 0, 1000, 0, 0, 1, 0, 0), -87784);
sendPacketX(world, new SpecialCamera(portraitDummy1, 1000, 118, 0, 0, 10000, 0, 0, 1, 0, 0), new SpecialCamera(portraitDummy3, 1000, 62, 0, 0, 10000, 0, 0, 1, 0, 0), -87784);
startQuestTimer("FRINTEZZA_INTRO_9", 2000, null, player, false);
break;
}
case "FRINTEZZA_INTRO_9":
{
final Instance world = player.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
final L2Npc portraitDummy1 = world.getParameters().getObject("portraitDummy1", L2Npc.class);
final L2Npc portraitDummy3 = world.getParameters().getObject("portraitDummy3", L2Npc.class);
broadCastPacket(world, new SpecialCamera(frintezza, 240, 90, 0, 0, 1000, 0, 0, 1, 0, 0));
broadCastPacket(world, new SpecialCamera(frintezza, 240, 90, 25, 5500, 10000, 0, 0, 1, 0, 0));
broadCastPacket(world, new SocialAction(frintezza.getObjectId(), 3));
portraitDummy1.deleteMe();
portraitDummy3.deleteMe();
startQuestTimer("FRINTEZZA_INTRO_10", 4500, null, player, false);
break;
}
case "FRINTEZZA_INTRO_10":
{
final Instance world = player.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new SpecialCamera(frintezza, 100, 195, 35, 0, 10000, 0, 0, 1, 0, 0));
startQuestTimer("FRINTEZZA_INTRO_11", 700, null, player, false);
break;
}
case "FRINTEZZA_INTRO_11":
{
final Instance world = player.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new SpecialCamera(frintezza, 100, 195, 35, 0, 10000, 0, 0, 1, 0, 0));
startQuestTimer("FRINTEZZA_INTRO_12", 1300, null, player, false);
break;
}
case "FRINTEZZA_INTRO_12":
{
final Instance world = player.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.MOURNFUL_CHORALE_PRELUDE, 2, 5000));
broadCastPacket(world, new SpecialCamera(frintezza, 120, 180, 45, 1500, 10000, 0, 0, 1, 0, 0));
broadCastPacket(world, new MagicSkillUse(frintezza, frintezza, 5006, 1, 34000, 0));
startQuestTimer("FRINTEZZA_INTRO_13", 1500, null, player, false);
break;
}
case "FRINTEZZA_INTRO_13":
{
final Instance world = player.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new SpecialCamera(frintezza, 520, 135, 45, 8000, 10000, 0, 0, 1, 0, 0));
startQuestTimer("FRINTEZZA_INTRO_14", 7500, null, player, false);
break;
}
case "FRINTEZZA_INTRO_14":
{
final Instance world = player.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new SpecialCamera(frintezza, 1500, 110, 25, 10000, 13000, 0, 0, 1, 0, 0));
startQuestTimer("FRINTEZZA_INTRO_15", 9500, null, player, false);
break;
}
case "FRINTEZZA_INTRO_15":
{
final Instance world = player.getInstanceWorld();
final L2Npc overheadDummy = world.getParameters().getObject("overheadDummy", L2Npc.class);
final L2Npc scarletDummy = world.getParameters().getObject("scarletDummy", L2Npc.class);
broadCastPacket(world, new SpecialCamera(overheadDummy, 930, 160, -20, 0, 1000, 0, 0, 1, 0, 0));
broadCastPacket(world, new SpecialCamera(overheadDummy, 600, 180, -25, 0, 10000, 0, 0, 1, 0, 0));
broadCastPacket(world, new MagicSkillUse(scarletDummy, overheadDummy, 5004, 1, 5800, 0));
startQuestTimer("FRINTEZZA_INTRO_16", 5000, null, player, false);
break;
}
case "FRINTEZZA_INTRO_16":
{
final Instance world = player.getInstanceWorld();
final L2Npc scarletDummy = world.getParameters().getObject("scarletDummy", L2Npc.class);
final L2Npc activeScarlet = addSpawn(SCARLET1, -87789, -153295, -9176, 16384, false, 0, false, world.getId());
world.setParameter("activeScarlet", activeScarlet);
activeScarlet.setRHandId(FIRST_SCARLET_WEAPON);
activeScarlet.setIsInvul(true);
activeScarlet.setIsImmobilized(true);
activeScarlet.disableAllSkills();
broadCastPacket(world, new SocialAction(activeScarlet.getObjectId(), 3));
broadCastPacket(world, new SpecialCamera(scarletDummy, 800, 180, 10, 1000, 10000, 0, 0, 1, 0, 0));
startQuestTimer("FRINTEZZA_INTRO_17", 2100, null, player, false);
break;
}
case "FRINTEZZA_INTRO_17":
{
final Instance world = player.getInstanceWorld();
final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class);
broadCastPacket(world, new SpecialCamera(activeScarlet, 300, 60, 8, 0, 10000, 0, 0, 1, 0, 0));
startQuestTimer("FRINTEZZA_INTRO_18", 2000, null, player, false);
break;
}
case "FRINTEZZA_INTRO_18":
{
final Instance world = player.getInstanceWorld();
final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class);
broadCastPacket(world, new SpecialCamera(activeScarlet, 500, 90, 10, 3000, 5000, 0, 0, 1, 0, 0));
world.setParameter("isPlayingSong", false);
playRandomSong(world);
startQuestTimer("FRINTEZZA_INTRO_19", 3000, null, player, false);
break;
}
case "FRINTEZZA_INTRO_19":
{
final Instance world = player.getInstanceWorld();
final Map<L2Npc, Integer> portraits = new HashMap<>();
for (int i = 0; i < PORTRAIT_SPAWNS.length; i++)
{
final L2Npc portrait = addSpawn(PORTRAIT_SPAWNS[i][0], PORTRAIT_SPAWNS[i][1], PORTRAIT_SPAWNS[i][2], PORTRAIT_SPAWNS[i][3], PORTRAIT_SPAWNS[i][4], false, 0, false, world.getId());
portraits.put(portrait, i);
}
world.setParameter("portraits", portraits);
final L2Npc overheadDummy = world.getParameters().getObject("overheadDummy", L2Npc.class);
final L2Npc scarletDummy = world.getParameters().getObject("scarletDummy", L2Npc.class);
overheadDummy.deleteMe();
scarletDummy.deleteMe();
startQuestTimer("FRINTEZZA_INTRO_20", 2000, null, player, false);
break;
}
case "FRINTEZZA_INTRO_20":
{
final Instance world = player.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class);
final List<L2Npc> demons = world.getParameters().getList("demons", L2Npc.class);
for (L2Npc demon : demons)
{
demon.setIsImmobilized(false);
demon.enableAllSkills();
}
activeScarlet.setIsInvul(false);
activeScarlet.setIsImmobilized(false);
activeScarlet.enableAllSkills();
activeScarlet.setRunning();
activeScarlet.doCast(INTRO_SKILL.getSkill());
frintezza.enableAllSkills();
frintezza.disableCoreAI(true);
frintezza.setIsInvul(true);
enablePlayers(world);
startQuestTimer("PLAY_RANDOM_SONG", RANDOM_SONG_INTERVAL * 1000, frintezza, null, false);
startQuestTimer("SPAWN_DEMONS", TIME_BETWEEN_DEMON_SPAWNS * 1000, null, player, false);
break;
}
case "SPAWN_DEMONS":
{
final Instance world = player.getInstanceWorld();
final Map<L2Npc, Integer> portraits = world.getParameters().getMap("portraits", L2Npc.class, Integer.class);
if (!portraits.isEmpty())
{
final List<L2Npc> demons = world.getParameters().getList("demons", L2Npc.class);
for (int i : portraits.values())
{
if (demons.size() > MAX_DEMONS)
{
break;
}
final L2Npc demon = addSpawn(PORTRAIT_SPAWNS[i][0] + 2, PORTRAIT_SPAWNS[i][5], PORTRAIT_SPAWNS[i][6], PORTRAIT_SPAWNS[i][7], PORTRAIT_SPAWNS[i][8], false, 0, false, world.getId());
demons.add(demon);
}
world.setParameter("demons", demons);
startQuestTimer("SPAWN_DEMONS", TIME_BETWEEN_DEMON_SPAWNS * 1000, null, player, false);
}
break;
}
case "PLAY_RANDOM_SONG":
{
if (npc != null)
{
final Instance world = npc.getInstanceWorld();
playRandomSong(world);
startQuestTimer("PLAY_RANDOM_SONG", RANDOM_SONG_INTERVAL * 1000, null, player, false);
}
break;
}
case "SCARLET_FIRST_MORPH":
{
final Instance world = npc.getInstanceWorld();
npc.doCast(FIRST_MORPH_SKILL.getSkill());
playRandomSong(world);
break;
}
case "SCARLET_SECOND_MORPH":
{
final Instance world = npc.getInstanceWorld();
disablePlayers(world);
final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class);
activeScarlet.abortAttack();
activeScarlet.abortCast();
activeScarlet.setIsInvul(true);
activeScarlet.setIsImmobilized(true);
activeScarlet.disableAllSkills();
playRandomSong(world);
startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_1", 2000, npc, null, false);
break;
}
case "SCARLET_SECOND_MORPH_CAMERA_1":
{
final Instance world = npc.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new SocialAction(frintezza.getObjectId(), 4));
broadCastPacket(world, new SpecialCamera(frintezza, 250, 120, 15, 0, 1000, 0, 0, 1, 0, 0));
broadCastPacket(world, new SpecialCamera(frintezza, 250, 120, 15, 0, 10000, 0, 0, 1, 0, 0));
startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_2", 7000, npc, null, false);
break;
}
case "SCARLET_SECOND_MORPH_CAMERA_2":
{
final Instance world = npc.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new MagicSkillUse(frintezza, frintezza, 5006, 1, 34000, 0));
broadCastPacket(world, new SpecialCamera(frintezza, 500, 70, 15, 3000, 10000, 0, 0, 1, 0, 0));
startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_3", 3000, npc, null, false);
break;
}
case "SCARLET_SECOND_MORPH_CAMERA_3":
{
final Instance world = npc.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new SpecialCamera(frintezza, 2500, 90, 12, 6000, 10000, 0, 0, 1, 0, 0));
startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_4", 3000, npc, null, false);
break;
}
case "SCARLET_SECOND_MORPH_CAMERA_4":
{
final Instance world = npc.getInstanceWorld();
final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class);
final Location scarletLocation = activeScarlet.getLocation();
int newHeading = 0;
if (scarletLocation.getHeading() < 32768)
{
newHeading = Math.abs(180 - (int) (scarletLocation.getHeading() / 182.044444444));
}
else
{
newHeading = Math.abs(540 - (int) (scarletLocation.getHeading() / 182.044444444));
}
world.setParameter("scarletLocation", scarletLocation);
world.setParameter("newHeading", newHeading);
broadCastPacket(world, new SpecialCamera(activeScarlet, 250, newHeading, 12, 0, 1000, 0, 0, 1, 0, 0));
broadCastPacket(world, new SpecialCamera(activeScarlet, 250, newHeading, 12, 0, 10000, 0, 0, 1, 0, 0));
startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_5", 500, npc, null, false);
break;
}
case "SCARLET_SECOND_MORPH_CAMERA_5":
{
final Instance world = npc.getInstanceWorld();
final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class);
final int newHeading = world.getParameters().getInt("newHeading");
activeScarlet.doDie(activeScarlet);
broadCastPacket(world, new SpecialCamera(activeScarlet, 450, newHeading, 14, 8000, 8000, 0, 0, 1, 0, 0));
startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_6", 6250, npc, null, false);
startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_7", 7200, npc, null, false);
break;
}
case "SCARLET_SECOND_MORPH_CAMERA_6":
{
final Instance world = npc.getInstanceWorld();
final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class);
activeScarlet.deleteMe();
break;
}
case "SCARLET_SECOND_MORPH_CAMERA_7":
{
final Instance world = npc.getInstanceWorld();
final int newHeading = world.getParameters().getInt("newHeading");
final Location scarletLocation = world.getParameters().getLocation("scarletLocation");
final L2Npc activeScarlet = addSpawn(SCARLET2, scarletLocation, false, 0, false, world.getId());
world.setParameter("activeScarlet", activeScarlet);
activeScarlet.setRHandId(SECOND_SCARLET_WEAPON);
activeScarlet.setIsInvul(true);
activeScarlet.setIsImmobilized(true);
activeScarlet.disableAllSkills();
broadCastPacket(world, new SpecialCamera(activeScarlet, 450, newHeading, 12, 500, 14000, 0, 0, 1, 0, 0));
startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_8", 8100, npc, null, false);
break;
}
case "SCARLET_SECOND_MORPH_CAMERA_8":
{
final Instance world = npc.getInstanceWorld();
final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class);
broadCastPacket(world, new SocialAction(activeScarlet.getObjectId(), 2));
startQuestTimer("SCARLET_SECOND_MORPH_CAMERA_9", 9000, npc, null, false);
break;
}
case "SCARLET_SECOND_MORPH_CAMERA_9":
{
final Instance world = npc.getInstanceWorld();
final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class);
activeScarlet.setIsInvul(false);
activeScarlet.setIsImmobilized(false);
activeScarlet.enableAllSkills();
enablePlayers(world);
break;
}
case "FINISH_CAMERA_1":
{
final Instance world = npc.getInstanceWorld();
final L2Npc activeScarlet = world.getParameters().getObject("activeScarlet", L2Npc.class);
final int newHeading = world.getParameters().getInt("newHeading");
broadCastPacket(world, new SpecialCamera(activeScarlet, 300, newHeading - 180, 5, 0, 7000, 0, 0, 1, 0, 0));
broadCastPacket(world, new SpecialCamera(activeScarlet, 200, newHeading, 85, 4000, 10000, 0, 0, 1, 0, 0));
startQuestTimer("FINISH_CAMERA_2", 7400, npc, null, false);
startQuestTimer("FINISH_CAMERA_3", 7500, npc, null, false);
break;
}
case "FINISH_CAMERA_2":
{
final Instance world = npc.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
frintezza.doDie(frintezza);
break;
}
case "FINISH_CAMERA_3":
{
final Instance world = npc.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new SpecialCamera(frintezza, 100, 120, 5, 0, 7000, 0, 0, 1, 0, 0));
broadCastPacket(world, new SpecialCamera(frintezza, 100, 90, 5, 5000, 15000, 0, 0, 1, 0, 0));
startQuestTimer("FINISH_CAMERA_4", 7000, npc, null, false);
break;
}
case "FINISH_CAMERA_4":
{
final Instance world = npc.getInstanceWorld();
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new SpecialCamera(frintezza, 900, 90, 25, 7000, 10000, 0, 0, 1, 0, 0));
startQuestTimer("FINISH_CAMERA_5", 9000, npc, null, false);
break;
}
case "FINISH_CAMERA_5":
{
final Instance world = npc.getInstanceWorld();
for (int doorId : FIRST_ROOM_DOORS)
{
world.openCloseDoor(doorId, true);
}
for (int doorId : FIRST_ROUTE_DOORS)
{
world.openCloseDoor(doorId, true);
}
for (int doorId : SECOND_ROOM_DOORS)
{
world.openCloseDoor(doorId, true);
}
for (int doorId : SECOND_ROUTE_DOORS)
{
world.openCloseDoor(doorId, true);
}
enablePlayers(world);
break;
}
}
return null;
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
if (npc.getId() == GUIDE)
{
enterInstance(player, npc, TEMPLATE_ID);
}
else // Teleport Cube
{
final Instance world = getPlayerInstance(player);
if (world != null)
{
teleportPlayerOut(player, world);
}
}
return null;
}
@Override
public String onSpawn(L2Npc npc)
{
npc.setRandomWalking(false);
npc.setIsImmobilized(true);
if (npc.getId() == HALL_ALARM)
{
npc.disableCoreAI(true);
}
else // dummy
{
npc.setIsInvul(true);
}
return super.onSpawn(npc);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
{
if (npc.getId() == SCARLET1)
{
if ((npc.getScriptValue() == 0) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.80)))
{
npc.setScriptValue(1);
startQuestTimer("SCARLET_FIRST_MORPH", 1000, npc, null, false);
}
if ((npc.getScriptValue() == 1) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.20)))
{
npc.setScriptValue(2);
startQuestTimer("SCARLET_SECOND_MORPH", 1000, npc, null, false);
}
}
if (skill != null)
{
// When Dewdrop of Destruction is used on Portraits they suicide.
if (CommonUtil.contains(PORTRAITS, npc.getId()) && (skill.getId() == DEWDROP_OF_DESTRUCTION_SKILL_ID))
{
npc.doDie(attacker);
}
}
return null;
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
if (skill.isSuicideAttack())
{
return onKill(npc, null, false);
}
return super.onSpellFinished(npc, player, skill);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
final Instance world = killer.getInstanceWorld();
if ((npc.getId() == HALL_ALARM) && (world.getStatus() == 0))
{
world.setStatus(1);
world.spawnGroup("room1");
final List<L2MonsterInstance> monsters = world.getAliveNpcs(L2MonsterInstance.class);
world.setParameter("monstersCount", monsters.size() - 1);
for (int doorId : FIRST_ROOM_DOORS)
{
world.openCloseDoor(doorId, true);
}
for (L2Npc monster : monsters)
{
monster.reduceCurrentHp(1, killer, null); // TODO: Find better way for attack
}
}
else if (npc.getId() == SCARLET2)
{
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
broadCastPacket(world, new MagicSkillCanceld(frintezza.getObjectId()));
startQuestTimer("FINISH_CAMERA_1", 500, npc, null, false);
}
else if (CommonUtil.contains(DEMONS, npc.getId()))
{
final List<L2Npc> demons = world.getParameters().getList("demons", L2Npc.class);
demons.remove(npc);
}
else if (CommonUtil.contains(PORTRAITS, npc.getId()))
{
final Map<L2Npc, Integer> portraits = world.getParameters().getMap("portraits", L2Npc.class, Integer.class);
portraits.remove(npc);
}
else
{
final int killCount = world.getParameters().getInt("monstersCount");
world.setParameter("monstersCount", killCount - 1);
if (killCount <= 0)
{
switch (world.getStatus())
{
case 1:
{
world.setStatus(2);
world.spawnGroup("room2_part1");
final List<L2MonsterInstance> monsters = world.getAliveNpcs(L2MonsterInstance.class);
world.setParameter("monstersCount", monsters.size() - 1);
for (int doorId : FIRST_ROUTE_DOORS)
{
world.openCloseDoor(doorId, true);
}
break;
}
case 2:
{
world.setStatus(3);
world.spawnGroup("room2_part2");
final List<L2MonsterInstance> monsters = world.getAliveNpcs(L2MonsterInstance.class);
world.setParameter("monstersCount", monsters.size() - 1);
for (int doorId : SECOND_ROOM_DOORS)
{
world.openCloseDoor(doorId, true);
}
for (L2Npc monster : monsters)
{
monster.reduceCurrentHp(1, killer, null); // TODO: Find better way for attack
}
break;
}
case 3:
{
world.setStatus(4);
for (int doorId : SECOND_ROUTE_DOORS)
{
world.openCloseDoor(doorId, true);
}
startQuestTimer("FRINTEZZA_INTRO_START", FRINTEZZA_WAIT_TIME * 60 * 1000, null, killer, false);
break;
}
}
}
if (getRandom(100) < 5)
{
npc.dropItem(killer, DEWDROP_OF_DESTRUCTION_ITEM_ID, 1);
}
}
return super.onKill(npc, killer, isSummon);
}
private void playRandomSong(Instance world)
{
final L2Npc frintezza = world.getParameters().getObject("frintezza", L2Npc.class);
final boolean isPlayingSong = world.getParameters().getBoolean("isPlayingSong");
if (isPlayingSong)
{
return;
}
world.setParameter("isPlayingSong", true);
final int random = getRandom(1, 5);
final SkillHolder skill = new SkillHolder(5007, random);
final SkillHolder skillEffect = new SkillHolder(5008, random);
broadCastPacket(world, new ExShowScreenMessage(2, -1, 2, 0, 0, 0, 0, true, 4000, false, null, SKILL_MSG.get(random), null));
broadCastPacket(world, new MagicSkillUse(frintezza, frintezza, skill.getSkillId(), skill.getSkillLevel(), skill.getSkill().getHitTime(), 0));
for (L2PcInstance player : world.getPlayers())
{
if ((player != null) && player.isOnline())
{
frintezza.setTarget(player);
frintezza.doCast(skillEffect.getSkill());
}
}
world.setParameter("isPlayingSong", false);
}
private void disablePlayers(Instance world)
{
for (L2PcInstance player : world.getPlayers())
{
if ((player != null) && player.isOnline())
{
player.abortAttack();
player.abortCast();
player.disableAllSkills();
player.setTarget(null);
player.stopMove(null);
player.setIsImmobilized(true);
player.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
}
}
}
private void enablePlayers(Instance world)
{
for (L2PcInstance player : world.getPlayers())
{
if ((player != null) && player.isOnline())
{
player.enableAllSkills();
player.setIsImmobilized(false);
}
}
}
void broadCastPacket(Instance world, IClientOutgoingPacket packet)
{
for (L2PcInstance player : world.getPlayers())
{
if ((player != null) && player.isOnline())
{
player.sendPacket(packet);
}
}
}
private void sendPacketX(Instance world, IClientOutgoingPacket packet1, IClientOutgoingPacket packet2, int x)
{
for (L2PcInstance player : world.getPlayers())
{
if ((player != null) && player.isOnline())
{
if (player.getX() < x)
{
player.sendPacket(packet1);
}
else
{
player.sendPacket(packet2);
}
}
}
}
public static void main(String[] args)
{
new LastImperialTomb();
}
}

View File

@@ -0,0 +1,282 @@
/*
* 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.bosses.Frintezza;
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 com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.data.xml.impl.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 ai.AbstractNpcAI;
/**
* @author Micr0, Zerox, Mobius
*/
public final class ScarletVanHalisha extends AbstractNpcAI
{
// NPCs
private static final int HALISHA2 = 29046;
private static final int HALISHA3 = 29047;
// Skills
private static final int FRINTEZZA_DAEMON_ATTACK = 5014;
private static final int FRINTEZZA_DAEMON_CHARGE = 5015;
private static final int YOKE_OF_SCARLET = 5016;
private static final int FRINTEZZA_DAEMON_MORPH = 5018;
private static final int FRINTEZZA_DAEMON_FIELD = 5019;
// Misc
private L2Character _target;
private Skill _skill;
private long _lastRangedSkillTime;
private final int _rangedSkillMinCoolTime = 60000; // 1 minute
public ScarletVanHalisha()
{
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 (getRandom(100) < 10)
{
return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_CHARGE, 2);
}
else if (getRandom(100) < 10)
{
return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_CHARGE, 5);
}
else if (getRandom(100) < 2)
{
return SkillData.getInstance().getSkill(YOKE_OF_SCARLET, 1);
}
else
{
return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_ATTACK, 2);
}
}
case HALISHA3:
{
if (getRandom(100) < 10)
{
return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_CHARGE, 3);
}
else if (getRandom(100) < 10)
{
return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_CHARGE, 6);
}
else if (getRandom(100) < 10)
{
return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_CHARGE, 2);
}
else if (((_lastRangedSkillTime + _rangedSkillMinCoolTime) < System.currentTimeMillis()) && (getRandom(100) < 10))
{
return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_FIELD, 1);
}
else if (((_lastRangedSkillTime + _rangedSkillMinCoolTime) < System.currentTimeMillis()) && (getRandom(100) < 10))
{
return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_MORPH, 1);
}
else if (getRandom(100) < 2)
{
return SkillData.getInstance().getSkill(YOKE_OF_SCARLET, 1);
}
else
{
return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_ATTACK, 3);
}
}
}
return SkillData.getInstance().getSkill(FRINTEZZA_DAEMON_ATTACK, 1);
}
private synchronized void getSkillAI(L2Npc npc)
{
if (npc.isInvul() || npc.isCastingNow())
{
return;
}
if ((getRandom(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 ArrayList<L2Character> result = new ArrayList<>();
{
for (L2Object obj : npc.getInstanceWorld().getPlayers())
{
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 FRINTEZZA_DAEMON_ATTACK:
{
skillRange = 150;
break;
}
case FRINTEZZA_DAEMON_CHARGE:
{
skillRange = 400;
break;
}
case YOKE_OF_SCARLET:
{
skillRange = 200;
break;
}
case FRINTEZZA_DAEMON_MORPH:
case FRINTEZZA_DAEMON_FIELD:
{
_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[getRandom(characters.length)];
}
return null;
}
public static void main(String[] args)
{
new ScarletVanHalisha();
}
}

View File

@@ -0,0 +1,8 @@
<html><body>Rumiese:<br>
Here's the plan. You weaken Istina as much as you can, while I prepare the magical Ballista. Have you seen one of those? They're rather impressive. They are powered by soulshots and can do a great deal of damage. Their main drawback is that they require a lot of energy to recharge, so please tell your team to push yourselves to collect as much magical power as you can, as quickly as possible.<br>
That is all the advice I can give; the rest of it is up to you.<br>
Oh, I once gave you an <font color="LEVEL">Energy Control Device</font>, didn't I? You will most certainly need it for your fight with Istina, so shall I give it to you now?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest IstinaCavern leaveInstance">"No, I have somewhere else to be."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest IstinaCavern giveDevice">"Please give me a Control Device."</Button>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Rumiese:<br>
Somebody is already fighting with Istina. If you want, I can let you in.<br>
Oh, I once gave you an <font color="LEVEL">Energy Control Device</font>, didn't I? You will most certainly need it for your fight with Istina, so shall I give it to you now?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest IstinaCavern battleTeleport">"Please let me in."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest IstinaCavern leaveInstance">"No, I have somewhere else to be."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest IstinaCavern giveDevice">"Please give me a Control Device."</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Rumiese:<br>
If you time things right, you can deal a critical blow to Istina with the magical power Ballista. Use all the power you have at your disposal to fully charge magical power within the time limit. If you can manage this--and with a little bit of luck--you'll really hurt Istina. Good luck!
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Rumiese:<br>
What an achievement! I am truly in awe of you and your cohorts. Now, let me give you something in recognition of your work. It's not much, compared to your great accomplishments, but I have a chest containing the strength of Istina's soul stone. The soul stone itself sometimes changes materials. Please, accept this with our thanks.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest IstinaCavern giveReward">"Can I get a chest imbued with soul stone power?"</Button>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Rumiese:<br>
Unfortunately, either our skill or our luck was not enough to meet the challenge. Istina has retreated, cowed but undefeated. It is only a matter of time before it returns.<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Rumiese:<br>
Here we go. Please do not forget you use this when you need it!<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Rumiese:<br>
This item can't be sold. But you already have one; you don't need another.<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Rumiese:<br>
You have quite excellent abilities, but you are also greedy. Shouldn't we give someone else a chance?<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,687 @@
/*
* 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.bosses.Istina;
import java.util.Comparator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.enums.CategoryType;
import com.l2jmobius.gameserver.enums.Movie;
import com.l2jmobius.gameserver.model.AggroInfo;
import com.l2jmobius.gameserver.model.DamageDoneInfo;
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.L2DoorInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
import com.l2jmobius.gameserver.util.Util;
import instances.AbstractInstance;
/**
* Istina Cavern instance zone.
* @author St3eT
*/
public final class IstinaCavern extends AbstractInstance
{
// NPCs
private static final int RUMIESE = 33151;
private static final int RUMIESE_INSTANCE = 33293;
private static final int INVISIBLE_NPC = 18919;
private static final int BALLISTA = 19021;
private static final int EXTREME_MINION = 23125;
private static final int[] ISTINA =
{
29195, // Istina (Common)
29196, // Istina (Extreme)
};
// Skills
private static final SkillHolder ERUPTION_1 = new SkillHolder(14222, 1);
private static final SkillHolder ERUPTION_2 = new SkillHolder(14223, 1);
private static final SkillHolder ISTINA_ERUPTION_SKILL = new SkillHolder(14221, 1);
// Items
private static final int CONTROL_DEVICE = 17608; // Energy Control Device
private static final int REWARD_BOX_COMMON = 30371; // Box Containing Magic Power
private static final int REWARD_BOX_EXTREME = 30374; // Magic Filled Box
// Locations
private static final Location DEFEAT_ISTINA_LOC = new Location(-177120, 148782, -11384, 49140);
private static final Location RUMIESE_LOC = new Location(-177001, 147844, -11380, 47684);
private static final Location BATTLE_LOC = new Location(-177111, 146802, -11384);
// Misc
private static final int PERFECT_SCORE_1 = 30000000;
private static final int PERFECT_SCORE_2 = 300000000;
private static final int TEMPLATE_ID_COMMON = 169;
private static final int TEMPLATE_ID_EXTREME = 170;
public IstinaCavern()
{
super(TEMPLATE_ID_COMMON, TEMPLATE_ID_EXTREME);
addStartNpc(RUMIESE);
addTalkId(RUMIESE, RUMIESE_INSTANCE);
addFirstTalkId(RUMIESE_INSTANCE);
addAttackId(ISTINA);
addAttackId(BALLISTA);
addSpellFinishedId(ISTINA);
addSpellFinishedId(INVISIBLE_NPC);
addSpawnId(INVISIBLE_NPC, BALLISTA);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = null;
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
switch (event)
{
case "leaveInstance":
{
teleportPlayerOut(player, instance);
break;
}
case "battleTeleport":
{
player.teleToLocation(BATTLE_LOC);
break;
}
case "giveDevice":
{
if (!hasQuestItems(player, CONTROL_DEVICE))
{
giveItems(player, CONTROL_DEVICE, 1);
htmltext = "33293-06.html";
}
else
{
htmltext = "33293-07.html";
}
}
case "giveReward":
{
if (instance.isStatus(3))
{
if (npc.getVariables().getBoolean("PLAYER_" + player.getObjectId(), true))
{
giveItems(player, (isExtremeMode(instance) ? REWARD_BOX_EXTREME : REWARD_BOX_COMMON), 1);
npc.getVariables().set("PLAYER_" + player.getObjectId(), false);
}
else
{
htmltext = "33293-08.html";
}
}
break;
}
}
}
else if (event.equals("enterInstanceCommon"))
{
enterInstance(player, npc, TEMPLATE_ID_COMMON);
}
else if (event.equals("enterInstanceExtreme"))
{
enterInstance(player, npc, TEMPLATE_ID_EXTREME);
}
return htmltext;
}
@Override
public void onTimerEvent(String event, StatsSet params, L2Npc npc, L2PcInstance player)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcParams = npc.getParameters();
final StatsSet npcVars = npc.getVariables();
switch (event)
{
case "DEATH_TIMER":
{
final L2Character mostHated = ((L2Attackable) npc).getMostHated();
if ((mostHated != null) && npc.isInsideRadius(mostHated, 15000, false, true))
{
final SkillHolder death1 = npcParams.getSkillHolder("Istina_Death_Skill01");
final SkillHolder death2 = npcParams.getSkillHolder("Istina_Death_Skill02");
if (mostHated.isInCategory(CategoryType.TANKER_GROUP))
{
addSkillCastDesire(npc, mostHated, (mostHated.isAffectedBySkill(death1) ? death2 : death1), 23);
}
else
{
addSkillCastDesire(npc, mostHated, death2, 23);
}
}
getTimers().addTimer("DEATH_TIMER", 35000, npc, null);
break;
}
case "DEATH_CHECK_TIMER":
{
final SkillHolder death1 = npcParams.getSkillHolder("Istina_Death_Skill01");
final SkillHolder death2 = npcParams.getSkillHolder("Istina_Death_Skill02");
final L2Character mostHated = ((L2Attackable) npc).getMostHated();
if ((mostHated != null) && npc.isInsideRadius(mostHated, 15000, false, true) && mostHated.isInCategory(CategoryType.TANKER_GROUP) && mostHated.isAffectedBySkill(death1))
{
addSkillCastDesire(npc, mostHated, death2, 23);
}
break;
}
case "REFLECT_TIMER":
{
if (!isExtremeMode(instance))
{
showOnScreenMsg(instance, NpcStringId.ISTINA_SPREADS_THE_REFLECTING_PROTECTIVE_SHEET, ExShowScreenMessage.TOP_CENTER, 4000);
}
final SkillHolder reflect = npcParams.getSkillHolder("Istina_Refraction_Skill");
npc.setTarget(npc);
npc.doCast(reflect.getSkill());
instance.broadcastPacket(new PlaySound(1, "Npcdialog1.istina_voice_02", 0, 0, 0, 0, 0));
getTimers().addTimer("REFLECT_TIMER", 90000 + getRandom(15000), npc, null);
break;
}
case "REFLECT_CHECK_TIMER":
{
if (npc.isAffectedBySkill(npcParams.getSkillHolder("Istina_Refraction_Skill")))
{
getTimers().addTimer("REFLECT_CHECK_TIMER", 1000, npc, null);
}
else
{
npc.setDisplayEffect(2);
}
break;
}
case "LOW_ERUPTION_TIMER":
{
final L2Attackable istina = (L2Attackable) npc;
if ((istina.getHateList() != null) && (istina.getHateList().size() > 0))
{
final L2Character target = istina.getHateList().stream().sorted((o1, o2) -> (int) o1.calculateDistance(o2, true, false)).findFirst().orElse(null);
if (target != null)
{
final L2Npc eruption = addSpawn(INVISIBLE_NPC, Util.getRandomPosition(target, 50, 50), false, 0, false, instance.getId());
eruption.getVariables().set("ERUPTION_TARGET", target);
}
}
getTimers().addTimer("LOW_ERUPTION_TIMER", 15000, npc, null);
break;
}
case "ERUPTION_TIMER":
{
addSkillCastDesire(npc, npc, ISTINA_ERUPTION_SKILL, 23);
showOnScreenMsg(instance, NpcStringId.POWERFUL_ACIDIC_ENERGY_IS_ERUPTING_FROM_ISTINA_S_BODY, ExShowScreenMessage.TOP_CENTER, 6000);
getTimers().addTimer("ERUPTION_TIMER", 50000 + getRandom(15000), npc, null);
break;
}
case "BALLISTA_START_TIMER":
{
final int helpCountDown = npcVars.getInt("HELP_COUNT_DOWN", 5);
if (helpCountDown == 0)
{
getTimers().addTimer("BALLISTA_CHECK_TIMER", 1000, npc, null);
npc.setTargetable(true);
npc.setIsInvul(false);
npcVars.set("COUNTING_ENABLED", true);
showOnScreenMsg(instance, NpcStringId.START_CHARGING_MANA_BALLISTA, ExShowScreenMessage.MIDDLE_CENTER, 4000);
}
else
{
showOnScreenMsg(instance, NpcStringId.AFTER_S1_SECONDS_THE_CHARGING_MAGIC_BALLISTAS_STARTS, ExShowScreenMessage.MIDDLE_CENTER, 4000, Integer.toString(helpCountDown));
npcVars.set("HELP_COUNT_DOWN", helpCountDown - 1);
getTimers().addTimer("BALLISTA_START_TIMER", 1000, npc, null);
}
break;
}
case "BALLISTA_CHECK_TIMER":
{
if (npcVars.getBoolean("COUNTING_ENABLED", false))
{
final int countDown = npcVars.getInt("COUNT_DOWN", 30);
final int charged = getChargedPercent(npcVars.getInt("SCORE_VAL", 0), isExtremeMode(instance));
if (countDown == 0)
{
npcVars.set("COUNTING_ENABLED", false);
npc.setTargetable(false);
npc.setIsInvul(true);
getTimers().addTimer("BALLISTA_END_TIMER", 1000, npc, null);
instance.getPlayers().forEach(temp -> temp.sendPacket(new ExSendUIEvent(temp, 2, countDown, charged, 0, 2042, 0, NpcStringId.REPLENISH_BALLISTA_MAGIC_POWER.getId())));
}
npcVars.set("HELP_COUNT_DOWN", npcVars.getInt("HELP_COUNT_DOWN", 0) + 1);
if (npcVars.getInt("HELP_COUNT_DOWN", 0) == 2)
{
npcVars.set("COUNT_DOWN", countDown - 1);
npcVars.set("HELP_COUNT_DOWN", 0);
instance.getPlayers().forEach(temp -> temp.sendPacket(new ExSendUIEvent(temp, 2, countDown, charged, 0, 2042, 0, NpcStringId.REPLENISH_BALLISTA_MAGIC_POWER.getId())));
}
getTimers().addTimer("BALLISTA_CHECK_TIMER", 500, npc, null);
}
break;
}
case "BALLISTA_END_TIMER":
{
if (getChargedPercent(npcVars.getInt("SCORE_VAL", 0), isExtremeMode(instance)) >= getRandom(100))
{
playMovie(instance, Movie.SC_ISTINA_ENDING_A);
instance.setStatus(3);
getTimers().addTimer("INSTANCE_FINISH_TIMER", 23000, npc, null);
}
else
{
playMovie(instance, Movie.SC_ISTINA_ENDING_B);
instance.setStatus(4);
getTimers().addTimer("INSTANCE_FINISH_TIMER", 22000, npc, null);
}
instance.getAliveNpcs(ISTINA).forEach(istina ->
{
istina.teleToLocation(instance.getEnterLocation());
istina.setInvisible(true);
});
break;
}
case "INSTANCE_FINISH_TIMER":
{
getTimers().addTimer("NPC_DELETE", 3000, evnt -> npc.deleteMe());
instance.finishInstance();
instance.getAliveNpcs(L2Attackable.class, ISTINA).forEach(istina ->
{
istina.teleToLocation(DEFEAT_ISTINA_LOC);
istina.setInvisible(false);
istina.setUndying(false);
istina.reduceCurrentHp(istina.getVariables().getInt("REWARD_DAMAGE", 1000000), istina.getVariables().getObject("REWARD_PLAYER", L2PcInstance.class), null);
});
break;
}
case "AUTHORITY_TIMER":
{
final int random = getRandom(1, 3);
final SkillHolder authoritySkill = npcParams.getSkillHolder("Istina_Authority_Skill0" + random);
if (authoritySkill != null)
{
addSkillCastDesire(npc, npc, authoritySkill, 23);
instance.broadcastPacket(new PlaySound(1, "Npcdialog1.istina_voice_01", 0, 0, 0, 0, 0));
switch (random)
{
case 1:
showOnScreenMsg(instance, NpcStringId.ISTINA_S_SOUL_STONE_STARTS_POWERFULLY_ILLUMINATING_IN_RED, ExShowScreenMessage.TOP_CENTER, 6000);
break;
case 2:
showOnScreenMsg(instance, NpcStringId.ISTINA_S_SOUL_STONE_STARTS_POWERFULLY_ILLUMINATING_IN_BLUE, ExShowScreenMessage.TOP_CENTER, 6000);
break;
case 3:
showOnScreenMsg(instance, NpcStringId.ISTINA_S_SOUL_STONE_STARTS_POWERFULLY_ILLUMINATING_IN_GREEN, ExShowScreenMessage.TOP_CENTER, 6000);
break;
}
}
getTimers().addTimer("AUTHORITY_TIMER", 70000 + getRandom(25000), npc, null);
break;
}
case "AUTHORITY_END_TIMER":
{
// gg->Area_SetOnOffEx(Istina_Authority_AreaData1, @OFF, myself->InstantZone_GetId());
// gg->Area_SetOnOffEx(Istina_Authority_AreaData2, @OFF, myself->InstantZone_GetId());
// gg->Area_SetOnOffEx(Istina_Authority_AreaData3, @OFF, myself->InstantZone_GetId());
break;
}
}
}
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
final Instance instance = npc.getInstanceWorld();
if ((skill != null) && isInInstance(instance))
{
final int skillId = skill.getId();
if (npc.getId() == INVISIBLE_NPC)
{
if (skillId == ERUPTION_1.getSkillId())
{
npc.setTarget(npc);
npc.doCast(ERUPTION_2.getSkill());
}
else if (skillId == ERUPTION_2.getSkillId())
{
getTimers().addTimer("NPC_DELETE", 2000, event -> npc.deleteMe());
if (isExtremeMode(instance) && (getRandom(100) < 30))
{
addAttackPlayerDesire(addSpawn(EXTREME_MINION, npc, false, 0, false, instance.getId()), npc.getVariables().getObject("ERUPTION_TARGET", L2PcInstance.class), 23);
}
}
}
else
{
final StatsSet npcParams = npc.getParameters();
if (skillId == npcParams.getSkillHolder("Istina_Death_Skill01").getSkillId())
{
showOnScreenMsg(player, NpcStringId.ISTINA_S_MARK_SHINES_ABOVE_THE_HEAD, ExShowScreenMessage.TOP_CENTER, 4000);
getTimers().addTimer("DEATH_CHECK_TIMER", 10000, npc, null);
}
else if (skillId == npcParams.getSkillHolder("Istina_Refraction_Skill").getSkillId())
{
npc.setDisplayEffect(1);
getTimers().addTimer("REFLECT_CHECK_TIMER", 1000, npc, null);
}
else if (skillId == ISTINA_ERUPTION_SKILL.getSkillId())
{
((L2Attackable) npc).getAggroList().values().stream().sorted(Comparator.comparingInt(AggroInfo::getHate)).map(AggroInfo::getAttacker).limit(5).forEach(character ->
{
final L2Npc eruption = addSpawn(INVISIBLE_NPC, Util.getRandomPosition(character, 150, 150), false, 0, false, instance.getId());
eruption.getVariables().set("ERUPTION_TARGET", character);
});
}
else if (skillId == npcParams.getSkillHolder("Istina_Authority_Skill01").getSkillId())
{
// gg->Area_SetOnOffEx(Istina_Authority_AreaData2, @ON, myself->InstantZone_GetId()); // TODO: Need be finished after zone rework
// gg->Area_SetOnOffEx(Istina_Authority_AreaData3, @ON, myself->InstantZone_GetId()); // TODO: Need be finished after zone rework
getTimers().addTimer("AUTHORITY_END_TIMER", 15000, npc, null);
}
else if (skillId == npcParams.getSkillHolder("Istina_Authority_Skill02").getSkillId())
{
// gg->Area_SetOnOffEx(Istina_Authority_AreaData1, @ON, myself->InstantZone_GetId()); // TODO: Need be finished after zone rework
// gg->Area_SetOnOffEx(Istina_Authority_AreaData3, @ON, myself->InstantZone_GetId()); // TODO: Need be finished after zone rework
getTimers().addTimer("AUTHORITY_END_TIMER", 15000, npc, null);
}
else if (skillId == npcParams.getSkillHolder("Istina_Authority_Skill03").getSkillId())
{
// gg->Area_SetOnOffEx(Istina_Authority_AreaData1, @ON, myself->InstantZone_GetId()); // TODO: Need be finished after zone rework
// gg->Area_SetOnOffEx(Istina_Authority_AreaData2, @ON, myself->InstantZone_GetId()); // TODO: Need be finished after zone rework
getTimers().addTimer("AUTHORITY_END_TIMER", 15000, npc, null);
}
}
}
return super.onSpellFinished(npc, player, skill);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcVars = npc.getVariables();
final int stage = npcVars.getInt("ISTINA_STAGE", -1);
if (npc.getId() == BALLISTA)
{
if (npcVars.getBoolean("COUNTING_ENABLED", false))
{
final int score = npcVars.getInt("SCORE_VAL", 0);
if (getChargedPercent(score, isExtremeMode(instance)) < 100)
{
int addScore = damage;
if (skill != null)
{
if (skill.getEffectPoint() < 0)
{
addScore *= 1.5;
}
addScore *= 1.5;
}
if (attacker.isInCategory(CategoryType.FIGHTER_GROUP))
{
addScore *= 2;
}
npcVars.set("SCORE_VAL", score + addScore);
}
}
}
else
{
switch (stage)
{
case -1:
{
instance.setStatus(1);
npcVars.set("ISTINA_STAGE", 1);
instance.getDoors().forEach(L2DoorInstance::closeMe);
npc.setUndying(true);
((L2Attackable) npc).setCanReturnToSpawnPoint(false);
getTimers().addTimer("DEATH_TIMER", 3500, npc, null);
getTimers().addTimer("REFLECT_TIMER", 3500, npc, null);
getTimers().addTimer("LOW_ERUPTION_TIMER", 15000, npc, null);
break;
}
case 1:
{
if (npc.getCurrentHpPercent() < 85)
{
npcVars.set("ISTINA_STAGE", 2);
getTimers().addTimer("AUTHORITY_TIMER", 3000, npc, null);
}
break;
}
case 2:
{
if (npc.getCurrentHpPercent() < 70)
{
npcVars.set("ISTINA_STAGE", 3);
if (isExtremeMode(instance))
{
// myself->AddTimerEx(Seal_Timer, (3 * 1000));
}
// myself->AddTimerEx(Overcrowding_Timer, (10 * 1000));
}
break;
}
case 3:
{
if (npc.getCurrentHpPercent() < 55)
{
npcVars.set("ISTINA_STAGE", 4);
getTimers().addTimer("ERUPTION_TIMER", 50000, npc, null);
// myself->AddTimerEx(Creation_Timer, (Creation_Timer_Interval * 1000));
}
break;
}
case 4:
{
if (npc.getCurrentHpPercent() < 40)
{
npcVars.set("ISTINA_STAGE", 5);
if (isExtremeMode(instance))
{
// myself->AddTimerEx(Order_Timer, (Order_Timer_Interval * 100));
}
}
break;
}
case 5:
{
if (npc.getCurrentHpPercent() < 0.01)
{
setPlayerRewardInfo(npc);
npcVars.set("ISTINA_STAGE", 6);
getTimers().cancelTimer("DEATH_TIMER", npc, null);
getTimers().cancelTimer("DEATH_CHECK_TIMER", npc, null);
getTimers().cancelTimer("REFLECT_TIMER", npc, null);
getTimers().cancelTimer("REFLECT_CHECK_TIMER", npc, null);
getTimers().cancelTimer("AUTHORITY_TIMER", npc, null);
getTimers().cancelTimer("ERUPTION_TIMER", npc, null);
getTimers().cancelTimer("LOW_ERUPTION_TIMER", npc, null);
// myself->BlockTimer(Overcrowding_Timer);
if (isExtremeMode(instance))
{
// myself->BlockTimer(Seal_Timer);
// myself->BlockTimer(Order_Timer);
}
instance.getAliveNpcs(EXTREME_MINION, INVISIBLE_NPC).forEach(L2Npc::deleteMe);
instance.spawnGroup("BALLISTA");
instance.setStatus(2);
instance.getAliveNpcs(RUMIESE_INSTANCE).forEach(rumiese -> rumiese.teleToLocation(RUMIESE_LOC));
instance.getDoors().forEach(L2DoorInstance::openMe);
// myself->AddTimerEx(Broadcast_Timer, (2 * 1000));
onTimerEvent("AUTHORITY_END_TIMER", null, npc, null);
// myself->AddTimerEx(Location_Check_Timer, (4 * 1000));
npc.disableCoreAI(true);
npc.teleToLocation(DEFEAT_ISTINA_LOC);
npc.setDisplayEffect(3);
npc.setTargetable(false);
playMovie(instance, Movie.SC_ISTINA_BRIDGE);
instance.finishInstance(15);
}
break;
}
}
}
}
return super.onAttack(npc, attacker, damage, isSummon, skill);
}
@Override
public String onSpawn(L2Npc npc)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
if (npc.getId() == INVISIBLE_NPC)
{
npc.setTarget(npc);
npc.doCast(ERUPTION_1.getSkill());
}
else if (npc.getId() == BALLISTA)
{
npc.disableCoreAI(true);
npc.setUndying(true);
npc.setIsInvul(true);
npc.setTargetable(false);
getTimers().addTimer("BALLISTA_START_TIMER", 10000, npc, null);
}
}
return super.onSpawn(npc);
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
String htmltext = null;
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
switch (instance.getStatus())
{
case 0:
htmltext = "33293-01.html";
break;
case 1:
htmltext = "33293-02.html";
break;
case 2:
htmltext = "33293-03.html";
break;
case 3:
htmltext = "33293-04.html";
break;
case 4:
htmltext = "33293-05.html";
break;
}
}
return htmltext;
}
private boolean isExtremeMode(Instance instance)
{
return instance.getTemplateId() == TEMPLATE_ID_EXTREME;
}
private int getChargedPercent(int score, boolean isExtreme)
{
final int charged;
if (score >= (isExtreme ? PERFECT_SCORE_2 : PERFECT_SCORE_1))
{
charged = 100;
}
else
{
charged = (score * 100) / (isExtreme ? PERFECT_SCORE_2 : PERFECT_SCORE_1);
}
return charged;
}
private L2PcInstance setPlayerRewardInfo(L2Npc npc)
{
final Map<L2PcInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
final StatsSet npcVars = npc.getVariables();
L2PcInstance maxDealer = null;
int maxDamage = 0;
int totalDamage = 0;
for (AggroInfo info : ((L2Attackable) npc).getAggroList().values())
{
if (info == null)
{
continue;
}
final L2PcInstance attacker = info.getAttacker().getActingPlayer();
if (attacker != null)
{
final int damage = info.getDamage();
if (damage > 1)
{
if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, npc, attacker, true))
{
continue;
}
final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
reward.addDamage(damage);
if (reward.getDamage() > maxDamage)
{
maxDealer = attacker;
maxDamage = reward.getDamage();
}
totalDamage += damage;
}
}
}
npcVars.set("REWARD_PLAYER", maxDealer);
npcVars.set("REWARD_DAMAGE", totalDamage);
return maxDealer;
}
public static void main(String[] args)
{
new IstinaCavern();
}
}

View File

@@ -0,0 +1,7 @@
<html><body>Noeti Mimilead:<br>
We tracked down Kimerian only to find him deranged and very, very dangerous!<br>
Please, you must stop him before the Magmeld Fairies are gone forever! We want to help, too, and will send the bravest of the warrior fairies, Naomi Kasheron, to fight alongside you.<br>
This is <font color="LEVEL">Glimmer</font>, which you need to use when the fairies that are helping you become weak and defenseless. The <font color="LEVEL">Glimmer</font> will be very useful.<br>
You should also remember to use the <font color="LEVEL">Fairy's Leaf Flute</font>, if you have it! Its melodies will attract other fairies to fight alongside you!<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest KimerianCommon giveFlute">"Let's try that..."</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Noeti Mimilead:<br>
I don't think you have the Fairy's Leaf Flute! Remember, if you collect and bring me Certificates of Friendship, I can give you the Fairy's Leaf Flute. You can get Certificates of Friendship from the Fairy being held by Timiniel.
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Noeti Mimilead:<br>
Podvodn<EFBFBD>k chlupat<61> hnusn<73>! (noeti_mymirid_indun1002.htm)
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Noeti Mimilead:<br>
You faced Kimerian, even stood toe to toe with him!<br1>
This is amazing! Even though Kimerian ran away in the end, he'll at least know that he can't just rampage around as he pleases anymore. Thank you!<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h KimerianCommon zdrhamCus">"You're welcome. I will now head back to the village."</Button>
</body></html>

View File

@@ -0,0 +1,462 @@
/*
* 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.bosses.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()
{
super(TEMPLATE_ID);
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 (isInInstance(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 (isInInstance(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 (isInInstance(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 (isInInstance(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 (isInInstance(instance))
{
getTimers().cancelTimersOf(npc);
}
}
@Override
public String onSpawn(L2Npc npc)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(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 (isInInstance(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 (isInInstance(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);
}
}
public static void main(String[] args)
{
new KimerianCommon();
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Elite Bodyguard Naomi Kasheron:<br>
I will not take a party, friend. Just one. Just you.
</body></html>

View File

@@ -0,0 +1,548 @@
/*
* 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.bosses.Octavis;
import com.l2jmobius.commons.util.CommonUtil;
import com.l2jmobius.gameserver.enums.Movie;
import com.l2jmobius.gameserver.instancemanager.WalkingManager;
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
import com.l2jmobius.gameserver.model.L2World;
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.L2PcInstance;
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.model.skills.Skill;
import com.l2jmobius.gameserver.model.stats.Stats;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.type.L2ScriptZone;
import com.l2jmobius.gameserver.network.serverpackets.ExShowUsm;
import com.l2jmobius.gameserver.util.Util;
import instances.AbstractInstance;
/**
* Octavis Warzone instance zone.
* @author St3eT
*/
public final class OctavisWarzone extends AbstractInstance
{
// NPCs
private static final int[] OCTAVIS_STAGE_1 =
{
29191, // Common
29209, // Extreme
};
private static final int[] OCTAVIS_STAGE_2 =
{
29193, // Common
29211, // Extreme
};
private static final int[] OCTAVIS_STAGE_3 =
{
29194, // Common
29212, // Extreme
};
private static final int[] BEASTS =
{
29192, // Common
29210, // Extreme
};
private static final int[] BEASTS_MINIONS =
{
22929, // Common
23087, // Extreme
};
private static final int[] GLADIATORS =
{
22928, // Common
23086, // Extreme
};
private static final int LYDIA = 32892;
private static final int DOOR_MANAGER = 18984;
// Skills
private static final SkillHolder STAGE_2_SKILL_1 = new SkillHolder(14026, 1);
private static final SkillHolder STAGE_2_SKILL_2 = new SkillHolder(14027, 1);
private static final SkillHolder STAGE_2_SKILL_3 = new SkillHolder(14575, 1);
// Locations
private static final Location BATTLE_LOC = new Location(208720, 120576, -10000);
private static final Location OCTAVIS_SPAWN_LOC = new Location(207069, 120580, -9987);
private static final Location BEASTS_RANDOM_POINT = new Location(207244, 120579, -10008);
private static final Location[] BEASTS_MINIONS_LOC =
{
new Location(206681, 119327, -9987),
new Location(207724, 119303, -9987),
new Location(208472, 120047, -9987),
new Location(208484, 121110, -9987),
new Location(207730, 121859, -9987),
new Location(206654, 121865, -9987),
};
// Zones
private static final L2ScriptZone TELEPORT_ZONE = ZoneManager.getInstance().getZoneById(12042, L2ScriptZone.class);
// Misc
private static final int TEMPLATE_ID = 180;
private static final int EXTREME_TEMPLATE_ID = 181;
private static final int MAIN_DOOR_1 = 26210002;
private static final int MAIN_DOOR_2 = 26210001;
public OctavisWarzone()
{
super(TEMPLATE_ID, EXTREME_TEMPLATE_ID);
addStartNpc(LYDIA);
addTalkId(LYDIA);
addSpawnId(DOOR_MANAGER);
addSpawnId(GLADIATORS);
addAttackId(OCTAVIS_STAGE_1);
addAttackId(OCTAVIS_STAGE_2);
addAttackId(BEASTS);
addKillId(OCTAVIS_STAGE_1);
addKillId(OCTAVIS_STAGE_2);
addKillId(OCTAVIS_STAGE_3);
addMoveFinishedId(GLADIATORS);
addSpellFinishedId(OCTAVIS_STAGE_2);
addEnterZoneId(TELEPORT_ZONE.getId());
setCreatureSeeId(this::onCreatureSee, DOOR_MANAGER);
addInstanceCreatedId(TEMPLATE_ID, EXTREME_TEMPLATE_ID);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "enterEasyInstance":
{
enterInstance(player, npc, TEMPLATE_ID);
break;
}
case "enterExtremeInstance":
{
enterInstance(player, npc, EXTREME_TEMPLATE_ID);
break;
}
case "reenterInstance":
{
final Instance activeInstance = getPlayerInstance(player);
if (isInInstance(activeInstance))
{
enterInstance(player, npc, activeInstance.getTemplateId());
return "PartyMemberReenter.html";
}
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public void onTimerEvent(String event, StatsSet params, L2Npc npc, L2PcInstance player)
{
final Instance world = npc.getInstanceWorld();
if (isInInstance(world))
{
final StatsSet npcVars = npc.getVariables();
final StatsSet npcParams = npc.getParameters();
switch (event)
{
case "SECOND_DOOR_OPEN":
{
world.openCloseDoor(MAIN_DOOR_2, true);
break;
}
case "CLOSE_DOORS":
{
world.openCloseDoor(MAIN_DOOR_2, false);
world.openCloseDoor(MAIN_DOOR_1, false);
world.getParameters().set("TELEPORT_ACTIVE", true);
npc.teleToLocation(BATTLE_LOC);
playMovie(world, Movie.SC_OCTABIS_OPENING);
getTimers().addTimer("START_STAGE_1", 26500, npc, null);
break;
}
case "START_STAGE_1":
{
world.spawnGroup("STAGE_1");
world.getAliveNpcs(BEASTS).forEach(beasts ->
{
beasts.disableCoreAI(true);
beasts.setUndying(true);
((L2Attackable) beasts).setCanReturnToSpawnPoint(false);
final L2Npc octavis = addSpawn((!isExtremeMode(world) ? OCTAVIS_STAGE_1[0] : OCTAVIS_STAGE_1[1]), OCTAVIS_SPAWN_LOC, false, 0, false, world.getId());
octavis.disableCoreAI(true);
octavis.setIsRunning(true);
octavis.sendChannelingEffect(beasts, 1);
octavis.setTargetable(false);
((L2Attackable) octavis).setCanReturnToSpawnPoint(false);
getTimers().addRepeatingTimer("FOLLOW_BEASTS", 500, octavis, null);
getTimers().addRepeatingTimer("BEASTS_CHECK_HP", 5000, beasts, null);
WalkingManager.getInstance().startMoving(beasts, "octabis_superpoint");
});
break;
}
case "FOLLOW_BEASTS":
{
world.getAliveNpcs(BEASTS).forEach(beasts ->
{
addMoveToDesire(npc, beasts.getLocation(), 23);
npc.sendChannelingEffect(beasts, 1);
});
break;
}
case "BEASTS_CHECK_HP":
{
final int hpPer = npc.getCurrentHpPercent();
if ((hpPer < 50) && npc.isScriptValue(0))
{
npc.getStat().addFixedValue(Stats.REGENERATE_HP_RATE, 95000d);
npc.setScriptValue(1);
}
else if ((hpPer > 90) && npc.isScriptValue(1))
{
npc.getStat().addFixedValue(Stats.REGENERATE_HP_RATE, 0d);
npc.setScriptValue(0);
}
final L2Npc octavis = world.getAliveNpcs(OCTAVIS_STAGE_1).stream().findAny().orElse(null);
if (octavis != null)
{
octavis.setTargetable(hpPer < 50);
}
break;
}
case "END_STAGE_1":
{
playMovie(world, Movie.SC_OCTABIS_PHASECH_A);
getTimers().addTimer("START_STAGE_2", 12000, npc, null);
break;
}
case "START_STAGE_2":
{
world.spawnGroup("STAGE_2").forEach(octavis -> ((L2Attackable) octavis).setCanReturnToSpawnPoint(false));
break;
}
case "END_STAGE_2":
{
playMovie(world, Movie.SC_OCTABIS_PHASECH_B);
getTimers().addTimer("START_STAGE_3", 15000, npc, null);
break;
}
case "START_STAGE_3":
{
world.spawnGroup("STAGE_3").forEach(octavis -> ((L2Attackable) octavis).setCanReturnToSpawnPoint(false));
break;
}
case "END_STAGE_3":
{
playMovie(world, Movie.SC_OCTABIS_ENDING);
getTimers().addTimer("USM_SCENE_TIMER", 40000, npc, null);
break;
}
case "USM_SCENE_TIMER":
{
world.broadcastPacket(ExShowUsm.OCTAVIS_INSTANCE_END);
break;
}
case "GLADIATOR_START_SPAWN":
{
final int spawnIndex = npcVars.getInt("SPAWN_INDEX", 1);
if (spawnIndex < 7)
{
if (isExtremeMode(world))
{
world.spawnGroup("magmeld4_2621_gro" + spawnIndex + "m1");
}
else
{
world.spawnGroup("magmeld4_2621_gmo" + spawnIndex + "m1");
}
npcVars.set("SPAWN_INDEX", spawnIndex + 1);
getTimers().addTimer("GLADIATOR_START_SPAWN", 3000, npc, null);
}
break;
}
case "GLADIATOR_MOVING":
{
final int moveX = npcParams.getInt("Move_to_X", 0);
final int moveY = npcParams.getInt("Move_to_Y", 0);
if ((moveX != 0) && (moveY != 0))
{
npc.setIsRunning(true);
addMoveToDesire(npc, new Location(moveX, moveY, -10008), 23);
}
break;
}
case "BEASTS_MINIONS_SPAWN":
{
final Location loc = BEASTS_MINIONS_LOC[getRandom(BEASTS_MINIONS_LOC.length)];
final int count = getRandom(10);
for (int i = 0; i < count; i++)
{
final L2Npc beast = addSpawn((!isExtremeMode(world) ? BEASTS_MINIONS[0] : BEASTS_MINIONS[1]), loc, false, 0, false, world.getId());
beast.setIsRunning(true);
((L2Attackable) beast).setCanReturnToSpawnPoint(false);
addMoveToDesire(beast, Util.getRandomPosition(BEASTS_RANDOM_POINT, 500, 500), 23);
}
getTimers().addTimer("BEASTS_MINIONS_SPAWN", 30000 + (getRandom(10) * 1000), npc, null);
break;
}
case "MINION_CALL":
{
final L2PcInstance mostHated = ((L2Attackable) npc).getMostHated().getActingPlayer();
if ((mostHated != null) && (mostHated.calculateDistance(npc, true, false) < 5000))
{
L2World.getInstance().getVisibleObjects(npc, L2Attackable.class, 4000, obj -> CommonUtil.contains(BEASTS_MINIONS, obj.getId()) || CommonUtil.contains(GLADIATORS, obj.getId())).forEach(minion ->
{
addAttackPlayerDesire(minion, mostHated, 23);
});
}
getTimers().addTimer("MINION_CALL", 5000 + (getRandom(5) * 1000), npc, null);
break;
}
case "ATTACK_TIMER":
{
final L2Character mostHated = ((L2Attackable) npc).getMostHated();
if ((mostHated != null) && mostHated.isPlayable() && (npc.calculateDistance(mostHated, false, false) < 1000))
{
final int random = getRandom(5);
if (random < 3)
{
addSkillCastDesire(npc, mostHated, STAGE_2_SKILL_1, 23);
}
else if (random < 5)
{
addSkillCastDesire(npc, mostHated, STAGE_2_SKILL_2, 23);
}
}
getTimers().addTimer("ATTACK_TIMER", getRandom(7, 9) * 1000, npc, null);
break;
}
case "MEDUSA_SKILL_TIMER":
{
addSkillCastDesire(npc, npc, STAGE_2_SKILL_3, 23);
break;
}
}
}
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
final Instance world = npc.getInstanceWorld();
if (isInInstance(world))
{
final int hpPer = npc.getCurrentHpPercent();
if (CommonUtil.contains(OCTAVIS_STAGE_1, npc.getId()))
{
if (hpPer >= 90)
{
npc.setDisplayEffect(0);
}
else if (hpPer >= 80)
{
npc.setDisplayEffect(1);
}
else if (hpPer >= 70)
{
npc.setDisplayEffect(2);
}
else if (hpPer >= 60)
{
npc.setDisplayEffect(3);
}
else if (hpPer >= 50)
{
npc.setDisplayEffect(4);
}
else
{
npc.setDisplayEffect(5);
}
}
else if (CommonUtil.contains(OCTAVIS_STAGE_2, npc.getId()))
{
final StatsSet npcVars = npc.getVariables();
if (npcVars.getBoolean("START_TIMERS", true))
{
npcVars.set("START_TIMERS", false);
getTimers().addTimer("GLADIATOR_START_SPAWN", 6000, npc, null);
getTimers().addTimer("ATTACK_TIMER", 15000, npc, null);
getTimers().addTimer("MINION_CALL", 30000, npc, null);
// myself->AddTimerEx(Royal_Timer, 30 * 1000);
// myself->AddTimerEx(Scan_Timer, 1000);
getTimers().addTimer("BEASTS_MINIONS_SPAWN", 1000, npc, null);
// myself->AddTimerEx(Gladiator_Fishnet_Timer, 15 * 1000);
}
final int hpState = npcVars.getInt("HP_STATE", 0);
if ((npc.getMaxHp() - npc.getCurrentHp()) > (npc.getMaxHp() * 0.01 * hpState))
{
final int state = hpState % 5;
if (state == 0)
{
npc.setDisplayEffect(5);
getTimers().addTimer("MEDUSA_SKILL_TIMER", 15000, npc, null);
}
else
{
npc.setDisplayEffect(state);
}
npcVars.set("HP_STATE", hpState + 1);
}
}
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
final Instance world = npc.getInstanceWorld();
if (isInInstance(world))
{
if (CommonUtil.contains(OCTAVIS_STAGE_1, npc.getId()))
{
getTimers().cancelTimer("FOLLOW_BEASTS", npc, null);
world.getAliveNpcs(BEASTS).forEach(beast ->
{
getTimers().cancelTimer("BEASTS_CHECK_HP", beast, null);
beast.teleToLocation(new Location(-113360, -244676, -15536)); // Don't even ask, it's pure hack. - St3eT 2k16
beast.deleteMe();
});
getTimers().addTimer("END_STAGE_1", 1000, npc, null);
}
else if (CommonUtil.contains(OCTAVIS_STAGE_2, npc.getId()))
{
// Cancel timers
getTimers().cancelTimer("BEASTS_MINIONS_SPAWN", npc, null);
getTimers().cancelTimer("MINION_CALL", npc, null);
getTimers().cancelTimer("ATTACK_TIMER", npc, null);
getTimers().cancelTimer("MEDUSA_SKILL_TIMER", npc, null);
// Despawn beasts
world.getAliveNpcs(BEASTS_MINIONS).forEach(beast -> beast.doDie(null));
// Despawn gladiators
for (int i = 1; i < 7; i++)
{
world.despawnGroup(isExtremeMode(world) ? ("magmeld4_2621_gro" + i + "m1") : ("magmeld4_2621_gmo" + i + "m1"));
}
getTimers().addTimer("END_STAGE_2", 3000, npc, null);
}
else if (CommonUtil.contains(OCTAVIS_STAGE_3, npc.getId()))
{
world.finishInstance();
getTimers().addTimer("END_STAGE_3", 2000, npc, null);
}
}
return super.onKill(npc, killer, isSummon);
}
@Override
public void onInstanceCreated(Instance instance, L2PcInstance player)
{
if ((player != null) && isInInstance(instance))
{
showHtmlFile(player, (instance.getTemplateId() == TEMPLATE_ID) ? "PartyEnterCommon.html" : "PartyEnterExtreme.html");
}
}
@Override
public String onSpawn(L2Npc npc)
{
final Instance world = npc.getInstanceWorld();
if (isInInstance(world))
{
if (CommonUtil.contains(GLADIATORS, npc.getId()))
{
npc.setRandomWalking(false);
world.openCloseDoor(npc.getParameters().getInt("My_DoorName", -1), true);
getTimers().addTimer("GLADIATOR_MOVING", 3000, npc, null);
}
npc.initSeenCreatures();
}
return super.onSpawn(npc);
}
@Override
public void onMoveFinished(L2Npc npc)
{
final Instance world = npc.getInstanceWorld();
if (isInInstance(world))
{
world.openCloseDoor(npc.getParameters().getInt("My_DoorName", -1), false);
}
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
if (skill.getId() == STAGE_2_SKILL_3.getSkillId())
{
npc.setDisplayEffect(6);
}
return super.onSpellFinished(npc, player, skill);
}
public void onCreatureSee(OnCreatureSee event)
{
final L2Character creature = event.getSeen();
final L2Npc npc = (L2Npc) event.getSeer();
final Instance world = npc.getInstanceWorld();
if (isInInstance(world) && creature.isPlayer() && npc.isScriptValue(0))
{
world.openCloseDoor(MAIN_DOOR_1, true);
getTimers().addTimer("SECOND_DOOR_OPEN", 3000, npc, null);
getTimers().addTimer("CLOSE_DOORS", 60000, npc, null);
npc.setScriptValue(1);
}
}
@Override
public String onEnterZone(L2Character character, L2ZoneType zone)
{
final Instance world = character.getInstanceWorld();
if (character.isPlayer() && isInInstance(world))
{
if (world.getParameters().getBoolean("TELEPORT_ACTIVE", false))
{
character.teleToLocation(BATTLE_LOC);
}
}
return super.onEnterZone(character, zone);
}
private boolean isExtremeMode(Instance instance)
{
return instance.getTemplateId() == EXTREME_TEMPLATE_ID;
}
public static void main(String[] args)
{
new OctavisWarzone();
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Divine Messenger Lydia:<br>
I will pray that you defeat Octavis... I hope your decision is the right one... I will pray.
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Divine Messenger Lydia:<br>
I will pray that you save the soul of Octavis...
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Divine Messenger Lydia:<br>
Please prove your decision is the right one and help your members.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Divine Messenger Lydia:<br>
That many people can't be moved.<br>
(A maximum of 35 people can participate.)
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Divine Messenger Lydia:<br>
As I explained earlier, you can enter only by forming an association.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Divine Messenger Lydia:<br>
I don't think you are quite prepared yet.<br>
(Party includes character(s) <font color="LEVEL">under level 95</font>.)
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Divine Messenger Lydia:<br>
I don't think you are quite prepared yet.<br>
(Party includes character(s) <font color="LEVEL">under level 97</font>.)
</body></html>

View File

@@ -14,7 +14,7 @@
* 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.areas.SeaOfSpores;
package ai.bosses.Orfen;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

View File

@@ -14,7 +14,7 @@
* 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.areas.Wastelands;
package ai.bosses.QueenAnt;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

View File

@@ -14,7 +14,7 @@
* 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.areas.StakatoNest;
package ai.bosses.QueenShyeed;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.instancemanager.ZoneManager;

View File

@@ -14,7 +14,7 @@
* 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.areas.PrimevalIsle.Sailren;
package ai.bosses.Sailren;
import com.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
import com.l2jmobius.gameserver.instancemanager.ZoneManager;

View File

@@ -14,7 +14,7 @@
* 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.areas.PrisonOfDarkness.Cannon;
package ai.bosses.Spezion.Cannon;
import java.util.HashMap;
import java.util.Map;
@@ -55,7 +55,6 @@ public final class Cannon extends AbstractNpcAI
private static final int F_MEMORY_FRAGMENT = 17613; // Frightening Memory Fragment
// Misc
private static final Map<Integer, Integer> TRANSFORM_DATA = new HashMap<>();
static
{
TRANSFORM_DATA.put(22965, 22979); // Novice Phantom -> Novice Escort Swordsman

View File

@@ -14,7 +14,7 @@
* 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.areas.PrisonOfDarkness;
package ai.bosses.Spezion;
import com.l2jmobius.gameserver.model.actor.L2Npc;

View File

@@ -0,0 +1,4 @@
<html><body>Finaria:<br>
Welcome back! I've been waiting for you. A fierce battle between the <font color="LEVEL">Revolutionaries</font> and <font color="LEVEL">Kundas</font>.<br>
Be careful! If all the <font color="LEVEL">Revolutionaries</font> fall, our plans to the end! Help <font color="LEVEL">Revolutionaries</font> to beat <font color="LEVEL">Kunda</font>. Before everyone power <font color="LEVEL">Revolutionaries</font> run out of, you must immediately kill <font color="LEVEL">Tauti</font>!<br>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Teleport Device:<br>
You do not have the key.<br>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Teleport Device:<br>
Mechanical device. Requires key.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest TautiWarzone useKey">"Use key"</Button>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Teleport Device:<br>
Teleport Device is now working.<br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest TautiWarzone teleport">"Move"</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Sizrak:<br>
I will pray that you defeat Tauti... I hope your decision is the right one... I will pray.
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Sizrak:<br>
We will win! We must!
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Sizrak:<br>
Please prove your decision is the right one and help your members.
</body></html>

View File

@@ -0,0 +1,241 @@
/*
* 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.bosses.Tauti;
import java.util.List;
import com.l2jmobius.gameserver.enums.Movie;
import com.l2jmobius.gameserver.model.Location;
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.instancezone.Instance;
import instances.AbstractInstance;
/**
* Tauti Warzone instance zone.
* @author Mobius
*/
public final class TautiWarzone extends AbstractInstance
{
// NPCs
private static final int FINARIA = 33675;
private static final int ZAHAK = 19266;
private static final int TELEPORTER = 33678;
private static final int TAUTI_COMMON = 29233;
private static final int TAUTI_EXTREME = 29234;
private static final int TAUTI_COMMON_AXE = 29236;
private static final int TAUTI_EXTREME_AXE = 29237;
// Item
private static final int KEY_OF_DARKNESS = 34899;
// Teleport
private static final Location TAUTI_TELEPORT = new Location(-148972, 209879, -10199);
// Misc
private static final int TEMPLATE_ID = 218;
private static final int EXTREME_TEMPLATE_ID = 219;
private static final int DOOR_1 = 15240001;
private static final int DOOR_2 = 15240002;
public TautiWarzone()
{
super(TEMPLATE_ID, EXTREME_TEMPLATE_ID);
addTalkId(FINARIA, TELEPORTER);
addFirstTalkId(FINARIA, TELEPORTER);
addAttackId(TAUTI_COMMON, TAUTI_EXTREME);
addKillId(ZAHAK, TAUTI_COMMON_AXE, TAUTI_EXTREME_AXE);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "enterEasyInstance":
{
enterInstance(player, npc, TEMPLATE_ID);
startQuestTimer("WORLD_STATUS_CHECK", 5000, null, player, false);
break;
}
case "enterExtremeInstance":
{
enterInstance(player, npc, EXTREME_TEMPLATE_ID);
startQuestTimer("WORLD_STATUS_CHECK", 5000, null, player, false);
break;
}
case "useKey":
{
final Instance world = npc.getInstanceWorld();
if (hasAtLeastOneQuestItem(player, KEY_OF_DARKNESS))
{
takeItems(player, KEY_OF_DARKNESS, -1);
world.setStatus(3);
return "33678-3.htm";
}
return "33678-1.htm";
}
case "teleport":
{
final Instance world = npc.getInstanceWorld();
world.setStatus(4);
world.openCloseDoor(DOOR_2, true);
for (L2PcInstance member : world.getPlayers())
{
member.teleToLocation(TAUTI_TELEPORT, world);
startQuestTimer("PLAY_OPENING_B_MOVIE", 5000, null, member, false);
}
startQuestTimer("SPAWN_TAUTI", 60000, npc, null, false);
break;
}
case "PLAY_OPENING_B_MOVIE":
{
playMovie(player, Movie.SC_TAUTI_OPENING_B);
break;
}
case "SPAWN_TAUTI":
{
final Instance world = npc.getInstanceWorld();
world.openCloseDoor(DOOR_1, true);
world.spawnGroup("boss");
break;
}
case "SPAWN_AXE":
{
final L2Npc axe = addSpawn(npc.getId() == TAUTI_EXTREME ? TAUTI_EXTREME_AXE : TAUTI_COMMON_AXE, npc, false, 0, false, npc.getInstanceId());
axe.setRandomWalking(false);
axe.setIsImmobilized(true);
break;
}
case "WORLD_STATUS_CHECK":
{
if ((player == null) || (player.getInstanceId() == 0))
{
return null;
}
final Instance world = player.getInstanceWorld();
if (world.isStatus(0))
{
world.setStatus(1);
world.spawnGroup("room1");
playMovie(world.getPlayers(), Movie.SC_TAUTI_OPENING);
for (L2PcInstance member : world.getPlayers())
{
takeItems(member, KEY_OF_DARKNESS, -1);
}
startQuestTimer("WORLD_STATUS_CHECK", 5000, null, player, false);
}
else if (world.isStatus(1))
{
if (world.getAliveNpcs(L2MonsterInstance.class).isEmpty())
{
world.setStatus(2);
final List<L2Npc> monsters = world.spawnGroup("room2");
for (L2Npc monster : monsters)
{
monster.setRandomWalking(false);
}
}
startQuestTimer("WORLD_STATUS_CHECK", 5000, null, player, false);
}
return null;
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
String htmltext = "";
switch (npc.getId())
{
case FINARIA:
{
htmltext = "33675.htm";
break;
}
case TELEPORTER:
{
final int worldStatus = npc.getInstanceWorld().getStatus();
if (worldStatus > 2)
{
htmltext = "33678-3.htm";
}
else if ((worldStatus == 2) && hasAtLeastOneQuestItem(player, KEY_OF_DARKNESS))
{
htmltext = "33678-2.htm";
}
else
{
htmltext = "33678-1.htm";
}
break;
}
}
return htmltext;
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
final Instance world = npc.getInstanceWorld();
if (world.isStatus(5) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.15)))
{
world.setStatus(6);
npc.deleteMe();
startQuestTimer("SPAWN_AXE", 15000, npc, null, false);
playMovie(world.getPlayers(), Movie.SC_TAUTI_PHASE);
}
if (world.isStatus(4))
{
world.setStatus(5);
world.openCloseDoor(DOOR_1, false);
world.openCloseDoor(DOOR_2, false);
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
if (npc.getId() == ZAHAK)
{
npc.dropItem(killer, KEY_OF_DARKNESS, 1);
}
else
{
final Instance world = npc.getInstanceWorld();
playMovie(world.getPlayers(), Movie.SC_TAUTI_ENDING);
npc.deleteMe();
}
return super.onKill(npc, killer, isSummon);
}
@Override
public void onInstanceCreated(Instance instance, L2PcInstance player)
{
if (player != null)
{
showHtmlFile(player, instance.getTemplateId() == EXTREME_TEMPLATE_ID ? "PartyEnterExtreme.html" : "PartyEnterCommon.html");
}
}
public static void main(String[] args)
{
new TautiWarzone();
}
}

View File

@@ -0,0 +1,4 @@
<html><body>Sizrak:<br>
That many people can't be moved.<br>
(A maximum of 35 people can participate.)
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Sizrak:<br>
As I explained earlier, you can enter only by forming an association.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Sizrak:<br>
I don't think you are quite prepared yet.<br>
(Party includes character(s) <font color="LEVEL">under level 95</font>.)
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Sizrak:<br>
I don't think you are quite prepared yet.<br>
(Party includes character(s) <font color="LEVEL">under level 97</font>.)
</body></html>

View File

@@ -0,0 +1,624 @@
/*
* 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.bosses.Teredor;
import java.util.HashMap;
import java.util.Map;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.instancemanager.WalkingManager;
import com.l2jmobius.gameserver.model.L2Object;
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.L2PcInstance;
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.model.skills.Skill;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import instances.AbstractInstance;
/**
* Teredor Warzone instance zone.
* @author St3eT
*/
public final class TeredorWarzone extends AbstractInstance
{
// NPCs
private static final int FILAUR = 30535;
private static final int TEREDOR = 25785;
private static final int FAKE_TEREDOR = 25801;
private static final int TEREDOR_POISON = 18998;
private static final int BEETLE = 19024;
private static final int POS_CHECKER = 18999;
private static final int EGG_2 = 18997;
private static final int ELITE_MILLIPADE = 19015;
private static final int AWAKENED_MILLIPADE = 18995; // Awakened Millipede
private static final int HATCHET_MILLIPADE = 18993; // Hatched Millipede
private static final int HATCHET_UNDERBUG = 18994; // Hatched Underbug
private static final int TEREDOR_LARVA = 19016; // Teredor's Larva
private static final int MUTANTED_MILLIPADE = 19000; // Mutated Millipede
// Items
private static final int FAKE_TEREDOR_WEAPON = 15280;
// Skill
private static final SkillHolder FAKE_TEREDOR_JUMP_SKILL = new SkillHolder(6268, 1);
private static final SkillHolder POISON_SKILL = new SkillHolder(14113, 1);
private static final SkillHolder BEETLE_SKILL = new SkillHolder(14412, 1);
private static final SkillHolder TEREDOR_POISON_SKILL = new SkillHolder(14112, 1);
private static final SkillHolder TEREDOR_POISON_SKILL_2 = new SkillHolder(14112, 2);
private static final SkillHolder TEREDOR_CANCEL = new SkillHolder(5902, 1);
// Misc
private static final int TEMPLATE_ID = 160;
//@formatter:off
private static final Map<Integer, String[]> WALKING_DATA = new HashMap<>();
static
{
WALKING_DATA.put(1, new String[] {"trajan101", "trajan102", "trajan103", "trajan104", "trajan105"});
WALKING_DATA.put(2, new String[] {"trajan106", "trajan107", "trajan108", "trajan109", "trajan110"});
WALKING_DATA.put(3, new String[] {"trajan111", "trajan112", "trajan113"});
WALKING_DATA.put(4, new String[] {"trajan114", "trajan115"});
WALKING_DATA.put(5, new String[] {"trajan116", "trajan117"});
WALKING_DATA.put(6, new String[] {"trajan118", "trajan119", "trajan120"});
WALKING_DATA.put(7, new String[] {"trajan121", "trajan122"});
WALKING_DATA.put(8, new String[] {"trajan14", "trajan15", "trajan16"});
}
//@formatter:on
public TeredorWarzone()
{
super(TEMPLATE_ID);
addStartNpc(FILAUR);
addTalkId(FILAUR);
addSpawnId(BEETLE, POS_CHECKER, EGG_2, FAKE_TEREDOR, TEREDOR);
addSpellFinishedId(BEETLE);
addEventReceivedId(EGG_2);
addAttackId(TEREDOR);
addKillId(EGG_2, TEREDOR);
setCreatureSeeId(this::onCreatureSee, BEETLE, POS_CHECKER, EGG_2, FAKE_TEREDOR);
}
@Override
public void onTimerEvent(String event, StatsSet params, L2Npc npc, L2PcInstance player)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcVars = npc.getVariables();
final StatsSet npcParams = npc.getParameters();
switch (event)
{
case "EGG_SPAWN_TIMER":
{
final L2Npc minion = addSpawn(AWAKENED_MILLIPADE, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0, false, instance.getId());
WalkingManager.getInstance().startMoving(minion, getRandomEntry(WALKING_DATA.get(npcParams.getInt("Spot", 0))));
npc.deleteMe();
break;
}
case "FAKE_TEREDOR_POISON_TIMER":
{
final L2Npc minion = addSpawn(TEREDOR_POISON, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0, false, instance.getId());
getTimers().addTimer("POISON_TIMER", 5000, minion, null);
getTimers().addTimer("POISON_TIMER", 10000, minion, null);
getTimers().addTimer("POISON_TIMER", 15000, minion, null);
getTimers().addTimer("POISON_TIMER", 20000, minion, null);
getTimers().addTimer("DELETE_ME", 22000, minion, null);
break;
}
case "POISON_TIMER":
{
addSkillCastDesire(npc, npc, POISON_SKILL, 23);
break;
}
case "DELETE_ME":
{
npc.deleteMe();
break;
}
case "TEREDOR_LAIR_CHECK":
{
final Location spawnLoc = npc.getSpawn().getLocation();
if (((spawnLoc.getX() - npc.getX()) > 1000) || ((spawnLoc.getX() - npc.getX()) < -2000))
{
showOnScreenMsg(instance, NpcStringId.TEREDOR_SUMMONS_SUBORDINATE_BECAUSE_YOU_MOVED_OUT_OF_TEREDOR_S_AREA, ExShowScreenMessage.TOP_CENTER, 4000);
addSpawn(ELITE_MILLIPADE, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0, false, instance.getId());
}
break;
}
case "TEREDOR_BUHATIMER":
{
npcVars.increaseInt("i_ai3", 0, 1);
break;
}
case "TEREDOR_POISON_TIMER":
{
final int i_ai4 = npcVars.increaseInt("i_ai4", 0, 1);
if (i_ai4 == 7)
{
npcVars.increaseInt("i_ai4", 0, -7);
}
else
{
// myself->CreateOnePrivateEx(18998, "trajan_poison_dummy", 0, 0, gg->FloatToInt(myself->sm->x), gg->FloatToInt(myself->sm->y), gg->FloatToInt(myself->sm->z), 0, 0, 0, 0); //TODO:
getTimers().addTimer("TEREDOR_POISON_TIMER", 2000, npc, null);
}
break;
}
case "TEREDOR_RUNTIMER_1":
case "TEREDOR_RUNTIMER_2":
case "TEREDOR_RUNTIMER_3":
case "TEREDOR_RUNTIMER_4":
{
npc.disableCoreAI(false);
npc.setTargetable(true);
npc.broadcastSocialAction(3);
break;
}
}
}
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("enterInstance"))
{
enterInstance(player, npc, TEMPLATE_ID);
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSpawn(L2Npc npc)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcParams = npc.getParameters();
switch (npc.getId())
{
case TEREDOR:
{
WalkingManager.getInstance().startMoving(npc, "trajan5");
getTimers().addRepeatingTimer("TEREDOR_LAIR_CHECK", 5000, npc, null);
((L2Attackable) npc).setCanReturnToSpawnPoint(false);
npc.initSeenCreatures();
break;
}
case BEETLE:
{
if (npcParams.getInt("Sp", 0) == 1)
{
WalkingManager.getInstance().startMoving(npc, npcParams.getString("SuperPointName1", ""));
}
npc.initSeenCreatures();
break;
}
case FAKE_TEREDOR:
{
WalkingManager.getInstance().startMoving(npc, npcParams.getString("SuperPointName", ""));
npc.setRHandId(FAKE_TEREDOR_WEAPON);
npc.initSeenCreatures();
getTimers().addTimer("FAKE_TEREDOR_POISON_TIMER", 3000, npc, null);
break;
}
default:
{
npc.initSeenCreatures();
break;
}
}
}
return super.onSpawn(npc);
}
public void onCreatureSee(OnCreatureSee event)
{
final L2Character creature = event.getSeen();
final L2Npc npc = (L2Npc) event.getSeer();
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcParams = npc.getParameters();
switch (npc.getId())
{
case BEETLE:
{
if (creature.isPlayer() && npc.isScriptValue(0))
{
npc.setScriptValue(1);
addSkillCastDesire(npc, npc, BEETLE_SKILL, 23);
}
break;
}
case FAKE_TEREDOR:
{
if (creature.isPlayer() && npc.isScriptValue(0))
{
npc.setScriptValue(1);
addSkillCastDesire(npc, npc, FAKE_TEREDOR_JUMP_SKILL, 23);
getTimers().addTimer("FAKE_TEREDOR_ELITE_REUSE", 30000, n -> npc.setScriptValue(0));
final L2Npc minion = addSpawn(ELITE_MILLIPADE, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0, false, instance.getId());
addAttackPlayerDesire(minion, creature.getActingPlayer());
}
break;
}
case POS_CHECKER:
{
if (creature.isPlayer() && npc.isScriptValue(0))
{
npc.setScriptValue(1);
final int spot = npcParams.getInt("Spot", 0);
switch (spot)
{
case 1:
{
instance.spawnGroup("schuttgart29_2512_sp1m1");
npc.broadcastEvent("SCE_BREAK_AN_EGG1", 800, null);
getTimers().addTimer("EGG_SPAWN_TIMER_2", 30000, n -> npc.broadcastEvent("SCE_BREAK_AN_EGG2", 800, creature));
break;
}
case 3:
{
instance.spawnGroup("schuttgart29_2512_sp2m1");
npc.broadcastEvent("SCE_BREAK_AN_EGG1", 800, null);
getTimers().addTimer("EGG_SPAWN_TIMER_2", 30000, n -> npc.broadcastEvent("SCE_BREAK_AN_EGG2", 800, creature));
break;
}
case 5:
{
instance.spawnGroup("schuttgart29_2512_sp4m1");
break;
}
case 6:
{
instance.spawnGroup("schuttgart29_2512_306m1");
npc.broadcastEvent("SCE_BREAK_AN_EGG1", 800, null);
getTimers().addTimer("EGG_SPAWN_TIMER_2", 30000, n -> npc.broadcastEvent("SCE_BREAK_AN_EGG2", 800, creature));
break;
}
case 7:
{
instance.spawnGroup("schuttgart29_2512_305m1");
npc.broadcastEvent("SCE_BREAK_AN_EGG1", 800, null);
getTimers().addTimer("EGG_SPAWN_TIMER_2", 30000, n -> npc.broadcastEvent("SCE_BREAK_AN_EGG2", 800, creature));
break;
}
}
}
break;
}
case EGG_2:
{
if (creature.isPlayer() && npc.isScriptValue(0))
{
npc.setScriptValue(1);
getTimers().addTimer("EGG_SPAWN_TIMER", (180 + getRandom(120)) * 1000, npc, null);
npc.getVariables().set("SEE_CREATURE_ID", creature.getObjectId());
}
break;
}
}
}
}
@Override
public String onEventReceived(String eventName, L2Npc sender, L2Npc npc, L2Object reference)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
switch (npc.getId())
{
case EGG_2:
{
switch (eventName)
{
case "SCE_EGG_DIE":
{
npc.setDisplayEffect(2);
final L2PcInstance player = instance.getPlayerById(npc.getVariables().getInt("SEE_CREATURE_ID", 0));
if (player != null)
{
final L2Npc minion = addSpawn(getRandomBoolean() ? HATCHET_MILLIPADE : HATCHET_UNDERBUG, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0, false, instance.getId());
addAttackPlayerDesire(minion, player, 23);
npc.deleteMe();
}
break;
}
case "SCE_BREAK_AN_EGG1":
{
npc.setDisplayEffect(2);
break;
}
case "SCE_BREAK_AN_EGG2":
{
final L2PcInstance player = reference == null ? instance.getPlayerById(npc.getVariables().getInt("SEE_CREATURE_ID", 0)) : reference.getActingPlayer();
int npcId = 0;
switch (npc.getParameters().getInt("Spot", 0))
{
case 1:
npcId = getRandomBoolean() ? TEREDOR_LARVA : MUTANTED_MILLIPADE;
break;
case 2:
case 3:
npcId = getRandomBoolean() ? MUTANTED_MILLIPADE : HATCHET_UNDERBUG;
break;
case 4:
case 5:
case 6:
npcId = getRandomBoolean() ? MUTANTED_MILLIPADE : HATCHET_UNDERBUG;
break;
case 7:
npcId = getRandomEntry(MUTANTED_MILLIPADE, HATCHET_UNDERBUG, HATCHET_MILLIPADE);
break;
}
if (npcId > 0)
{
final L2Npc minion = addSpawn(npcId, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0, false, instance.getId());
if ((player != null) && (minion.calculateDistance(player, true, false) < 2000))
{
addAttackPlayerDesire(minion, player, 23);
}
npc.deleteMe();
}
break;
}
case "SCE_BREAK_AN_EGG3":
{
npc.setDisplayEffect(4);
break;
}
}
break;
}
}
}
return super.onEventReceived(eventName, sender, npc, reference);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
switch (npc.getId())
{
case TEREDOR:
{
final StatsSet npcVars = npc.getVariables();
final int hpPer = npc.getCurrentHpPercent();
int teredorStatus = npcVars.getInt("TEREDOR_STATUS", 1);
if ((npc.distFromMe(attacker) > 450) && (getRandom(100) < 5))
{
addSkillCastDesire(npc, attacker, TEREDOR_POISON_SKILL, 23);
// myself->CreateOnePrivateEx(18998, "trajan_poison_dummy", 0, 0, gg->FloatToInt(attacker->x), gg->FloatToInt(attacker->y), gg->FloatToInt(attacker->z), 0, 0, 0, 0);
}
if ((hpPer <= 80) && (hpPer >= 60))
{
if (teredorStatus == 1)
{
addSkillCastDesire(npc, npc, TEREDOR_CANCEL, 23);
teredorStatus = npcVars.increaseInt("TEREDOR_STATUS", 1);
npc.disableCoreAI(true);
npc.setTargetable(false);
npc.breakAttack();
npc.breakCast();
npc.setWalking();
((L2Attackable) npc).clearAggroList();
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
npc.broadcastSocialAction(4);
WalkingManager.getInstance().resumeMoving(npc);
getTimers().addTimer("TEREDOR_BUHATIMER", 10000, npc, null);
getTimers().addTimer("TEREDOR_RUNTIMER_1", 30000, npc, null);
getTimers().addTimer("TEREDOR_POISON_TIMER", 2000, npc, null);
}
else if (getRandom(100) < 1)
{
addSkillCastDesire(npc, attacker, TEREDOR_POISON_SKILL, 23);
// myself->CreateOnePrivateEx(18998, "trajan_poison_dummy", 0, 0, gg->FloatToInt(attacker->x), gg->FloatToInt(attacker->y), gg->FloatToInt(attacker->z), 0, 0, 0, 0);
}
}
else if ((hpPer <= 60) && (hpPer >= 40))
{
if (teredorStatus == 2)
{
addSkillCastDesire(npc, npc, TEREDOR_CANCEL, 23);
teredorStatus = npcVars.increaseInt("TEREDOR_STATUS", 1);
npc.disableCoreAI(true);
npc.setTargetable(false);
npc.breakAttack();
npc.breakCast();
npc.setWalking();
((L2Attackable) npc).clearAggroList();
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
npc.broadcastSocialAction(4);
WalkingManager.getInstance().resumeMoving(npc);
// myself->BroadcastScriptEvent(@SCE_EGG_SPAWN5, 0, 3000);
getTimers().addTimer("TEREDOR_BUHATIMER", 10000, npc, null);
getTimers().addTimer("TEREDOR_RUNTIMER_2", 30000, npc, null);
getTimers().addTimer("TEREDOR_POISON_TIMER", 2000, npc, null);
}
else if (getRandom(100) < 3)
{
addSkillCastDesire(npc, attacker, TEREDOR_POISON_SKILL, 23);
// myself->CreateOnePrivateEx(18998, "trajan_poison_dummy", 0, 0, gg->FloatToInt(attacker->x), gg->FloatToInt(attacker->y), gg->FloatToInt(attacker->z), 0, 0, 0, 0);
}
}
else if ((hpPer <= 40) && (hpPer >= 20))
{
if (teredorStatus == 3)
{
addSkillCastDesire(npc, npc, TEREDOR_CANCEL, 23);
// if (myself->i_ai2 == 1)
// {
// myself->AddUseSkillDesire(myself->sm, toggle_shield1, @HEAL, @STAND, 500000000);
// myself->ChangeNPCState(myself->sm, 4);
// myself->i_ai2 = myself->i_ai2 - 1;
// }
// if (myself->i_ai2 == 2)
// {
// myself->AddUseSkillDesire(myself->sm, toggle_shield2, @HEAL, @STAND, 500000000);
npc.setDisplayEffect(4);
// myself->i_ai2 = myself->i_ai2 - 2;
// }
teredorStatus = npcVars.increaseInt("TEREDOR_STATUS", 1);
npc.disableCoreAI(true);
npc.setTargetable(false);
npc.breakAttack();
npc.breakCast();
npc.setWalking();
((L2Attackable) npc).clearAggroList();
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
npc.broadcastSocialAction(4);
WalkingManager.getInstance().resumeMoving(npc);
// myself->BroadcastScriptEvent(@SCE_TRAJAN_EGG_DIE, gg->GetIndexFromCreature(c0), 3000);
// myself->BroadcastScriptEvent(@SCE_EGG_SPAWN6, 0, 3000);
getTimers().addTimer("TEREDOR_BUHATIMER", 10000, npc, null);
getTimers().addTimer("TEREDOR_RUNTIMER_3", 30000, npc, null);
getTimers().addTimer("TEREDOR_POISON_TIMER", 2000, npc, null);
}
else if (getRandom(100) < 5)
{
addSkillCastDesire(npc, attacker, TEREDOR_POISON_SKILL, 23);
// myself->CreateOnePrivateEx(18998, "trajan_poison_dummy", 0, 0, gg->FloatToInt(attacker->x), gg->FloatToInt(attacker->y), gg->FloatToInt(attacker->z), 0, 0, 0, 0);
}
}
else if (hpPer < 20)
{
if (teredorStatus == 4)
{
addSkillCastDesire(npc, npc, TEREDOR_CANCEL, 23);
// if (myself->i_ai2 == 1)
// {
// myself->AddUseSkillDesire(myself->sm, toggle_shield1, @HEAL, @STAND, 500000000);
// myself->ChangeNPCState(myself->sm, 4);
// myself->i_ai2 = myself->i_ai2 - 1;
// }
// if (myself->i_ai2 == 2)
// {
// myself->AddUseSkillDesire(myself->sm, toggle_shield2, @HEAL, @STAND, 500000000);
npc.setDisplayEffect(4);
// myself->i_ai2 = myself->i_ai2 - 2;
// }
teredorStatus = npcVars.increaseInt("TEREDOR_STATUS", 1);
npc.disableCoreAI(true);
npc.setTargetable(false);
npc.breakAttack();
npc.breakCast();
npc.setWalking();
((L2Attackable) npc).clearAggroList();
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
npc.broadcastSocialAction(4);
WalkingManager.getInstance().resumeMoving(npc);
// myself->BroadcastScriptEvent(@SCE_TRAJAN_EGG_DIE, gg->GetIndexFromCreature(c0), 3000);
// myself->BroadcastScriptEvent(@SCE_EGG_SPAWN7, 0, 3000);
// myself->AddUseSkillDesire(myself->sm, Lastskill, @HEAL, @STAND, 500000000);
npc.setDisplayEffect(1);
getTimers().addTimer("TEREDOR_BUHATIMER", 10000, npc, null);
getTimers().addTimer("TEREDOR_RUNTIMER_4", 30000, npc, null);
getTimers().addTimer("TEREDOR_POISON_TIMER", 2000, npc, null);
}
else if (getRandom(100) < 5)
{
addSkillCastDesire(npc, attacker, TEREDOR_POISON_SKILL_2, 23);
// myself->CreateOnePrivateEx(18998, "trajan_poison_dummy", 0, 0, gg->FloatToInt(attacker->x), gg->FloatToInt(attacker->y), gg->FloatToInt(attacker->z), 0, 0, 0, 0);
}
else if (getRandom(100) < 5)
{
// myself->AddUseSkillDesire(attacker, Specialskill1, @ATTACK, @MOVE_TO_TARGET, 1000000);
}
}
else if ((teredorStatus == 5) && (hpPer < 7))
{
// myself->BroadcastScriptEvent(@SCE_ALL_BREAK_AN_EGG5, gg->GetIndexFromCreature(c0), 3000);
teredorStatus = npcVars.increaseInt("TEREDOR_STATUS", 1);
}
break;
}
}
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
switch (npc.getId())
{
case TEREDOR:
{
instance.finishInstance();
break;
}
case EGG_2:
{
if (getRandom(4) < 3)
{
final L2Npc minion = addSpawn(getRandomBoolean() ? MUTANTED_MILLIPADE : TEREDOR_LARVA, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0, false, instance.getId());
addAttackPlayerDesire(minion, killer, 23);
npc.deleteMe();
}
break;
}
}
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
switch (npc.getId())
{
case BEETLE:
{
npc.broadcastEvent("SCE_EGG_DIE", 500, null);
break;
}
}
}
return super.onSpellFinished(npc, player, skill);
}
public static void main(String[] args)
{
new TeredorWarzone();
}
}

Some files were not shown because too many files have changed in this diff Show More