Addition of Crystal Cavern instances.

Author: St3eT
Adapted from: L2jUnity free files.
This commit is contained in:
MobiusDevelopment
2019-11-02 15:45:52 +00:00
parent 8a8b5c0cb6
commit e9abca9dbe
120 changed files with 39216 additions and 16 deletions

View File

@@ -0,0 +1,215 @@
/*
* 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.areas.Parnassus.EntrancePortalToCrystalCaverns;
import java.util.Calendar;
import org.l2jmobius.gameserver.instancemanager.QuestManager;
import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.quest.Quest;
import org.l2jmobius.gameserver.network.serverpackets.OnEventTrigger;
import ai.AbstractNpcAI;
import instances.CrystalCaverns.CrystalCavernsCoralGarden;
import instances.CrystalCaverns.CrystalCavernsEmeraldSquare;
import instances.CrystalCaverns.CrystalCavernsSteamCorridor;
/**
* Entrance Portal to Crystal Caverns AI.
* @author St3eT
*/
public class EntrancePortalToCrystalCaverns extends AbstractNpcAI
{
// NPCs
private static final int CAVERNS_ENTRACE = 33522;
// Misc
private static final int EMERALD_SQUARE_TEMPLATE_ID = 163;
private static final int STEAM_CORRIDOR_TEMPLATE_ID = 164;
private static final int CORAL_GARDEN_TEMPLATE_ID = 165;
private static final int PRISON_ENTRACE_TRIGGER_1 = 24230010;
private static final int PRISON_ENTRACE_TRIGGER_2 = 24230012;
private static final int CAVERNS_ENTRACE_TRIGGER_1 = 24230014;
private static final int CAVERNS_ENTRACE_TRIGGER_2 = 24230016;
private static final int CAVERNS_ENTRACE_TRIGGER_3 = 24230018;
private EntrancePortalToCrystalCaverns()
{
addStartNpc(CAVERNS_ENTRACE);
addTalkId(CAVERNS_ENTRACE);
addFirstTalkId(CAVERNS_ENTRACE);
addSpawnId(CAVERNS_ENTRACE);
addSeeCreatureId(CAVERNS_ENTRACE);
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (event.equals("enterInstance"))
{
Quest instanceScript = null;
switch (getCurrentInstanceTemplateId())
{
case EMERALD_SQUARE_TEMPLATE_ID:
{
instanceScript = QuestManager.getInstance().getQuest(CrystalCavernsEmeraldSquare.class.getSimpleName());
break;
}
case STEAM_CORRIDOR_TEMPLATE_ID:
{
instanceScript = QuestManager.getInstance().getQuest(CrystalCavernsSteamCorridor.class.getSimpleName());
break;
}
case CORAL_GARDEN_TEMPLATE_ID:
{
instanceScript = QuestManager.getInstance().getQuest(CrystalCavernsCoralGarden.class.getSimpleName());
break;
}
}
if (instanceScript != null)
{
instanceScript.notifyEvent(event, npc, player);
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onFirstTalk(Npc npc, PlayerInstance player)
{
return "EntrancePortal_" + getCurrentInstanceTemplateId() + ".html";
}
@Override
public String onSpawn(Npc npc)
{
getTimers().addRepeatingTimer("LOOP_TIMER", 10000, npc, null);
return super.onSpawn(npc);
}
@Override
public void onTimerEvent(String event, StatsSet params, Npc npc, PlayerInstance player)
{
if (event.equals("LOOP_TIMER"))
{
final int currentTemplateId = getCurrentInstanceTemplateId();
World.getInstance().forEachVisibleObjectInRange(npc, PlayerInstance.class, 500, p ->
{
updateTriggersForPlayer(player, currentTemplateId);
});
}
}
@Override
public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
{
if (creature.isPlayer())
{
creature.getActingPlayer().sendPacket(new OnEventTrigger(PRISON_ENTRACE_TRIGGER_1, true));
creature.getActingPlayer().sendPacket(new OnEventTrigger(PRISON_ENTRACE_TRIGGER_2, true));
updateTriggersForPlayer(creature.getActingPlayer(), getCurrentInstanceTemplateId());
}
return super.onSeeCreature(npc, creature, isSummon);
}
public void updateTriggersForPlayer(PlayerInstance player, int currentTemplateId)
{
if (player != null)
{
player.sendPacket(new OnEventTrigger(CAVERNS_ENTRACE_TRIGGER_1, false));
player.sendPacket(new OnEventTrigger(CAVERNS_ENTRACE_TRIGGER_2, false));
player.sendPacket(new OnEventTrigger(CAVERNS_ENTRACE_TRIGGER_3, false));
switch (currentTemplateId)
{
case EMERALD_SQUARE_TEMPLATE_ID:
{
player.sendPacket(new OnEventTrigger(CAVERNS_ENTRACE_TRIGGER_1, true));
break;
}
case STEAM_CORRIDOR_TEMPLATE_ID:
{
player.sendPacket(new OnEventTrigger(CAVERNS_ENTRACE_TRIGGER_2, true));
break;
}
case CORAL_GARDEN_TEMPLATE_ID:
{
player.sendPacket(new OnEventTrigger(CAVERNS_ENTRACE_TRIGGER_3, true));
break;
}
}
}
}
public int getCurrentInstanceTemplateId()
{
final int day = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
final int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
int templateId = -1;
switch (day)
{
case Calendar.MONDAY:
{
templateId = (hour < 18) ? EMERALD_SQUARE_TEMPLATE_ID : STEAM_CORRIDOR_TEMPLATE_ID;
break;
}
case Calendar.TUESDAY:
{
templateId = (hour < 18) ? CORAL_GARDEN_TEMPLATE_ID : EMERALD_SQUARE_TEMPLATE_ID;
break;
}
case Calendar.WEDNESDAY:
{
templateId = (hour < 18) ? STEAM_CORRIDOR_TEMPLATE_ID : CORAL_GARDEN_TEMPLATE_ID;
break;
}
case Calendar.THURSDAY:
{
templateId = (hour < 18) ? EMERALD_SQUARE_TEMPLATE_ID : STEAM_CORRIDOR_TEMPLATE_ID;
break;
}
case Calendar.FRIDAY:
{
templateId = (hour < 18) ? CORAL_GARDEN_TEMPLATE_ID : EMERALD_SQUARE_TEMPLATE_ID;
break;
}
case Calendar.SATURDAY:
{
templateId = (hour < 18) ? STEAM_CORRIDOR_TEMPLATE_ID : CORAL_GARDEN_TEMPLATE_ID;
break;
}
case Calendar.SUNDAY:
{
templateId = (hour < 18) ? EMERALD_SQUARE_TEMPLATE_ID : STEAM_CORRIDOR_TEMPLATE_ID;
break;
}
}
return templateId;
}
public static void main(String[] args)
{
new EntrancePortalToCrystalCaverns();
}
}

View File

@@ -0,0 +1,4 @@
<html><body>Entrance Portal to Crystal Caverns:<br>
At this time, you can go into the <font color="LEVEL">Emerald Square</font>.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EntrancePortalToCrystalCaverns enterInstance">Enter</Button>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Entrance Portal to Crystal Caverns:<br>
At this time, you can go into the <font color="LEVEL">Steam Corridor</font>.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EntrancePortalToCrystalCaverns enterInstance">Enter</Button>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Entrance Portal to Crystal Caverns:<br>
At this time, you can go into the <font color="LEVEL">Coral Garden</font>.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EntrancePortalToCrystalCaverns enterInstance">Enter</Button>
</body></html>

View File

@@ -0,0 +1,253 @@
/*
* 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.CrystalCaverns;
import org.l2jmobius.gameserver.instancemanager.WalkingManager;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.Spawn;
import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.instancezone.Instance;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import instances.AbstractInstance;
/**
* Crystal Caverns - Coral Garden instance zone.
* @author St3eT
*/
public class CrystalCavernsCoralGarden extends AbstractInstance
{
// NPCs
private static final int CAVERNS_ENTRACE = 33522;
private static final int MICHAELA_NORMAL = 25799;
private static final int MICHAELA_WISE = 26116;
private static final int MICHAELA_WEALTHY = 26115;
private static final int MICHAELA_ARMED = 26114;
private static final int GOLEM_1 = 19013; // Crystalline Golem
private static final int GOLEM_2 = 19014; // Crystalline Golem
// Location
private static final Location BOSS_LOC = new Location(144307, 220032, -11824);
// Misc
private static final int TEMPLATE_ID = 165;
private static final int BOSS_DOOR_ID = 24240026;
private static final int PLAYER_MAX_DISTANCE = 250;
public CrystalCavernsCoralGarden()
{
super(TEMPLATE_ID);
addStartNpc(CAVERNS_ENTRACE);
addTalkId(CAVERNS_ENTRACE);
addFirstTalkId(GOLEM_1, GOLEM_2);
addKillId(MICHAELA_NORMAL, MICHAELA_WISE, MICHAELA_WEALTHY, MICHAELA_ARMED);
addAttackId(MICHAELA_NORMAL, MICHAELA_WISE, MICHAELA_WEALTHY, MICHAELA_ARMED);
addRouteFinishedId(GOLEM_1, GOLEM_2);
addInstanceEnterId(TEMPLATE_ID);
addInstanceLeaveId(TEMPLATE_ID);
}
@Override
public void onTimerEvent(String event, StatsSet params, Npc npc, PlayerInstance player)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcVars = npc.getVariables();
switch (event)
{
case "SUCCESS_TIMER":
{
showOnScreenMsg(instance, NpcStringId.GOLEM_LOCATION_SUCCESSFUL_ENTRY_ACCESSED, ExShowScreenMessage.MIDDLE_CENTER, 5000);
break;
}
case "LOOP_TIMER":
{
player = npcVars.getObject("PLAYER_OBJECT", PlayerInstance.class);
if ((player != null) && (npc.calculateDistance3D(player) > PLAYER_MAX_DISTANCE) && npcVars.getBoolean("NPC_FOLLOWING", true))
{
WalkingManager.getInstance().cancelMoving(npc);
addMoveToDesire(npc, new Location(npc.getX() + getRandom(-100, 100), npc.getY() + getRandom(-150, 150), npc.getZ()), 23);
npc.setRunning();
npcVars.set("NPC_FOLLOWING", false);
getTimers().cancelTimer("LOOP_TIMER", npc, null);
getTimers().addTimer("FAIL_TIMER", 5000, npc, null);
}
break;
}
case "FAIL_TIMER":
{
final Spawn spawn = npc.getSpawn();
if (!npcVars.getBoolean("NPC_FOLLOWING", true))
{
WalkingManager.getInstance().cancelMoving(npc);
npc.setWalking();
npc.teleToLocation(npc.getSpawn().getX(), npc.getSpawn().getY(), npc.getSpawn().getZ());
npc.setScriptValue(0);
npc.setNameString(null);
npc.setTitleString(null);
npc.setTitle(null);
npc.broadcastInfo();
}
npcVars.set("CAN_CALL_MONSTERS", ((spawn.getX() - ((npc.getX() * spawn.getX()) - npc.getX())) + (spawn.getY() - (npc.getY() * spawn.getY()) - npc.getY())) > (200 * 200));
break;
}
}
}
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (event.equals("enterInstance"))
{
enterInstance(player, npc, TEMPLATE_ID);
}
return super.onAdvEvent(event, npc, player);
}
@Override
public void onInstanceEnter(PlayerInstance player, Instance instance)
{
final int startTime = (int) (instance.getElapsedTime() / 1000);
final int endTime = (int) (instance.getRemainingTime() / 1000);
player.sendPacket(new ExSendUIEvent(player, false, true, startTime, endTime, NpcStringId.ELAPSED_TIME));
}
@Override
public void onInstanceLeave(PlayerInstance player, Instance instance)
{
player.sendPacket(new ExSendUIEvent(player, true, true, 0, 0, NpcStringId.ELAPSED_TIME));
}
@Override
public String onFirstTalk(Npc npc, PlayerInstance player)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
if (npc.isScriptValue(0))
{
npc.setScriptValue(1);
npc.getVariables().set("PLAYER_OBJECT", player);
npc.setNameString(NpcStringId.TRAITOR_CRYSTALLINE_GOLEM);
npc.setTitleString(NpcStringId.GIVEN_TO_S1);
npc.setTitle(player.getName());
npc.broadcastInfo();
WalkingManager.getInstance().startMoving(npc, npc.getId() == GOLEM_1 ? "gd_golem_1" : "gd_golem_2");
getTimers().addRepeatingTimer("LOOP_TIMER", 500, npc, null);
}
}
return null;
}
@Override
public void onRouteFinished(Npc npc)
{
final Instance instance = npc.getInstanceWorld();
if (instance != null)
{
WalkingManager.getInstance().cancelMoving(npc);
showOnScreenMsg(instance, NpcStringId.GOLEM_ENTERED_THE_REQUIRED_ZONE, ExShowScreenMessage.MIDDLE_CENTER, 5000);
npc.deleteMe();
if (instance.getAliveNpcs(GOLEM_1, GOLEM_2).isEmpty())
{
instance.openCloseDoor(BOSS_DOOR_ID, true);
final int random = getRandom(100);
int bossId = -1;
if (random < 55)
{
bossId = MICHAELA_NORMAL;
}
else if (random < 80)
{
bossId = MICHAELA_WISE;
}
else if (random < 95)
{
bossId = MICHAELA_WEALTHY;
}
else
{
bossId = MICHAELA_ARMED;
}
final Npc boss = addSpawn(bossId, BOSS_LOC, false, 0, false, instance.getId());
getTimers().addTimer("SUCCESS_TIMER", 5000, boss, null);
}
}
}
@Override
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
switch (npc.getId())
{
case MICHAELA_NORMAL:
case MICHAELA_WISE:
case MICHAELA_WEALTHY:
case MICHAELA_ARMED:
{
instance.finishInstance();
break;
}
}
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
switch (npc.getId())
{
case MICHAELA_NORMAL:
case MICHAELA_WISE:
case MICHAELA_WEALTHY:
case MICHAELA_ARMED:
{
if (npc.isScriptValue(0))
{
npc.setScriptValue(1);
instance.openCloseDoor(BOSS_DOOR_ID, false);
}
break;
}
}
}
return super.onAttack(npc, attacker, damage, isSummon);
}
public static void main(String[] args)
{
new CrystalCavernsCoralGarden();
}
}

