552 lines
16 KiB
Java
552 lines
16 KiB
Java
/*
|
|
* 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 instances.OctavisWarzone;
|
|
|
|
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()
|
|
{
|
|
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 (isOctavisInstance(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 (isOctavisInstance(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 (isOctavisInstance(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 (isOctavisInstance(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) && isOctavisInstance(instance))
|
|
{
|
|
showHtmlFile(player, (instance.getTemplateId() == TEMPLATE_ID) ? "PartyEnterCommon.html" : "PartyEnterExtreme.html");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String onSpawn(L2Npc npc)
|
|
{
|
|
final Instance world = npc.getInstanceWorld();
|
|
if (isOctavisInstance(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 (isOctavisInstance(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 (isOctavisInstance(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() && isOctavisInstance(world))
|
|
{
|
|
if (world.getParameters().getBoolean("TELEPORT_ACTIVE", false))
|
|
{
|
|
character.teleToLocation(BATTLE_LOC);
|
|
}
|
|
}
|
|
return super.onEnterZone(character, zone);
|
|
}
|
|
|
|
private boolean isOctavisInstance(Instance instance)
|
|
{
|
|
return ((instance != null) && ((instance.getTemplateId() == TEMPLATE_ID) || (instance.getTemplateId() == EXTREME_TEMPLATE_ID)));
|
|
}
|
|
|
|
private boolean isExtremeMode(Instance instance)
|
|
{
|
|
return instance.getTemplateId() == EXTREME_TEMPLATE_ID;
|
|
}
|
|
|
|
public static void main(String[] args)
|
|
{
|
|
new OctavisWarzone();
|
|
}
|
|
} |