View File

@@ -0,0 +1,424 @@
/*
* 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.CrystalCaverns;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureSee;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.instancezone.Instance;
import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.Stats;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import instances.AbstractInstance;
/**
* Crystal Caverns - Emerald Square instance zone.
* @author St3eT
*/
public class CrystalCavernsEmeraldSquare extends AbstractInstance
{
// NPCs
private static final int CAVERNS_ENTRACE = 33522;
private static final int VERIDAN_NORMAL = 25796;
private static final int VERIDAN_WISE = 26107;
private static final int VERIDAN_WEALTHY = 26106;
private static final int VERIDAN_ARMED = 26105;
private static final int WATER_CANNON = 19008;
private static final int WATER_CANNON_SKILL = 19009;
private static final int STRONGHOLD_PROTECTOR = 23012;
private static final int SQUARE_INTRUDER = 23010;
private static final int SQUARE_ATTACKER = 23011;
// Skills
private static final SkillHolder DESTROY_SKILL = new SkillHolder(12003, 1);
private static final SkillHolder WATER_CANNON_SKILL_ATTACK = new SkillHolder(14179, 1);
// Locations
private static final Location[] BOSS_SPAWNS =
{
new Location(152745, 145957, -12584, 16446),
new Location(152816, 145968, -12633, 16446),
};
// Misc
private static final int TEMPLATE_ID = 163;
private static final int RAID_DOOR_1 = 24220005;
private static final int RAID_DOOR_2 = 24220006;
public CrystalCavernsEmeraldSquare()
{
super(TEMPLATE_ID);
addStartNpc(CAVERNS_ENTRACE);
addTalkId(CAVERNS_ENTRACE);
addSpawnId(WATER_CANNON);
addKillId(WATER_CANNON, VERIDAN_NORMAL, VERIDAN_WISE, VERIDAN_WEALTHY, VERIDAN_ARMED);
addAttackId(WATER_CANNON, VERIDAN_NORMAL, VERIDAN_WISE, VERIDAN_WEALTHY, VERIDAN_ARMED);
addSpellFinishedId(WATER_CANNON_SKILL);
addInstanceEnterId(TEMPLATE_ID);
addInstanceLeaveId(TEMPLATE_ID);
setCreatureSeeId(this::onCreatureSee, WATER_CANNON);
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (event.equals("enterInstance"))
{
enterInstance(player, npc, TEMPLATE_ID);
}
return super.onAdvEvent(event, npc, player);
}
@Override
public void onTimerEvent(String event, StatsSet params, Npc npc, PlayerInstance player)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcParams = npc.getParameters();
final StatsSet npcVars = npc.getVariables();
final int baseId = npcParams.getInt("base_id", -1);
switch (event)
{
case "HP_REGEN_TIMER":
{
int value = ((baseId == 5) || (baseId == 6)) ? 5 : baseId;
npc.getStat().addFixedValue(Stats.REGENERATE_HP_RATE, Double.valueOf(value * 1000));
break;
}
case "SUPPORT_SPAWN_TIMER":
{
int supportVal = npcVars.getInt("SUPPORT_VALUE", 0);
if (supportVal > 3)
{
return;
}
if ((supportVal == 0) || (supportVal == 1) || (supportVal == 2))
{
final String spawnName = npcParams.getString("SupportMaker" + (supportVal + 1), null);
if (spawnName != null)
{
instance.spawnGroup(spawnName);
}
npcVars.increaseInt("SUPPORT_VALUE", 1);
}
if (!npcVars.getBoolean("PREVIOUS_BASE_DESTROYED", false))
{
getTimers().addTimer("SUPPORT_SPAWN_TIMER", 60000, npc, null);
}
break;
}
case "CANNON_LOOP_ATTACK":
{
if (npc.getCurrentHpPercent() > 30)
{
if (npcVars.getBoolean("IS_DESTROY_ACTIVATED", false) || (getRandom(10) < 2))
{
final Npc cannonSkill = addSpawn(WATER_CANNON_SKILL, npc, true, 0, false, instance.getId());
addSkillCastDesire(cannonSkill, cannonSkill, WATER_CANNON_SKILL_ATTACK, 23);
}
}
break;
}
case "SUICIDE_TIMER":
{
npc.doDie(null);
break;
}
}
}
}
@Override
public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcVars = npc.getVariables();
switch (npc.getId())
{
case VERIDAN_WISE:
case VERIDAN_WEALTHY:
case VERIDAN_ARMED:
{
if (!npcVars.getBoolean("CLOSED_DOORS", false))
{
npcVars.set("CLOSED_DOORS", true);
instance.openCloseDoor(RAID_DOOR_2, false);
}
}
case WATER_CANNON:
{
if ((skill != null) && (skill.getId() == DESTROY_SKILL.getSkillId()) && !npcVars.getBoolean("IS_DESTROY_ACTIVATED", false))
{
npcVars.set("IS_DESTROY_ACTIVATED", true);
npc.setDisplayEffect(2);
getTimers().addTimer("SUICIDE_TIMER", 60000, npc, null);
}
if (npc.getCurrentHpPercent() < 30)
{
if (!npcVars.getBoolean("IS_DESTROY_ACTIVATED", false))
{
npc.setDisplayEffect(3);
}
}
else if (!npcVars.getBoolean("IS_DESTROY_ACTIVATED", false))
{
npc.setDisplayEffect(1);
}
break;
}
}
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcParams = npc.getParameters();
final int baseId = npcParams.getInt("base_id", -1);
switch (npc.getId())
{
case VERIDAN_NORMAL:
case VERIDAN_WISE:
case VERIDAN_WEALTHY:
case VERIDAN_ARMED:
{
if (instance.getAliveNpcs(VERIDAN_NORMAL, VERIDAN_WISE, VERIDAN_WEALTHY, VERIDAN_ARMED).isEmpty())
{
instance.finishInstance();
}
else
{
instance.setReenterTime();
}
break;
}
case WATER_CANNON:
{
npc.setDisplayEffect(4);
showOnScreenMsg(instance, NpcStringId.SUCCESSFUL_DESTRUCTION_OF_STRONGHOLD_S1, ExShowScreenMessage.MIDDLE_CENTER, 4000, String.valueOf(npc.getParameters().getInt("base_id", -1)));
World.getInstance().forEachVisibleObjectInRange(npc, MonsterInstance.class, 400, monster ->
{
if ((monster.getId() == STRONGHOLD_PROTECTOR) || (monster.getId() == SQUARE_INTRUDER) || (monster.getId() == SQUARE_ATTACKER))
{
monster.doDie(null);
}
});
instance.getAliveNpcs(WATER_CANNON).forEach(cannon ->
{
final int cannonBaseId = cannon.getParameters().getInt("base_id", -1);
switch (baseId)
{
case 1:
{
if (cannonBaseId == 2)
{
cannon.getVariables().set("PREVIOUS_BASE_DESTROYED", true);
cannon.setTargetable(true);
}
break;
}
case 2:
{
if (cannonBaseId == 3)
{
cannon.getVariables().set("PREVIOUS_BASE_DESTROYED", true);
cannon.setTargetable(true);
}
break;
}
case 3:
{
if (cannonBaseId == 4)
{
cannon.getVariables().set("PREVIOUS_BASE_DESTROYED", true);
cannon.setTargetable(true);
}
break;
}
case 4:
{
if ((cannonBaseId == 5) || (cannonBaseId == 6))
{
cannon.getVariables().set("PREVIOUS_BASE_DESTROYED", true);
cannon.setTargetable(true);
}
break;
}
case 5:
case 6:
{
if (cannonBaseId == 7)
{
cannon.getVariables().set("PREVIOUS_BASE_DESTROYED", true);
cannon.setTargetable(true);
}
break;
}
case 7:
{
if ((cannonBaseId == 8) || (cannonBaseId == 9))
{
cannon.getVariables().set("PREVIOUS_BASE_DESTROYED", true);
cannon.setTargetable(true);
}
break;
}
}
});
if ((baseId == 8) || (baseId == 9))
{
instance.getParameters().increaseInt("MAIN_TARGETS_KILLED", 0, 1);
if (instance.getParameters().getInt("MAIN_TARGETS_KILLED", 0) == 2)
{
showOnScreenMsg(instance, NpcStringId.SUCCESSFUL_DESTRUCTION_OF_STRONGHOLD_ENTRY_ACCESSED, ExShowScreenMessage.MIDDLE_CENTER, 4000);
instance.openCloseDoor(RAID_DOOR_1, true);
instance.openCloseDoor(RAID_DOOR_2, true);
final int random = getRandom(100);
int bossId = -1;
if (random < 55)
{
bossId = VERIDAN_NORMAL;
}
else if (random < 80)
{
bossId = VERIDAN_WISE;
}
else if (random < 95)
{
bossId = VERIDAN_WEALTHY;
}
else
{
bossId = VERIDAN_ARMED;
}
for (Location loc : BOSS_SPAWNS)
{
addSpawn(bossId, loc, false, 0, false, instance.getId());
}
}
}
}
}
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance) && (npc.getId() == WATER_CANNON_SKILL) && (skill.getId() == WATER_CANNON_SKILL_ATTACK.getSkillId()))
{
npc.deleteMe();
}
return super.onSpellFinished(npc, player, skill);
}
@Override
public String onSpawn(Npc npc)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
switch (npc.getId())
{
case WATER_CANNON:
{
final StatsSet npcParams = npc.getParameters();
final int baseId = npcParams.getInt("base_id", -1);
if (baseId != 1)
{
npc.setTargetable(false);
}
getTimers().addTimer("HP_REGEN_TIMER", 10000, npc, null);
if (baseId > 0)
{
getTimers().addTimer("SUPPORT_SPAWN_TIMER", (baseId * 60) * 1000, npc, null);
}
npc.initSeenCreatures();
break;
}
}
}
return super.onSpawn(npc);
}
public void onCreatureSee(OnCreatureSee event)
{
final Creature creature = event.getSeen();
final Npc npc = (Npc) event.getSeer();
final Instance world = npc.getInstanceWorld();
if ((world != null) && creature.isPlayer() && npc.isScriptValue(0))
{
npc.setScriptValue(1);
npc.setDisplayEffect(1);
getTimers().addRepeatingTimer("CANNON_LOOP_ATTACK", 1000, npc, null);
}
}
@Override
public void onInstanceEnter(PlayerInstance player, Instance instance)
{
final int startTime = (int) (instance.getElapsedTime() / 1000);
final int endTime = (int) (instance.getRemainingTime() / 1000);
player.sendPacket(new ExSendUIEvent(player, false, true, startTime, endTime, NpcStringId.ELAPSED_TIME));
}
@Override
public void onInstanceLeave(PlayerInstance player, Instance instance)
{
player.sendPacket(new ExSendUIEvent(player, true, true, 0, 0, NpcStringId.ELAPSED_TIME));
}
public static void main(String[] args)
{
new CrystalCavernsEmeraldSquare();
}
}

View File

@@ -0,0 +1,408 @@
/*
* 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.CrystalCaverns;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureSee;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.instancezone.Instance;
import org.l2jmobius.gameserver.model.zone.ZoneType;
import org.l2jmobius.gameserver.model.zone.type.TeleportZone;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import instances.AbstractInstance;
/**
* Crystal Caverns - Steam Corridor instance zone.
* @author St3eT
*/
public class CrystalCavernsSteamCorridor extends AbstractInstance
{
// NPCs
private static final int CAVERNS_ENTRACE = 33522;
private static final int KECHI_NORMAL = 25797;
private static final int KECHI_WISE = 26113;
private static final int KECHI_WEALTHY = 26112;
private static final int KECHI_ARMED = 26111;
private static final int VICIOUS_DUELER = 23014;
private static final int VICIOUS_WARRIOR = 23016;
private static final int VICIOUS_SWORDSMAN = 23015;
private static final int SPIRIT_PROTECTOR = 23013;
private static final int FIRE_REGION = 19161;
private static final int PLAYER_DETECTOR = 19075;
private static final int TRAP_1 = 19011;
private static final int TRAP_2 = 19012;
// Skills
private static final SkillHolder FIRE_SKILL_1 = new SkillHolder(14373, 1);
private static final SkillHolder FIRE_SKILL_2 = new SkillHolder(14373, 2);
private static final SkillHolder FIRE_SKILL_3 = new SkillHolder(14197, 1);
private static final SkillHolder TRAP_SKILL_1 = new SkillHolder(14180, 1);
private static final SkillHolder TRAP_SKILL_2 = new SkillHolder(14181, 1);
private static final SkillHolder TRAP_SKILL_3 = new SkillHolder(14372, 1);
// Location
private static final Location BOSS_LOC = new Location(154078, 215125, -12140);
// Misc
private static final int TEMPLATE_ID = 164;
public CrystalCavernsSteamCorridor()
{
super(TEMPLATE_ID);
addStartNpc(CAVERNS_ENTRACE);
addTalkId(CAVERNS_ENTRACE);
addAttackId(TRAP_1, TRAP_2);
addKillId(VICIOUS_DUELER, VICIOUS_WARRIOR, VICIOUS_SWORDSMAN, KECHI_NORMAL, KECHI_WISE, KECHI_WEALTHY, KECHI_ARMED);
addSpawnId(SPIRIT_PROTECTOR, VICIOUS_DUELER, VICIOUS_WARRIOR, VICIOUS_SWORDSMAN, FIRE_REGION, PLAYER_DETECTOR);
addEventReceivedId(SPIRIT_PROTECTOR, VICIOUS_DUELER, VICIOUS_WARRIOR, VICIOUS_SWORDSMAN);
addInstanceCreatedId(TEMPLATE_ID);
addInstanceEnterId(TEMPLATE_ID);
addInstanceLeaveId(TEMPLATE_ID);
setCreatureSeeId(this::onCreatureSee, PLAYER_DETECTOR);
}
@Override
public void onTimerEvent(String event, StatsSet params, Npc npc, PlayerInstance player)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcVars = npc.getVariables();
switch (event)
{
case "FIRE_REGION_TIMER_1":
{
addSkillCastDesire(npc, npc, FIRE_SKILL_1, 23);
getTimers().addTimer("FIRE_REGION_TIMER_2", 10000, npc, null);
break;
}
case "FIRE_REGION_TIMER_2":
{
addSkillCastDesire(npc, npc, FIRE_SKILL_2, 23);
getTimers().addTimer("FIRE_REGION_TIMER_3", 10000, npc, null);
break;
}
case "FIRE_REGION_TIMER_3":
{
addSkillCastDesire(npc, npc, FIRE_SKILL_3, 23);
getTimers().addTimer("FIRE_REGION_TIMER_3", 1000, npc, null);
break;
}
case "TRAP_REACT_TIMER":
{
final int timer = npcVars.increaseInt("TIMER_VAL", -1);
if (timer > 0)
{
npc.broadcastSay(ChatType.NPC_GENERAL, " " + timer);
}
else
{
if (npc.getId() == TRAP_1)
{
addSkillCastDesire(npc, npc, (getRandom(10) < 8 ? TRAP_SKILL_1 : TRAP_SKILL_3), 23);
}
else if (npc.getId() == TRAP_2)
{
addSkillCastDesire(npc, npc, (getRandom(10) < 8 ? TRAP_SKILL_2 : TRAP_SKILL_3), 23);
}
}
getTimers().addTimer("TRAP_REACT_TIMER", 1000, npc, null);
break;
}
}
}
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (event.equals("enterInstance"))
{
enterInstance(player, npc, TEMPLATE_ID);
}
return super.onAdvEvent(event, npc, player);
}
@Override
public void onInstanceCreated(Instance instance, PlayerInstance player)
{
instance.setStatus(1);
for (int i = 0; i < 6; i++)
{
final ZoneType zone = ZoneManager.getInstance().getZoneByName("24_24_fire_telezone_0" + i, TeleportZone.class);
if (zone != null)
{
zone.setEnabled(false, instance.getId());
}
}
super.onInstanceCreated(instance, player);
}
@Override
public void onInstanceEnter(PlayerInstance player, Instance instance)
{
final int startTime = (int) (instance.getElapsedTime() / 1000);
final int endTime = (int) (instance.getRemainingTime() / 1000);
player.sendPacket(new ExSendUIEvent(player, false, true, startTime, endTime, NpcStringId.ELAPSED_TIME));
}
@Override
public void onInstanceLeave(PlayerInstance player, Instance instance)
{
player.sendPacket(new ExSendUIEvent(player, true, true, 0, 0, NpcStringId.ELAPSED_TIME));
}
@Override
public String onSpawn(Npc npc)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcParams = npc.getParameters();
switch (npc.getId())
{
case SPIRIT_PROTECTOR:
case VICIOUS_DUELER:
case VICIOUS_WARRIOR:
case VICIOUS_SWORDSMAN:
{
npc.setTargetable(false);
npc.disableCoreAI(true);
npc.setInvisible(true);
break;
}
case FIRE_REGION:
{
final int timeLimit = npcParams.getInt("Limit_Time", 0);
if (timeLimit > 0)
{
getTimers().addTimer("FIRE_REGION_TIMER_1", ((timeLimit * 30) * 100), npc, null);
}
npc.setTargetable(false);
npc.setIsInvul(true);
npc.setRandomAnimation(false);
npc.setRandomWalking(false);
npc.disableCoreAI(true);
break;
}
case PLAYER_DETECTOR:
{
npc.initSeenCreatures();
break;
}
}
}
return super.onSpawn(npc);
}
@Override
public String onEventReceived(String eventName, Npc sender, Npc receiver, WorldObject reference)
{
final Instance instance = receiver.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcParams = receiver.getParameters();
if (eventName.equals(String.valueOf(24220005 + npcParams.getInt("Terri_ID", 0))))
{
receiver.setTargetable(true);
receiver.disableCoreAI(false);
receiver.setInvisible(false);
}
}
return super.onEventReceived(eventName, sender, receiver, reference);
}
@Override
public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
switch (npc.getId())
{
case TRAP_1:
case TRAP_2:
{
if (npc.isScriptValue(0))
{
getTimers().addTimer("TRAP_REACT_TIMER", 1000, npc, null);
npc.setScriptValue(1);
}
break;
}
}
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
{
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance))
{
final StatsSet npcParams = npc.getParameters();
final int killTarget = instance.getParameters().getInt("KILL_TARGET", 5);
int currentKillCount = instance.getParameters().getInt("KILL_COUNT", 0);
switch (npc.getId())
{
case VICIOUS_DUELER:
case VICIOUS_WARRIOR:
case VICIOUS_SWORDSMAN:
{
if (npcParams.getInt("last_checker", 0) == 1)
{
currentKillCount = instance.getParameters().increaseInt("KILL_COUNT", 0, 1);
if (currentKillCount >= killTarget)
{
final ZoneType zone = ZoneManager.getInstance().getZoneByName(npc.getParameters().getString("AreaTeleName"), TeleportZone.class);
if (zone != null)
{
zone.setEnabled(true, instance.getId());
showOnScreenMsg(instance, NpcStringId.THE_PORTAL_TO_THE_NEXT_ROOM_IS_NOW_OPEN, ExShowScreenMessage.MIDDLE_CENTER, 4000);
instance.spawnGroup("innadril23_mb2422_pt" + instance.getStatus() + "m1");
instance.getParameters().set("KILL_COUNT", 0);
switch (instance.getStatus())
{
case 1:
{
instance.getParameters().set("KILL_TARGET", 12);
instance.setStatus(2);
break;
}
case 2:
{
instance.getParameters().set("KILL_TARGET", 3);
instance.setStatus(3);
break;
}
case 3:
{
instance.getParameters().set("KILL_TARGET", 18);
instance.setStatus(4);
break;
}
case 4:
{
instance.getParameters().set("KILL_TARGET", 5);
instance.setStatus(5);
break;
}
case 5:
{
instance.getParameters().set("KILL_TARGET", 20);
instance.setStatus(6);
break;
}
case 6:
{
final int random = getRandom(100);
int bossId = -1;
if (random < 55)
{
bossId = KECHI_NORMAL;
}
else if (random < 80)
{
bossId = KECHI_WISE;
}
else if (random < 95)
{
bossId = KECHI_WEALTHY;
}
else
{
bossId = KECHI_ARMED;
}
addSpawn(bossId, BOSS_LOC, false, 0, false, instance.getId());
break;
}
}
}
else
{
LOGGER.warning("Cannot find teleport zone for Crystal Cavern: Steam Corridor instance!!!");
}
}
}
break;
}
case KECHI_NORMAL:
case KECHI_WISE:
case KECHI_WEALTHY:
case KECHI_ARMED:
{
instance.finishInstance();
break;
}
}
}
return super.onKill(npc, killer, isSummon);
}
private void onCreatureSee(OnCreatureSee event)
{
final Creature creature = event.getSeen();
final Npc npc = (Npc) event.getSeer();
final Instance instance = npc.getInstanceWorld();
if (isInInstance(instance) && creature.isPlayer())
{
final StatsSet npcParams = npc.getParameters();
switch (npc.getId())
{
case PLAYER_DETECTOR:
{
if (npc.isScriptValue(0))
{
npc.setScriptValue(1);
npc.broadcastEvent(String.valueOf(24220005 + npcParams.getInt("Terri_ID", 0)), 2000, null);
for (int i = 0; i < getRandom(5); i++)
{
final Npc trap = addSpawn(((npcParams.getInt("MobType", 0) == 0) ? TRAP_1 : TRAP_2), npc, true, 0, false, instance.getId());
trap.getVariables().set("TIMER_VAL", 4);
}
npc.deleteMe();
}
break;
}
}
}
}
public static void main(String[] args)
{
new CrystalCavernsSteamCorridor();
}
}

View File

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

View File

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