This commit is contained in:
MobiusDev
2016-10-21 21:26:21 +00:00
parent 4247fae039
commit 34fc592ced
25699 changed files with 2534454 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,132 @@
/*
* 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 gracia.AI;
import java.util.Calendar;
import java.util.GregorianCalendar;
import com.l2jmobius.gameserver.datatables.SpawnTable;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.NpcStringId;
import ai.npc.AbstractNpcAI;
/**
* Lindvior Scene AI.
* @author nonom
*/
public class Lindvior extends AbstractNpcAI
{
private static final int LINDVIOR_CAMERA = 18669;
private static final int TOMARIS = 32552;
private static final int ARTIUS = 32559;
private static int LINDVIOR_SCENE_ID = 1;
private static final int RESET_HOUR = 18;
private static final int RESET_MIN = 58;
private static final int RESET_DAY_1 = Calendar.TUESDAY;
private static final int RESET_DAY_2 = Calendar.FRIDAY;
private static boolean ALT_MODE = false;
private static int ALT_MODE_MIN = 60; // schedule delay in minutes if ALT_MODE enabled
private L2Npc _lindviorCamera = null;
private L2Npc _tomaris = null;
private L2Npc _artius = null;
public Lindvior()
{
super(Lindvior.class.getSimpleName(), "gracia/AI");
scheduleNextLindviorVisit();
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "tomaris_shout1":
broadcastNpcSay(npc, ChatType.NPC_SHOUT, NpcStringId.HUH_THE_SKY_LOOKS_FUNNY_WHAT_S_THAT);
break;
case "artius_shout":
broadcastNpcSay(npc, ChatType.NPC_SHOUT, NpcStringId.A_POWERFUL_SUBORDINATE_IS_BEING_HELD_BY_THE_BARRIER_ORB_THIS_REACTION_MEANS);
break;
case "tomaris_shout2":
broadcastNpcSay(npc, ChatType.NPC_SHOUT, NpcStringId.BE_CAREFUL_SOMETHING_S_COMING);
break;
case "lindvior_scene":
if (npc != null)
{
for (L2PcInstance pl : npc.getKnownList().getKnownPlayersInRadius(4000))
{
if ((pl.getZ() >= 1100) && (pl.getZ() <= 3100))
{
pl.showQuestMovie(LINDVIOR_SCENE_ID);
}
}
}
break;
case "start":
_lindviorCamera = SpawnTable.getInstance().findAny(LINDVIOR_CAMERA).getLastSpawn();
_tomaris = SpawnTable.getInstance().findAny(TOMARIS).getLastSpawn();
_artius = SpawnTable.getInstance().findAny(ARTIUS).getLastSpawn();
startQuestTimer("tomaris_shout1", 1000, _tomaris, null);
startQuestTimer("artius_shout", 60000, _artius, null);
startQuestTimer("tomaris_shout2", 90000, _tomaris, null);
startQuestTimer("lindvior_scene", 120000, _lindviorCamera, null);
scheduleNextLindviorVisit();
break;
}
return super.onAdvEvent(event, npc, player);
}
public void scheduleNextLindviorVisit()
{
final long delay = (ALT_MODE) ? ALT_MODE_MIN * 60000 : scheduleNextLindviorDate();
startQuestTimer("start", delay, null, null);
}
protected long scheduleNextLindviorDate()
{
final GregorianCalendar date = new GregorianCalendar();
date.set(Calendar.MINUTE, RESET_MIN);
date.set(Calendar.HOUR_OF_DAY, RESET_HOUR);
if (System.currentTimeMillis() >= date.getTimeInMillis())
{
date.add(Calendar.DAY_OF_WEEK, 1);
}
final int dayOfWeek = date.get(Calendar.DAY_OF_WEEK);
if (dayOfWeek <= RESET_DAY_1)
{
date.add(Calendar.DAY_OF_WEEK, RESET_DAY_1 - dayOfWeek);
}
else if (dayOfWeek <= RESET_DAY_2)
{
date.add(Calendar.DAY_OF_WEEK, RESET_DAY_2 - dayOfWeek);
}
else
{
date.add(Calendar.DAY_OF_WEEK, 1 + RESET_DAY_1);
}
return date.getTimeInMillis() - System.currentTimeMillis();
}
}

View File

@@ -0,0 +1,377 @@
/*
* 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 gracia.AI;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.instancemanager.QuestManager;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.model.quest.Quest;
import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.NpcStringId;
import ai.npc.AbstractNpcAI;
import gracia.AI.NPC.Nemo.Nemo;
/**
* Maguen AI.
* @author St3eT
*/
public final class Maguen extends AbstractNpcAI
{
// NPC
private static final int MAGUEN = 18839; // Wild Maguen
private static final int[] ELITES =
{
22750, // Elite Bgurent (Bistakon)
22751, // Elite Brakian (Bistakon)
22752, // Elite Groikan (Bistakon)
22753, // Elite Treykan (Bistakon)
22757, // Elite Turtlelian (Reptilikon)
22758, // Elite Krajian (Reptilikon)
22759, // Elite Tardyon (Reptilikon)
22763, // Elite Kanibi (Kokracon)
22764, // Elite Kiriona (Kokracon)
22765, // Elite Kaiona (Kokracon)
};
// Item
private static final int MAGUEN_PET = 15488; // Maguen Pet Collar
private static final int ELITE_MAGUEN_PET = 15489; // Elite Maguen Pet Collar
// Skills
private static final SkillHolder MACHINE = new SkillHolder(9060, 1); // Maguen Machine
private static final SkillHolder B_BUFF_1 = new SkillHolder(6343, 1); // Maguen Plasma - Power
private static final SkillHolder B_BUFF_2 = new SkillHolder(6343, 2); // Maguen Plasma - Power
private static final SkillHolder C_BUFF_1 = new SkillHolder(6365, 1); // Maguen Plasma - Speed
private static final SkillHolder C_BUFF_2 = new SkillHolder(6365, 2); // Maguen Plasma - Speed
private static final SkillHolder R_BUFF_1 = new SkillHolder(6366, 1); // Maguen Plasma - Critical
private static final SkillHolder R_BUFF_2 = new SkillHolder(6366, 2); // Maguen Plasma - Critical
private static final SkillHolder B_PLASMA1 = new SkillHolder(6367, 1); // Maguen Plasma - Bistakon
private static final SkillHolder B_PLASMA2 = new SkillHolder(6367, 2); // Maguen Plasma - Bistakon
private static final SkillHolder B_PLASMA3 = new SkillHolder(6367, 3); // Maguen Plasma - Bistakon
private static final SkillHolder C_PLASMA1 = new SkillHolder(6368, 1); // Maguen Plasma - Cokrakon
private static final SkillHolder C_PLASMA2 = new SkillHolder(6368, 2); // Maguen Plasma - Cokrakon
private static final SkillHolder C_PLASMA3 = new SkillHolder(6368, 3); // Maguen Plasma - Cokrakon
private static final SkillHolder R_PLASMA1 = new SkillHolder(6369, 1); // Maguen Plasma - Reptilikon
private static final SkillHolder R_PLASMA2 = new SkillHolder(6369, 2); // Maguen Plasma - Reptilikon
private static final SkillHolder R_PLASMA3 = new SkillHolder(6369, 3); // Maguen Plasma - Reptilikon
public Maguen()
{
super(Maguen.class.getSimpleName(), "gracia/AI");
addKillId(ELITES);
addSkillSeeId(MAGUEN);
addSpellFinishedId(MAGUEN);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if ((npc == null) || (player == null))
{
return null;
}
switch (event)
{
case "SPAWN_MAGUEN":
{
final L2Npc maguen = addSpawn(MAGUEN, npc.getLocation(), true, 60000, true);
maguen.getVariables().set("SUMMON_PLAYER", player);
maguen.setTitle(player.getName());
maguen.setIsRunning(true);
maguen.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player);
maguen.broadcastStatusUpdate();
showOnScreenMsg(player, NpcStringId.MAGUEN_APPEARANCE, 2, 4000);
startQuestTimer("DIST_CHECK_TIMER", 1000, maguen, player);
break;
}
case "DIST_CHECK_TIMER":
{
if ((npc.calculateDistance(player, true, false) < 100) && (npc.getVariables().getInt("IS_NEAR_PLAYER") == 0))
{
npc.getVariables().set("IS_NEAR_PLAYER", 1);
startQuestTimer("FIRST_TIMER", 4000, npc, player);
}
else
{
startQuestTimer("DIST_CHECK_TIMER", 1000, npc, player);
}
break;
}
case "FIRST_TIMER":
{
npc.getAI().stopFollow();
final int randomEffect = getRandom(1, 3);
npc.setDisplayEffect(randomEffect);
npc.getVariables().set("NPC_EFFECT", randomEffect);
startQuestTimer("SECOND_TIMER", 5000 + getRandom(300), npc, player);
npc.broadcastSocialAction(getRandom(1, 3));
break;
}
case "SECOND_TIMER":
{
final int randomEffect = getRandom(1, 3);
npc.setDisplayEffect(4);
npc.setDisplayEffect(randomEffect);
npc.getVariables().set("NPC_EFFECT", randomEffect);
startQuestTimer("THIRD_TIMER", 4600 + getRandom(600), npc, player);
npc.broadcastSocialAction(getRandom(1, 3));
break;
}
case "THIRD_TIMER":
{
final int randomEffect = getRandom(1, 3);
npc.setDisplayEffect(4);
npc.setDisplayEffect(randomEffect);
npc.getVariables().set("NPC_EFFECT", randomEffect);
startQuestTimer("FORTH_TIMER", 4200 + getRandom(900), npc, player);
npc.broadcastSocialAction(getRandom(1, 3));
break;
}
case "FORTH_TIMER":
{
npc.getVariables().set("NPC_EFFECT", 0);
npc.setDisplayEffect(4);
startQuestTimer("END_TIMER", 500, npc, player);
npc.broadcastSocialAction(getRandom(1, 3));
break;
}
case "END_TIMER":
{
if (npc.getVariables().getInt("TEST_MAGUEN") == 1)
{
player.getEffectList().stopSkillEffects(true, B_PLASMA1.getSkill().getAbnormalType());
player.getEffectList().stopSkillEffects(true, C_PLASMA1.getSkill().getAbnormalType());
player.getEffectList().stopSkillEffects(true, R_PLASMA1.getSkill().getAbnormalType());
nemoAi().notifyEvent("DECREASE_COUNT", npc, player);
}
npc.doDie(null);
break;
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
final BuffInfo b_info = player.getEffectList().getBuffInfoByAbnormalType(B_PLASMA1.getSkill().getAbnormalType());
final BuffInfo c_info = player.getEffectList().getBuffInfoByAbnormalType(C_PLASMA1.getSkill().getAbnormalType());
final BuffInfo r_info = player.getEffectList().getBuffInfoByAbnormalType(R_PLASMA1.getSkill().getAbnormalType());
final int b = b_info == null ? 0 : b_info.getSkill().getAbnormalLvl();
final int c = c_info == null ? 0 : c_info.getSkill().getAbnormalLvl();
final int r = r_info == null ? 0 : r_info.getSkill().getAbnormalLvl();
if ((b == 3) && (c == 0) && (r == 0))
{
showOnScreenMsg(player, NpcStringId.ENOUGH_MAGUEN_PLASMA_BISTAKON_HAVE_GATHERED, 2, 4000);
player.getEffectList().stopSkillEffects(true, B_PLASMA1.getSkill().getAbnormalType());
npc.setTarget(player);
npc.doCast((getRandom(100) < 70) ? B_BUFF_1.getSkill() : B_BUFF_2.getSkill());
maguenPetChance(player);
startQuestTimer("END_TIMER", 3000, npc, player);
}
else if ((b == 0) && (c == 3) && (r == 0))
{
showOnScreenMsg(player, NpcStringId.ENOUGH_MAGUEN_PLASMA_COKRAKON_HAVE_GATHERED, 2, 4000);
player.getEffectList().stopSkillEffects(true, C_PLASMA1.getSkill().getAbnormalType());
npc.setTarget(player);
npc.doCast((getRandom(100) < 70) ? C_BUFF_1.getSkill() : C_BUFF_2.getSkill());
maguenPetChance(player);
startQuestTimer("END_TIMER", 3000, npc, player);
}
else if ((b == 0) && (c == 0) && (r == 3))
{
showOnScreenMsg(player, NpcStringId.ENOUGH_MAGUEN_PLASMA_LEPTILIKON_HAVE_GATHERED, 2, 4000);
player.getEffectList().stopSkillEffects(true, R_PLASMA1.getSkill().getAbnormalType());
npc.setTarget(player);
npc.doCast((getRandom(100) < 70) ? R_BUFF_1.getSkill() : R_BUFF_2.getSkill());
maguenPetChance(player);
startQuestTimer("END_TIMER", 3000, npc, player);
}
else if ((b + c + r) == 3)
{
if ((b == 1) && (c == 1) && (r == 1))
{
player.getEffectList().stopSkillEffects(true, B_PLASMA1.getSkill().getAbnormalType());
player.getEffectList().stopSkillEffects(true, C_PLASMA1.getSkill().getAbnormalType());
player.getEffectList().stopSkillEffects(true, R_PLASMA1.getSkill().getAbnormalType());
showOnScreenMsg(player, NpcStringId.THE_PLASMAS_HAVE_FILLED_THE_AEROSCOPE_AND_ARE_HARMONIZED, 2, 4000);
SkillHolder skillToCast = null;
switch (getRandom(3))
{
case 0:
skillToCast = (getRandom(100) < 70) ? B_BUFF_1 : B_BUFF_2;
break;
case 1:
skillToCast = (getRandom(100) < 70) ? C_BUFF_1 : C_BUFF_2;
break;
case 2:
skillToCast = (getRandom(100) < 70) ? R_BUFF_1 : R_BUFF_2;
break;
}
if (skillToCast != null)
{
npc.setTarget(player);
npc.doCast(skillToCast.getSkill());
}
maguenPetChance(player);
startQuestTimer("END_TIMER", 3000, npc, player);
}
else
{
showOnScreenMsg(player, NpcStringId.THE_PLASMAS_HAVE_FILLED_THE_AEROSCOPE_BUT_THEY_ARE_RAMMING_INTO_EACH_OTHER_EXPLODING_AND_DYING, 2, 4000);
player.getEffectList().stopSkillEffects(true, B_PLASMA1.getSkill().getAbnormalType());
player.getEffectList().stopSkillEffects(true, C_PLASMA1.getSkill().getAbnormalType());
player.getEffectList().stopSkillEffects(true, R_PLASMA1.getSkill().getAbnormalType());
}
}
else
{
startQuestTimer("END_TIMER", 1000, npc, player);
}
npc.setDisplayEffect(4);
return super.onSpellFinished(npc, player, skill);
}
@Override
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
{
if ((skill == MACHINE.getSkill()) && (caster == npc.getVariables().getObject("SUMMON_PLAYER", L2PcInstance.class)))
{
if ((npc.getVariables().getInt("NPC_EFFECT") != 0) && (npc.getVariables().getInt("BLOCKED_SKILLSEE") == 0))
{
final BuffInfo i1_info = caster.getEffectList().getBuffInfoByAbnormalType(B_PLASMA1.getSkill().getAbnormalType());
final BuffInfo i2_info = caster.getEffectList().getBuffInfoByAbnormalType(C_PLASMA1.getSkill().getAbnormalType());
final BuffInfo i3_info = caster.getEffectList().getBuffInfoByAbnormalType(R_PLASMA1.getSkill().getAbnormalType());
final int i1 = i1_info == null ? 0 : i1_info.getSkill().getAbnormalLvl();
final int i2 = i2_info == null ? 0 : i2_info.getSkill().getAbnormalLvl();
final int i3 = i3_info == null ? 0 : i3_info.getSkill().getAbnormalLvl();
caster.getEffectList().stopSkillEffects(true, B_PLASMA1.getSkill().getAbnormalType());
caster.getEffectList().stopSkillEffects(true, C_PLASMA1.getSkill().getAbnormalType());
caster.getEffectList().stopSkillEffects(true, R_PLASMA1.getSkill().getAbnormalType());
cancelQuestTimer("FIRST_TIMER", npc, caster);
cancelQuestTimer("SECOND_TIMER", npc, caster);
cancelQuestTimer("THIRD_TIMER", npc, caster);
cancelQuestTimer("FORTH_TIMER", npc, caster);
npc.getVariables().set("BLOCKED_SKILLSEE", 1);
SkillHolder skillToCast = null;
switch (npc.getVariables().getInt("NPC_EFFECT"))
{
case 1:
{
switch (i1)
{
case 0:
skillToCast = B_PLASMA1;
break;
case 1:
skillToCast = B_PLASMA2;
break;
case 2:
skillToCast = B_PLASMA3;
break;
}
break;
}
case 2:
{
switch (i2)
{
case 0:
skillToCast = C_PLASMA1;
break;
case 1:
skillToCast = C_PLASMA2;
break;
case 2:
skillToCast = C_PLASMA3;
break;
}
break;
}
case 3:
{
switch (i3)
{
case 0:
skillToCast = R_PLASMA1;
break;
case 1:
skillToCast = R_PLASMA2;
break;
case 2:
skillToCast = R_PLASMA3;
break;
}
break;
}
}
if (skillToCast != null)
{
npc.setTarget(caster);
npc.doCast(skillToCast.getSkill());
}
}
}
return super.onSkillSee(npc, caster, skill, targets, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
if (killer.isInParty())
{
final L2PcInstance partyMember = getRandomPartyMember(killer);
final int i0 = 10 + (10 * killer.getParty().getMemberCount());
if ((getRandom(1000) < i0) && (npc.calculateDistance(killer, true, false) < 2000) && (npc.calculateDistance(partyMember, true, false) < 2000))
{
notifyEvent("SPAWN_MAGUEN", npc, partyMember);
}
}
return super.onKill(npc, killer, isSummon);
}
private void maguenPetChance(L2PcInstance player)
{
final int chance1 = getRandom(10000);
final int chance2 = getRandom(20);
if ((chance1 == 0) && (chance2 != 0))
{
giveItems(player, MAGUEN_PET, 1);
}
else if ((chance1 == 0) && (chance2 == 0))
{
giveItems(player, ELITE_MAGUEN_PET, 1);
}
}
private Quest nemoAi()
{
return QuestManager.getInstance().getQuest(Nemo.class.getSimpleName());
}
}

View File

@@ -0,0 +1,4 @@
<html><body>Gatekeeper of the Abyss:<br>
The gaze seems to lose interest and move on from you.<br>
It appears that no one will be accepted at this time.
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Gatekeeper of the Abyss:<br>
The way to the Heart of Infinity is opened, you should truly feel it's gaze. You will need much experience and courage to defeat Ekimus.<br>
(Heart of Infinity is an instant zone for 18 - 27 players united in Command channel).<br>
<a action="bypass -h npc_%objectId%_Quest HeartInfinityAttack">Challenge Ekimus.</a>
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Gatekeeper of the Abyss:<br>
You don't feel any cold energy from the gaze.<br>
Apparently the recovered souls are confusing Gatekeeper's judgement.<br>
You may enter the Seed with an invitation, but nobody knows where you will be moved to.<br>
<!--<a action="bypass -h Quest AbyssGaze enter_seed">Enter the Seed.</a>-->
<a action="bypass -h npc_%objectId%_Quest HeartInfinityAttack">Enter the Seed.</a>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Gatekeeper of the Abyss:<br>
You sense an icy cold gaze fixed on you from a gigantic structure that seems somehow not quite alive nor dead. You must pass its judgment to enter the <font color="LEVEL">heart of the Seed of Infinity</font>; if you wish to avoid it, you will be expelled <font color="LEVEL">outside the Seed of Infinity</font>. However, the gaze isn't as painful as you feared. Has something happened to Ekimus?<br>
<a action="bypass -h Quest AbyssGaze request_permission">Withstand the gaze.</a><br>
<a action="bypass -h npc_%objectId%_goto 14001">Say yes.</a>
</body></html>

View File

@@ -0,0 +1,86 @@
/*
* 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 gracia.AI.NPC.AbyssGaze;
import com.l2jmobius.gameserver.instancemanager.SoIManager;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.quest.QuestState;
import ai.npc.AbstractNpcAI;
public class AbyssGaze extends AbstractNpcAI
{
// NPC
private static final int ABYSS_GATEKEEPER = 32539;
public AbyssGaze()
{
super(AbyssGaze.class.getSimpleName(), "gracia/AI/NPC");
addStartNpc(ABYSS_GATEKEEPER);
addFirstTalkId(ABYSS_GATEKEEPER);
addTalkId(ABYSS_GATEKEEPER);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = event;
QuestState st = player.getQuestState(getName());
if (st == null)
{
st = newQuestState(player);
}
if (event.equals("request_permission"))
{
if ((SoIManager.getCurrentStage() == 2) || (SoIManager.getCurrentStage() == 5))
{
htmltext = "32539-2.htm";
}
else if ((SoIManager.getCurrentStage() == 3) && SoIManager.isSeedOpen())
{
htmltext = "32539-3.htm";
}
else
{
htmltext = "32539-1.htm";
}
}
else if (event.equals("enter_seed"))
{
if (SoIManager.getCurrentStage() == 3)
{
return null;
}
}
return htmltext;
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
QuestState qs = player.getQuestState(getName());
if (qs == null)
{
qs = newQuestState(player);
}
return "32539.htm";
}
}

View File

@@ -0,0 +1,6 @@
<html><body>Mouth of Ekimus:<br>
The echoes of the screams of the dying spread to the other side of the gap.<br>
The name <font color="LEVEL">Hall of Suffering</font> seems to suit this place where new souls are made.<br>
(The Hall of Suffering is an instant zone exclusively for party use.)<br>
<a action="bypass -h npc_%objectId%_Quest HallOfSufferingAttack">Enter to the Hall of Suffering.</a>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Mouth of Ekimus:<br>
The echoes of the screams of the dying spread to the other side of the gap.<br>
The name <font color="LEVEL">Hall of Suffering</font> seems to suit this place where new souls are made.<br>
(The Hall of Suffering is an instant zone exclusively for party use.)<br>
<a action="bypass -h npc_%objectId%_Quest HallOfSufferingDefence">Enter to the Hall of Suffering.</a>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Mouth of Ekimus:<br>
As if they're the flames that have been put out, the low moaning sound from falling souls spreads over the other side of the gap.<br>
It seems to be a passage to <font color="LEVEL">Hall of Erosion</font> where the souls are sucked into Ekimus and part of Seed of Immortality.<br>
(Hall of Erosion is an instant zone exclusively for command channel where minimum 18 and maximum 27 people can enter.)<br>
<a action="bypass -h npc_%objectId%_Quest HallOfErosionAttack">Enter to the Hall of Erosion.</a>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Mouth of Ekimus:<br>
As if they're the flames that have been put out, the low moaning sound from falling souls spreads over the other side of the gap.<br>
It seems to be a passage to <font color="LEVEL">Hall of Erosion</font> where the souls are sucked into Ekimus and part of Seed of Immortality.<br>
(Hall of Erosion is an instant zone exclusively for command channel where minimum 18 and maximum 27 people can enter.)<br>
<a action="bypass -h npc_%objectId%_Quest HallOfErosionDefence">Enter to the Hall of Erosion.</a>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Mouth of Ekimus:<br>
There is a narrow path among the decomposed flesh and frayed yellow bones. It is surrounded by the feel of death and the stench of decay.<br>
It seems that you must pass through the gap to secretly enter one of many <font color="LEVEL">halls</font> of the Seed of Infinity inside.<br>
<a action="bypass -h Quest EkimusMouth hos_enter">Pass through the gap and into the Hall of Suffering.</a><br>
<a action="bypass -h Quest EkimusMouth hoe_enter">Pass through the gap and into the Hall of Erosion.</a>
</body></html>

View File

@@ -0,0 +1,86 @@
/*
* 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 gracia.AI.NPC.EkimusMouth;
import com.l2jmobius.gameserver.instancemanager.SoIManager;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.quest.QuestState;
import ai.npc.AbstractNpcAI;
public class EkimusMouth extends AbstractNpcAI
{
// NPC
private static final int EKIMUS_MOUTH = 32537;
public EkimusMouth()
{
super(EkimusMouth.class.getSimpleName(), "gracia/AI/NPC");
addStartNpc(EKIMUS_MOUTH);
addFirstTalkId(EKIMUS_MOUTH);
addTalkId(EKIMUS_MOUTH);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = event;
QuestState qs = player.getQuestState(getName());
if (qs == null)
{
qs = newQuestState(player);
}
if (event.equalsIgnoreCase("hos_enter"))
{
if (SoIManager.getCurrentStage() == 1)
{
htmltext = "32537-1.htm";
}
else if (SoIManager.getCurrentStage() == 4)
{
htmltext = "32537-2.htm";
}
}
else if (event.equalsIgnoreCase("hoe_enter"))
{
if (SoIManager.getCurrentStage() == 1)
{
htmltext = "32537-3.htm";
}
else if (SoIManager.getCurrentStage() == 4)
{
htmltext = "32537-4.htm";
}
}
return htmltext;
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
QuestState qs = player.getQuestState(getName());
if (qs == null)
{
qs = newQuestState(player);
}
return "32537.htm";
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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 gracia.AI.NPC.FortuneTelling;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
import ai.npc.AbstractNpcAI;
/**
* Fortune Telling AI.<br>
* Original Jython script by Kerberos.
* @author Nyaran
*/
public class FortuneTelling extends AbstractNpcAI
{
// NPC
private static final int MINE = 32616;
// Misc
private static final int COST = 1000;
public FortuneTelling()
{
super(FortuneTelling.class.getSimpleName(), "gracia/AI/NPC");
addStartNpc(MINE);
addTalkId(MINE);
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
String htmltext = getNoQuestMsg(player);
if (player.getAdena() < COST)
{
htmltext = "lowadena.htm";
}
else
{
takeItems(player, Inventory.ADENA_ID, COST);
htmltext = getHtm(player.getHtmlPrefix(), "fortune.htm").replace("%fortune%", String.valueOf(getRandom(1800309, 1800695)));
}
return htmltext;
}
}

View File

@@ -0,0 +1,6 @@
<html><body>Fortune-Teller Mine:<br>
I see an image approaching before you... It is difficult to put what I saw into words.<br>
How can I say this? Okay, listen closely:<br>
<center><fstring>%fortune%</fstring></center><br><br>
Take these words to heart. You should seriously consider the meaning...
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Fortune-Teller Mine:<br>
Very well. I perceive you either cannot afford my offer or are not ready to learn your future.<br>
No matter! Your future is still there waiting for you. Good luck!
</body></html>

View File

@@ -0,0 +1,110 @@
/*
* 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 gracia.AI.NPC.GeneralDilios;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.model.L2Spawn;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
import ai.npc.AbstractNpcAI;
/**
* Dilios AI
* @author JIV, Sephiroth, Apocalipce
*/
public final class GeneralDilios extends AbstractNpcAI
{
private static final int GENERAL_ID = 32549;
private static final int GUARD_ID = 32619;
private L2Npc _general = null;
private final Set<L2Spawn> _guards = Collections.newSetFromMap(new ConcurrentHashMap<L2Spawn, Boolean>());
private static final NpcStringId[] DILIOS_TEXT =
{
NpcStringId.MESSENGER_INFORM_THE_PATRONS_OF_THE_KEUCEREUS_ALLIANCE_BASE_WE_RE_GATHERING_BRAVE_ADVENTURERS_TO_ATTACK_TIAT_S_MOUNTED_TROOP_THAT_S_ROOTED_IN_THE_SEED_OF_DESTRUCTION,
// NpcStringId.MESSENGER_INFORM_THE_PATRONS_OF_THE_KEUCEREUS_ALLIANCE_BASE_THE_SEED_OF_DESTRUCTION_IS_CURRENTLY_SECURED_UNDER_THE_FLAG_OF_THE_KEUCEREUS_ALLIANCE,
// NpcStringId.MESSENGER_INFORM_THE_PATRONS_OF_THE_KEUCEREUS_ALLIANCE_BASE_TIATS_MOUNTED_TROOP_IS_CURRENTLY_TRYING_TO_RETAKE_SEED_OF_DESTRUCTION_COMMIT_ALL_THE_AVAILABLE_REINFORCEMENTS_INTO_SEED_OF_DESTRUCTION,
NpcStringId.MESSENGER_INFORM_THE_BROTHERS_IN_KUCEREUS_CLAN_OUTPOST_BRAVE_ADVENTURERS_WHO_HAVE_CHALLENGED_THE_SEED_OF_INFINITY_ARE_CURRENTLY_INFILTRATING_THE_HALL_OF_EROSION_THROUGH_THE_DEFENSIVELY_WEAK_HALL_OF_SUFFERING,
// NpcStringId.MESSENGER_INFORM_THE_BROTHERS_IN_KUCEREUS_CLAN_OUTPOST_SWEEPING_THE_SEED_OF_INFINITY_IS_CURRENTLY_COMPLETE_TO_THE_HEART_OF_THE_SEED_EKIMUS_IS_BEING_DIRECTLY_ATTACKED_AND_THE_UNDEAD_REMAINING_IN_THE_HALL_OF_SUFFERING_ARE_BEING_ERADICATED,
NpcStringId.MESSENGER_INFORM_THE_PATRONS_OF_THE_KEUCEREUS_ALLIANCE_BASE_THE_SEED_OF_INFINITY_IS_CURRENTLY_SECURED_UNDER_THE_FLAG_OF_THE_KEUCEREUS_ALLIANCE
// NpcStringId.MESSENGER_INFORM_THE_PATRONS_OF_THE_KEUCEREUS_ALLIANCE_BASE_THE_RESURRECTED_UNDEAD_IN_THE_SEED_OF_INFINITY_ARE_POURING_INTO_THE_HALL_OF_SUFFERING_AND_THE_HALL_OF_EROSION
// NpcStringId.MESSENGER_INFORM_THE_BROTHERS_IN_KUCEREUS_CLAN_OUTPOST_EKIMUS_IS_ABOUT_TO_BE_REVIVED_BY_THE_RESURRECTED_UNDEAD_IN_SEED_OF_INFINITY_SEND_ALL_REINFORCEMENTS_TO_THE_HEART_AND_THE_HALL_OF_SUFFERING
};
public GeneralDilios()
{
super(GeneralDilios.class.getSimpleName(), "gracia/AI/NPC");
addSpawnId(GENERAL_ID, GUARD_ID);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.startsWith("command_"))
{
int value = Integer.parseInt(event.substring(8));
if (value < 6)
{
_general.broadcastPacket(new NpcSay(_general.getObjectId(), ChatType.NPC_GENERAL, GENERAL_ID, NpcStringId.STABBING_THREE_TIMES));
startQuestTimer("guard_animation_0", 3400, null, null);
}
else
{
value = -1;
_general.broadcastPacket(new NpcSay(_general.getObjectId(), ChatType.NPC_SHOUT, GENERAL_ID, DILIOS_TEXT[getRandom(DILIOS_TEXT.length)]));
}
startQuestTimer("command_" + (value + 1), 60000, null, null);
}
else if (event.startsWith("guard_animation_"))
{
final int value = Integer.parseInt(event.substring(16));
for (L2Spawn guard : _guards)
{
guard.getLastSpawn().broadcastSocialAction(4);
}
if (value < 2)
{
startQuestTimer("guard_animation_" + (value + 1), 1500, null, null);
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSpawn(L2Npc npc)
{
if (npc.getId() == GENERAL_ID)
{
startQuestTimer("command_0", 60000, null, null);
_general = npc;
}
else if (npc.getId() == GUARD_ID)
{
_guards.add(npc.getSpawn());
}
return super.onSpawn(npc);
}
}

View File

@@ -0,0 +1,7 @@
<html><body>Engineer Lekon:<br>
Airship, eh? If you want board an Airship, you need to first register for a Summon License. There's a switch on the Airship controls that proves your qualifications to summon and pilot it. Unless you obtain that license, you won't be allowed to fly.<br>
Only <font color="LEVEL">clan lords whose clan is level 5 or higher</font> may earn the license. There is also a limit on the number of Airships.<br>
If you meet the requirements, you can obtain a Airship Summon License in exchange for <font color="LEVEL">10 Energy Star Stones</font>.<br>
An Energy Star Stone can be made by assembling Star Stones found floating in the skies over Gracia. If you thinkk this is too time-consuming, you can also buy them from Officer Tolonis right over there..<br>
<a action="bypass -h Quest Lekon licence">Obtain the Airship Summon License.</a>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Engineer Lekon:<br>
Only a clan lord whose clan is level 5 or above can be issued an Airship Summon License.
</body></html>

View File

@@ -0,0 +1,3 @@
<html><head><body>Engineer Lekon:<br>
You don't have enough Energy Star Stones yet. You can make them by assembling Star Stones found floating in the skies over Gracia. If you prefer, you can also purchase them from Officer Tolonis.
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Engineer Lekon:<br>
Hey, I see here that you already have a Airship Summon License! Haven't you registered it yet? Or did you lose it already?
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Engineer Lekon:<br>
I'm too busy to take a breath! I'm supposed to maintain all these Airships and air vehicles by myself?! How does that make sense?<br>
And it's all very detailed, time-consuming work with no margin for error. Somebody up there must really hate me!<br>
Well, at least they supply me with the materials I need. Hey, adventurer! You must know how to use Airships or air vehicles. Care to lend me a hand?<br>
<a action="bypass -h Quest Lekon 32557-01.html">Ask about Airship Summon License.</a><br>
<a action="bypass -h npc_%objectId%_Quest">Quest</a>
</body></html>

View File

@@ -0,0 +1,90 @@
/*
* 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 gracia.AI.NPC.Lekon;
import com.l2jmobius.gameserver.instancemanager.AirShipManager;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.SystemMessageId;
import ai.npc.AbstractNpcAI;
/**
* Lekon AI.
* @author St3eT
*/
public final class Lekon extends AbstractNpcAI
{
// NPCs
private static final int LEKON = 32557;
// Items
private static final int LICENCE = 13559; // Airship Summon License
private static final int STONE = 13277; // Energy Star Stone
// Misc
private static final int MIN_CLAN_LV = 5;
private static final int STONE_COUNT = 10;
public Lekon()
{
super(Lekon.class.getSimpleName(), "gracia/AI/NPC");
addFirstTalkId(LEKON);
addTalkId(LEKON);
addStartNpc(LEKON);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = null;
switch (event)
{
case "32557-01.html":
{
htmltext = event;
break;
}
case "licence":
{
final L2Clan clan = player.getClan();
if ((clan == null) || !player.isClanLeader() || (clan.getLevel() < MIN_CLAN_LV))
{
htmltext = "32557-02.html";
}
else if (hasAtLeastOneQuestItem(player, LICENCE))
{
htmltext = "32557-04.html";
}
else if (AirShipManager.getInstance().hasAirShipLicense(clan.getId()))
{
player.sendPacket(SystemMessageId.THE_AIRSHIP_SUMMON_LICENSE_HAS_ALREADY_BEEN_ACQUIRED);
}
else if (getQuestItemsCount(player, STONE) >= STONE_COUNT)
{
takeItems(player, STONE, STONE_COUNT);
giveItems(player, LICENCE, 1);
}
else
{
htmltext = "32557-03.html";
}
break;
}
}
return htmltext;
}
}

View File

@@ -0,0 +1,8 @@
<html><body>Nemo:<br>
I have no information about the origins of this species, but what I have found is that these creatures do possess a unique energy, sort of plasma if you will. Hmm... <font color="LEVEL">Maguen Plasma</font>. I like that. I think that is what I'll call it. Anyway, when a Maguen appears it begins to bring forth one of these plasmas. It will also cycle through its various plasmas before hiding.<br>
With Blacksmith Kusto's talent and my magic we were able to create a device that could harvest these plasmas... a <font color="LEVEL">Maguen Plasma Collector</font>. I know it isn't too creative but we decided to keep the name simple to avoid explaining what it does.<br>
Ugh... fine. I'll explain it to you. When you are in the Seed and a Maguen appears you have a very limited time to collect the Maguen Plasma. If you don't collect the plasma in time the Maguen will go back into hiding. I've set up a practice Maguen if you want to try using the Maguen Plasma Collector.<br>
This isn't a real Maguen, so you won't collect any Plasma just thought you should know so you don't get your hopes up.<br>
<a action="bypass -h Quest Nemo giveCollector">Receive the Maguen Plasma Collector</a><br>
<a action="bypass -h Quest Nemo summonMaguen">Practice using the Maguen Plasma Collector</a>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Nemo:<br>
Here is the Maguen Plasma Collector.<br>
Remember these rules:<br>
1. Collect <font color="LEVEL">one of each type</font>, or <font color="LEVEL">several of the same type</font>.<br>
2. Collecting random Maguen Plasmas can overload the Plasma Collector and will release any plasma you have collected. Yes, this means you'll have to start all over again.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Nemo:<br>
Are you pulling my leg? You're NOT an adventurer? Or you ARE? You have one? You want another? What is it?! Tell me!!<br>
You've confused me. I don't know what to say... I need a moment...
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Nemo:<br>
Everything needs preparation. Did you think about how you are going to use it when you carry all that stuff? Make yourself lighter, or empty your inventory. Sheez.
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Nemo:<br>
Take a look at the top of the Maguen's head. Observe the aura of the Plasma that the Maguen is producing. Use the Maguen Plasma Collector when the Maguen summons the Plasma you wish to collect.
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Nemo:<br>
This is my magic's limit, now I can't help you. Look around... there are others just like you.
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Nemo:<br>
Who are you? What business do you have with the Great Magician of Oren? Speak! Hmm... not a chatty one, are you? Well if you must know, I am here on important business.<br>
It is said that a mysterious creature can only be found on this Seed. Have you heard of a <font color="LEVEL">Maguen</font>? Yes, I know it is a silly name. But aren't you the least bit intrigued?<br>
<a action="bypass -h Quest Nemo 32735-01.html">What is a Maguen?</a><br>
<a action="bypass -h npc_%objectId%_Quest">Quest</a>
</body></html>

View File

@@ -0,0 +1,120 @@
/*
* 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 gracia.AI.NPC.Nemo;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.instancemanager.QuestManager;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.quest.Quest;
import com.l2jmobius.gameserver.network.NpcStringId;
import ai.npc.AbstractNpcAI;
import gracia.AI.Maguen;
/**
* Nemo AI.
* @author St3eT
*/
public final class Nemo extends AbstractNpcAI
{
// NPC
private static final int NEMO = 32735; // Nemo
private static final int MAGUEN = 18839; // Wild Maguen
// Items
private static final int COLLECTOR = 15487; // Maguen Plasma Collector
// Misc
private static final int MAXIMUM_MAGUEN = 18; // Maximum maguens in one time
public Nemo()
{
super(Nemo.class.getSimpleName(), "gracia/AI/NPC");
addStartNpc(NEMO);
addFirstTalkId(NEMO);
addTalkId(NEMO);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = null;
switch (event)
{
case "32735-01.html":
{
htmltext = event;
break;
}
case "giveCollector":
{
if (hasQuestItems(player, COLLECTOR))
{
htmltext = "32735-03.html";
}
else if (!player.isInventoryUnder90(false))
{
htmltext = "32735-04.html";
}
else
{
htmltext = "32735-02.html";
giveItems(player, COLLECTOR, 1);
}
break;
}
case "summonMaguen":
{
if ((player.getVariables().getInt("TEST_MAGUEN", 0) == 0) && (npc.getScriptValue() < MAXIMUM_MAGUEN))
{
final L2Npc maguen = addSpawn(MAGUEN, npc.getLocation(), true, 60000, true);
maguen.getVariables().set("SUMMON_PLAYER", player);
maguen.getVariables().set("SPAWNED_NPC", npc);
maguen.getVariables().set("TEST_MAGUEN", 1);
player.getVariables().set("TEST_MAGUEN", 1);
maguen.setTitle(player.getName());
maguen.setIsRunning(true);
maguen.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player);
maguen.broadcastStatusUpdate();
showOnScreenMsg(player, NpcStringId.MAGUEN_APPEARANCE, 2, 4000);
maguenAi().startQuestTimer("DIST_CHECK_TIMER", 1000, maguen, player);
npc.setScriptValue(npc.getScriptValue() + 1);
htmltext = "32735-05.html";
}
else
{
htmltext = "32735-06.html";
}
break;
}
case "DECREASE_COUNT":
{
final L2Npc spawnedNpc = npc.getVariables().getObject("SPAWNED_NPC", L2Npc.class);
if ((spawnedNpc != null) && (spawnedNpc.getScriptValue() > 0))
{
player.getVariables().remove("TEST_MAGUEN");
spawnedNpc.setScriptValue(spawnedNpc.getScriptValue() - 1);
}
}
}
return htmltext;
}
private Quest maguenAi()
{
return QuestManager.getInstance().getQuest(Maguen.class.getSimpleName());
}
}

View File

@@ -0,0 +1,5 @@
<html><body>Mage Notingale:<br>
First of all, you must acquire either an Aurabird or an Airship in order to fight against the enemies who populate our skies. Since the number of Airships is limited, I recommend you acquire an Aurabird.<br>
To do so, go meet Engineer Lekon and do what he tells you. Even if you decide to acquire an Airship, Lekon is worth talking to.<br>
Check your map and I will tell you his location.
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Mage Notingale:<br>
Once you have acquired transportaion, the next thing is to fight against those who are attacking us.<br>
Our chief enemies are the monsters of the skies and the Seeds. Since you cannot possible handle either of these by yourself, you should start by gathering a party of your fellows.<br>
<a action="bypass -h Quest Nottingale 32627-03.html">Ask about Aerial Raid Monsters.</a><br>
<a action="bypass -h Quest Nottingale 32627-04.html">Ask about major hunting grounds.</a>
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Mage Notingale:<br>
The following enemies have attacked us from the skies nearby:<br>
<a action="bypass -h Quest Nottingale 32627-05.html">Valdstone the Master Rider</a><br>
<a action="bypass -h Quest Nottingale 32627-06.html">Rok the King of Birds</a><br>
<a action="bypass -h Quest Nottingale 32627-07.html">Enira the Banshee Queen</a><br>
<a action="bypass -h Quest Nottingale 32627-08.html">Dius the Messenger of Destruction</a>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Mage Notigale:<br>
The following Seeds are the main sites of enemy power nearby:<br>
<a action="bypass -h Quest Nottingale 32627-09.html">Seed of Infinity</a><br>
<a action="bypass -h Quest Nottingale 32627-10.html">Seed of Destruction</a>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Mage Notingale:<br>
Valdstone the Master Rider used to be a lord of this land. He gained the power to control wild Aurabirds in exchange for yielding his territory to the Seed of Infinity.<br>
His Elite Riders always watch our fortress. Look at the map to see where he and his minions most frequently appear.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Mage Notingale:<br>
Rok, the King of Birds, used to be the largest and most intelligent bird in Gracia. But since the Seed of Destruction and Storm Dragon Lindvior appeared, he has been in hiding.<br>
As the power of the Seed of Destruction has waned, however, he appears to be regaining his former control over birds. When the power of the Seed of Destruction is weak, you may see Rok if you attack birds nearby. I will mark the areas on the map where he most often appears.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Mage Notingale:<br>
It is said that Enira the Banshee Queen is a subordinate of Ekimus, the ruler of the Seed of Infinity. But I believe differently. It seems as though she is keeping an eye on the Seed of Infinity.<br>
Of course, I'm not saying Enira is on our side. She is still very much a threat. If we hope to travel the skies of Gracia unmolested, she must be defeated. I have marked the areas where she frequently appears on your map.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Mage Notingale:<br>
Dius the Messenger of Destruction is a huge Drake of the Sky. He scours the skies for Tiat, the lord of the Seed of Destruction.<br>
Fortunately, he is normally scarce. If you apply a special <font color="LEVEL">bait for Drakes</font> to <font color="LEVEL">Baby Drake Wings</font>, however, you can lure him out. I will mark the area where he appears on your map.
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Mage Notingale:<br>
I will mark the location of the Seed of Infinity on your map.<br>
It is controlled by Ekimus, the lord of Eternity. His ability to control both living and dead has transformed the whole Seed of Infinity into a living organism...<br>
General Dilios can give you more details.
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Mage Notingale:<br>
I will mark the location of the Seed of Destruction on your map.<br>
It is controlled by Tiat, the lord of the Mounted Troop. The Seed is like a one huge fortress, thwarting any attempts to enter.<br>
General Dilios can give you more details.
</body></html>

View File

@@ -0,0 +1,9 @@
<html><body>Mage Notingale:<br>
Welcome to Gracia! I am here to guide adventures who come from Aden.<br>
It is impossible to walk around in Gracia because of the contamination caused by the Seeds. Most move via Airship, but that is also difficult -- there simply aren't enough for everyone.<br>
The magicians of Aden crafted an alternative plan. It is called an <font color="LEVEL">Aurabird</font>. I think it is the better solution for you.<br>
<a action="bypass -h Quest Nottingale 32627-02.html">Ask what to do.</a><br>
<a action="bypass -h Quest Nottingale 32627-03.html">Ask about Aerial Raid Monsters.</a><br>
<a action="bypass -h Quest Nottingale 32627-04.html">Ask about major hunting grounds.</a><br>
<a action="bypass -h npc_%objectId%_Quest">Quest</a>
</body></html>

View File

@@ -0,0 +1,120 @@
/*
* 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 gracia.AI.NPC.Nottingale;
import java.util.HashMap;
import java.util.Map;
import com.l2jmobius.gameserver.instancemanager.AirShipManager;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.network.serverpackets.RadarControl;
import ai.npc.AbstractNpcAI;
import quests.Q10273_GoodDayToFly.Q10273_GoodDayToFly;
/**
* Nottingale AI
* @author xban1x
*/
public final class Nottingale extends AbstractNpcAI
{
// NPC
private static final int NOTTINGALE = 32627;
// Misc
private static final Map<Integer, RadarControl> RADARS = new HashMap<>();
static
{
RADARS.put(2, new RadarControl(0, -184545, 243120, 1581, 2));
RADARS.put(5, new RadarControl(0, -192361, 254528, 3598, 1));
RADARS.put(6, new RadarControl(0, -174600, 219711, 4424, 1));
RADARS.put(7, new RadarControl(0, -181989, 208968, 4424, 1));
RADARS.put(8, new RadarControl(0, -252898, 235845, 5343, 1));
RADARS.put(9, new RadarControl(0, -212819, 209813, 4288, 1));
RADARS.put(10, new RadarControl(0, -246899, 251918, 4352, 1));
}
public Nottingale()
{
super(Nottingale.class.getSimpleName(), "gracia/AI/NPC");
addStartNpc(NOTTINGALE);
addTalkId(NOTTINGALE);
addFirstTalkId(NOTTINGALE);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = null;
switch (event)
{
case "32627-02.html":
case "32627-03.html":
case "32627-04.html":
{
if (player.getClan() != null)
{
if (player.hasClanPrivilege(ClanPrivilege.CL_SUMMON_AIRSHIP) && AirShipManager.getInstance().hasAirShipLicense(player.getClanId()) && !AirShipManager.getInstance().hasAirShip(player.getClanId()))
{
htmltext = event;
}
else
{
final QuestState st = player.getQuestState(Q10273_GoodDayToFly.class.getSimpleName());
if ((st != null) && st.isCompleted())
{
htmltext = event;
}
else
{
player.sendPacket(RADARS.get(2));
htmltext = "32627-01.html";
}
}
}
else
{
final QuestState st = player.getQuestState(Q10273_GoodDayToFly.class.getSimpleName());
if ((st != null) && st.isCompleted())
{
htmltext = event;
}
else
{
player.sendPacket(RADARS.get(2));
htmltext = "32627-01.html";
}
}
break;
}
case "32627-05.html":
case "32627-06.html":
case "32627-07.html":
case "32627-08.html":
case "32627-09.html":
case "32627-10.html":
{
player.sendPacket(RADARS.get(Integer.valueOf(event.substring(6, 8))));
htmltext = event;
break;
}
}
return htmltext;
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Seyo:<br>
... Okay, who are you? You aren't here to give me a hard time I hope... I'm married already. Can't you just leave me alone...
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Seyo:<br>
If you don't have 5... why are you here....? I said five. One more than four, but not yet six... geez... No silver barrel items unless you have five... I hate my job... Less than five is a brown yellow barrel item... next!
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Seyo:<br>
Is twenty too many? No, not to me... You said you would give, don't change your mind now.... I'm a busy person too... Is it break time yet?
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Seyo:<br>
One at a time... Stand in line... Wait your turn... That's it. It's just a line... You can do it...
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Seyo:<br>
Hello, and welcome to the middle of nowhere. Who am I? I like to think of myself as a business man of sorts. What I offer to you is a game of chance. I am giving you the opportunity to win <font color="LEVEL">Soul Stone Fragments</font>. You agree to give me a predetermined number of fragments. And in return, you have the chance of winning a random number of fragments. Sound good? Well then, how much can I put you down for?<br>
<a action="bypass -h Quest Seyo give1">Give Seyo 1 fragment.</a><br>
<a action="bypass -h Quest Seyo give5">Give Seyo 5 fragments.</a><br>
<a action="bypass -h Quest Seyo give20">Give Seyo 20 fragments.</a><br>
<a action="bypass -h npc_%objectId%_Quest">Quest</a>
</body></html>

View File

@@ -0,0 +1,171 @@
/*
* 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 gracia.AI.NPC.Seyo;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.NpcStringId;
import ai.npc.AbstractNpcAI;
/**
* Seyo AI.
* @author St3eT
*/
public final class Seyo extends AbstractNpcAI
{
// NPC
private static final int SEYO = 32737;
// Item
private static final int STONE_FRAGMENT = 15486; // Spirit Stone Fragment
// Misc
private static final NpcStringId[] TEXT =
{
NpcStringId.NO_ONE_ELSE_DON_T_WORRY_I_DON_T_BITE_HAHA,
NpcStringId.OK_MASTER_OF_LUCK_THAT_S_YOU_HAHA_WELL_ANYONE_CAN_COME_AFTER_ALL,
NpcStringId.SHEDDING_BLOOD_IS_A_GIVEN_ON_THE_BATTLEFIELD_AT_LEAST_IT_S_SAFE_HERE,
NpcStringId.OK_WHO_S_NEXT_IT_ALL_DEPENDS_ON_YOUR_FATE_AND_LUCK_RIGHT_AT_LEAST_COME_AND_TAKE_A_LOOK,
NpcStringId.THERE_WAS_SOMEONE_WHO_WON_10_000_FROM_ME_A_WARRIOR_SHOULDN_T_JUST_BE_GOOD_AT_FIGHTING_RIGHT_YOU_VE_GOTTA_BE_GOOD_IN_EVERYTHING
};
public Seyo()
{
super(Seyo.class.getSimpleName(), "gracia/AI/NPC");
addStartNpc(SEYO);
addTalkId(SEYO);
addFirstTalkId(SEYO);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = null;
if (npc == null)
{
return htmltext;
}
switch (event)
{
case "TRICKERY_TIMER":
{
if (npc.isScriptValue(1))
{
npc.setScriptValue(0);
broadcastNpcSay(npc, ChatType.NPC_GENERAL, TEXT[getRandom(TEXT.length)]);
}
break;
}
case "give1":
{
if (npc.isScriptValue(1))
{
htmltext = "32737-04.html";
}
else if (!hasQuestItems(player, STONE_FRAGMENT))
{
htmltext = "32737-01.html";
}
else
{
npc.setScriptValue(1);
takeItems(player, STONE_FRAGMENT, 1);
if (getRandom(100) == 0)
{
giveItems(player, STONE_FRAGMENT, 100);
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.AMAZING_S1_TOOK_100_OF_THESE_SOUL_STONE_FRAGMENTS_WHAT_A_COMPLETE_SWINDLER, player.getName());
}
else
{
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.HMM_HEY_DID_YOU_GIVE_S1_SOMETHING_BUT_IT_WAS_JUST_1_HAHA, player.getName());
}
startQuestTimer("TRICKERY_TIMER", 5000, npc, null);
}
break;
}
case "give5":
{
if (npc.isScriptValue(1))
{
htmltext = "32737-04.html";
}
else if (getQuestItemsCount(player, STONE_FRAGMENT) < 5)
{
htmltext = "32737-02.html";
}
else
{
npc.setScriptValue(1);
takeItems(player, STONE_FRAGMENT, 5);
final int chance = getRandom(100);
if (chance < 20)
{
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.AHEM_S1_HAS_NO_LUCK_AT_ALL_TRY_PRAYING, player.getName());
}
else if (chance < 80)
{
giveItems(player, STONE_FRAGMENT, 1);
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.IT_S_BETTER_THAN_LOSING_IT_ALL_RIGHT_OR_DOES_THIS_FEEL_WORSE);
}
else
{
final int itemCount = getRandom(10, 16);
giveItems(player, STONE_FRAGMENT, itemCount);
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.S1_PULLED_ONE_WITH_S2_DIGITS_LUCKY_NOT_BAD, player.getName(), String.valueOf(itemCount));
}
startQuestTimer("TRICKERY_TIMER", 5000, npc, null);
}
break;
}
case "give20":
{
if (npc.isScriptValue(1))
{
htmltext = "32737-04.html";
}
else if (getQuestItemsCount(player, STONE_FRAGMENT) < 20)
{
htmltext = "32737-03.html";
}
else
{
npc.setScriptValue(1);
takeItems(player, STONE_FRAGMENT, 20);
final int chance = getRandom(10000);
if (chance == 0)
{
giveItems(player, STONE_FRAGMENT, 10000);
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.AH_IT_S_OVER_WHAT_KIND_OF_GUY_IS_THAT_DAMN_FINE_YOU_S1_TAKE_IT_AND_GET_OUTTA_HERE, player.getName());
}
else if (chance < 10)
{
giveItems(player, STONE_FRAGMENT, 1);
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.YOU_DON_T_FEEL_BAD_RIGHT_ARE_YOU_SAD_BUT_DON_T_CRY);
}
else
{
giveItems(player, STONE_FRAGMENT, getRandom(1, 100));
broadcastNpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.A_BIG_PIECE_IS_MADE_UP_OF_LITTLE_PIECES_SO_HERE_S_A_LITTLE_PIECE);
}
startQuestTimer("TRICKERY_TIMER", 5000, npc, null);
}
break;
}
}
return htmltext;
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Airharbor Guard:<br>
I'm so busy now! I'd be grateful if you could help me!
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Airharbor Guard:<br>
From here you can take an airship to Gracia. Our mission is to maintain the public peace, as ordered by the Magister and Master!<br>
You should know that there are rumors of possible terrorist attacks on the airships, as well as reports of spies trying to infiltrate our realm here!<br>
<a action="bypass -h npc_%objectId%_Quest">Quest.</a>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Airharbor Guard:<br>
From here you can take an airship to Gracia. Our mission is to maintain the public peace, as ordered by the Magister and Master!<br>
You should know that there are rumors of possible terrorist attacks on the airships, as well as reports of spies trying to infiltrate our realm here!<br>
<a action="bypass -h npc_%objectId%_Quest">Quest.</a>
</body></html>

View File

@@ -0,0 +1,94 @@
/*
* 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 gracia.AI.NPC.ZealotOfShilen;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.model.actor.L2Attackable;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import ai.npc.AbstractNpcAI;
/**
* Zealot of Shilen AI.
* @author nonom
*/
public final class ZealotOfShilen extends AbstractNpcAI
{
// NPCs
private static final int ZEALOT = 18782;
private static final int[] GUARDS =
{
32628,
32629
};
public ZealotOfShilen()
{
super(ZealotOfShilen.class.getSimpleName(), "gracia/AI/NPC");
addSpawnId(ZEALOT);
addSpawnId(GUARDS);
addFirstTalkId(GUARDS);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (npc == null)
{
return null;
}
startQuestTimer("WATCHING", 10000, npc, null, true);
if (event.equalsIgnoreCase("WATCHING") && !npc.isAttackingNow())
{
for (L2Character character : npc.getKnownList().getKnownCharacters())
{
if (character.isMonster() && !character.isDead() && !((L2Attackable) character).isDecayed())
{
npc.setRunning();
((L2Attackable) npc).addDamageHate(character, 0, 999);
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, character, null);
}
}
}
return null;
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
return (npc.isAttackingNow()) ? "32628-01.html" : npc.getId() + ".html";
}
@Override
public String onSpawn(L2Npc npc)
{
if (npc.getId() == ZEALOT)
{
npc.setIsNoRndWalk(true);
}
else
{
npc.setIsInvul(true);
((L2Attackable) npc).setCanReturnToSpawnPoint(false);
startQuestTimer("WATCHING", 10000, npc, null, true);
}
return super.onSpawn(npc);
}
}

View File

@@ -0,0 +1,366 @@
/*
* 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 gracia.AI.SeedOfAnnihilation;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import com.l2jmobius.gameserver.datatables.SkillData;
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.type.L2EffectZone;
import com.l2jmobius.gameserver.util.Util;
import ai.npc.AbstractNpcAI;
/**
* Seed Of Annihilation AI.
* @author Gigiikun
*/
public class SeedOfAnnihilation extends AbstractNpcAI
{
private static final Map<Integer, Location> TELEPORT_ZONES = new HashMap<>();
private static final int ANNIHILATION_FURNACE = 18928;
// Strength, Agility, Wisdom
private static final int[] ZONE_BUFFS =
{
0,
6443,
6444,
6442
};
//@formatter:off
private static final int[][] ZONE_BUFFS_LIST =
{
{1, 2, 3},
{1, 3, 2},
{2, 1, 3},
{2, 3, 1},
{3, 2, 1},
{3, 1, 2}
};
//@formatter:on
// 0: Bistakon, 1: Reptilikon, 2: Cokrakon
private final SeedRegion[] _regionsData = new SeedRegion[3];
private Long _seedsNextStatusChange;
static
{
TELEPORT_ZONES.put(60002, new Location(-213175, 182648, -10992));
TELEPORT_ZONES.put(60003, new Location(-181217, 186711, -10528));
TELEPORT_ZONES.put(60004, new Location(-180211, 182984, -15152));
TELEPORT_ZONES.put(60005, new Location(-179275, 186802, -10720));
}
public SeedOfAnnihilation()
{
super(SeedOfAnnihilation.class.getSimpleName(), "gracia/AI");
loadSeedRegionData();
for (int i : TELEPORT_ZONES.keySet())
{
addEnterZoneId(i);
}
for (SeedRegion element : _regionsData)
{
for (int elite_mob_id : element.elite_mob_ids)
{
addSpawnId(elite_mob_id);
}
}
addStartNpc(32739);
addTalkId(32739);
startEffectZonesControl();
}
public void loadSeedRegionData()
{
// Bistakon data
_regionsData[0] = new SeedRegion(new int[]
{
22750,
22751,
22752,
22753
}, new int[][]
{
{
22746,
22746,
22746
},
{
22747,
22747,
22747
},
{
22748,
22748,
22748
},
{
22749,
22749,
22749
}
}, 60006, new int[][]
{
{
-180450,
185507,
-10544,
11632
},
{
-180005,
185489,
-10544,
11632
}
});
// Reptilikon data
_regionsData[1] = new SeedRegion(new int[]
{
22757,
22758,
22759
}, new int[][]
{
{
22754,
22755,
22756
}
}, 60007, new int[][]
{
{
-179600,
186998,
-10704,
11632
},
{
-179295,
186444,
-10704,
11632
}
});
// Cokrakon data
_regionsData[2] = new SeedRegion(new int[]
{
22763,
22764,
22765
}, new int[][]
{
{
22760,
22760,
22761
},
{
22760,
22760,
22762
},
{
22761,
22761,
22760
},
{
22761,
22761,
22762
},
{
22762,
22762,
22760
},
{
22762,
22762,
22761
}
}, 60008, new int[][]
{
{
-180971,
186361,
-10528,
11632
},
{
-180758,
186739,
-10528,
11632
}
});
int buffsNow = 0;
final String var = loadGlobalQuestVar("SeedNextStatusChange");
if (var.equalsIgnoreCase("") || (Long.parseLong(var) < System.currentTimeMillis()))
{
buffsNow = getRandom(ZONE_BUFFS_LIST.length);
saveGlobalQuestVar("SeedBuffsList", String.valueOf(buffsNow));
_seedsNextStatusChange = getNextSeedsStatusChangeTime();
saveGlobalQuestVar("SeedNextStatusChange", String.valueOf(_seedsNextStatusChange));
}
else
{
_seedsNextStatusChange = Long.parseLong(var);
buffsNow = Integer.parseInt(loadGlobalQuestVar("SeedBuffsList"));
}
for (int i = 0; i < _regionsData.length; i++)
{
_regionsData[i].activeBuff = ZONE_BUFFS_LIST[buffsNow][i];
}
}
private Long getNextSeedsStatusChangeTime()
{
final Calendar reenter = Calendar.getInstance();
reenter.set(Calendar.SECOND, 0);
reenter.set(Calendar.MINUTE, 0);
reenter.set(Calendar.HOUR_OF_DAY, 13);
reenter.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
if (reenter.getTimeInMillis() <= System.currentTimeMillis())
{
reenter.add(Calendar.DAY_OF_MONTH, 7);
}
return reenter.getTimeInMillis();
}
private void startEffectZonesControl()
{
for (int i = 0; i < _regionsData.length; i++)
{
for (int j = 0; j < _regionsData[i].af_spawns.length; j++)
{
_regionsData[i].af_npcs[j] = addSpawn(ANNIHILATION_FURNACE, _regionsData[i].af_spawns[j][0], _regionsData[i].af_spawns[j][1], _regionsData[i].af_spawns[j][2], _regionsData[i].af_spawns[j][3], false, 0);
_regionsData[i].af_npcs[j].setDisplayEffect(_regionsData[i].activeBuff);
}
ZoneManager.getInstance().getZoneById(_regionsData[i].buff_zone, L2EffectZone.class).addSkill(ZONE_BUFFS[_regionsData[i].activeBuff], 1);
}
startQuestTimer("ChangeSeedsStatus", _seedsNextStatusChange - System.currentTimeMillis(), null, null);
}
private void spawnGroupOfMinion(L2MonsterInstance npc, int[] mobIds)
{
for (int mobId : mobIds)
{
addMinion(npc, mobId);
}
}
@Override
public String onSpawn(L2Npc npc)
{
for (SeedRegion element : _regionsData)
{
if (Util.contains(element.elite_mob_ids, npc.getId()))
{
spawnGroupOfMinion((L2MonsterInstance) npc, element.minion_lists[getRandom(element.minion_lists.length)]);
}
}
return super.onSpawn(npc);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equalsIgnoreCase("ChangeSeedsStatus"))
{
final int buffsNow = getRandom(ZONE_BUFFS_LIST.length);
saveGlobalQuestVar("SeedBuffsList", String.valueOf(buffsNow));
_seedsNextStatusChange = getNextSeedsStatusChangeTime();
saveGlobalQuestVar("SeedNextStatusChange", String.valueOf(_seedsNextStatusChange));
for (int i = 0; i < _regionsData.length; i++)
{
_regionsData[i].activeBuff = ZONE_BUFFS_LIST[buffsNow][i];
for (L2Npc af : _regionsData[i].af_npcs)
{
af.setDisplayEffect(_regionsData[i].activeBuff);
}
final L2EffectZone zone = ZoneManager.getInstance().getZoneById(_regionsData[i].buff_zone, L2EffectZone.class);
zone.clearSkills();
zone.addSkill(ZONE_BUFFS[_regionsData[i].activeBuff], 1);
}
startQuestTimer("ChangeSeedsStatus", _seedsNextStatusChange - System.currentTimeMillis(), null, null);
}
else if (event.equalsIgnoreCase("transform"))
{
if (player.isAffectedBySkill(6408))
{
npc.showChatWindow(player, 2);
}
else
{
npc.setTarget(player);
npc.doCast(SkillData.getInstance().getSkill(6408, 1));
npc.doCast(SkillData.getInstance().getSkill(6649, 1));
npc.showChatWindow(player, 1);
}
}
return null;
}
@Override
public String onEnterZone(L2Character character, L2ZoneType zone)
{
if (TELEPORT_ZONES.containsKey(zone.getId()))
{
final Location teleLoc = TELEPORT_ZONES.get(zone.getId());
character.teleToLocation(teleLoc, false);
}
return super.onEnterZone(character, zone);
}
private static class SeedRegion
{
public int[] elite_mob_ids;
public int[][] minion_lists;
public int buff_zone;
public int[][] af_spawns;
public L2Npc[] af_npcs = new L2Npc[2];
public int activeBuff = 0;
public SeedRegion(int[] emi, int[][] ml, int bz, int[][] as)
{
elite_mob_ids = emi;
minion_lists = ml;
buff_zone = bz;
af_spawns = as;
}
}
}

View File

@@ -0,0 +1,97 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gracia.AI;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.SystemMessageId;
import ai.npc.AbstractNpcAI;
/**
* Star Stones AI.
* @author Gigiikun
*/
public class StarStones extends AbstractNpcAI
{
// @formatter:off
private static final int[] MOBS =
{
18684, 18685, 18686, 18687, 18688, 18689, 18690, 18691, 18692
};
// @formatter:on
private static final int COLLECTION_RATE = 1;
public StarStones()
{
super(StarStones.class.getSimpleName(), "gracia/AI");
addSkillSeeId(MOBS);
}
@Override
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
{
if (skill.getId() == 932)
{
int itemId = 0;
switch (npc.getId())
{
case 18684:
case 18685:
case 18686:
// give Red item
itemId = 14009;
break;
case 18687:
case 18688:
case 18689:
// give Blue item
itemId = 14010;
break;
case 18690:
case 18691:
case 18692:
// give Green item
itemId = 14011;
break;
default:
// unknown npc!
return super.onSkillSee(npc, caster, skill, targets, isSummon);
}
if (getRandom(100) < 33)
{
caster.sendPacket(SystemMessageId.YOUR_COLLECTION_HAS_SUCCEEDED);
caster.addItem("StarStone", itemId, getRandom(COLLECTION_RATE + 1, 2 * COLLECTION_RATE), null, true);
}
else if (((skill.getLevel() == 1) && (getRandom(100) < 15)) || ((skill.getLevel() == 2) && (getRandom(100) < 50)) || ((skill.getLevel() == 3) && (getRandom(100) < 75)))
{
caster.sendPacket(SystemMessageId.YOUR_COLLECTION_HAS_SUCCEEDED);
caster.addItem("StarStone", itemId, getRandom(1, COLLECTION_RATE), null, true);
}
else
{
caster.sendPacket(SystemMessageId.THE_COLLECTION_HAS_FAILED);
}
npc.deleteMe();
}
return super.onSkillSee(npc, caster, skill, targets, isSummon);
}
}

View File

@@ -0,0 +1,109 @@
/*
* 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 gracia;
import java.util.logging.Level;
import java.util.logging.Logger;
import gracia.AI.EnergySeeds;
import gracia.AI.Lindvior;
import gracia.AI.Maguen;
import gracia.AI.StarStones;
import gracia.AI.NPC.AbyssGaze.AbyssGaze;
import gracia.AI.NPC.EkimusMouth.EkimusMouth;
import gracia.AI.NPC.FortuneTelling.FortuneTelling;
import gracia.AI.NPC.GeneralDilios.GeneralDilios;
import gracia.AI.NPC.Lekon.Lekon;
import gracia.AI.NPC.Nemo.Nemo;
import gracia.AI.NPC.Nottingale.Nottingale;
import gracia.AI.NPC.Seyo.Seyo;
import gracia.AI.NPC.ZealotOfShilen.ZealotOfShilen;
import gracia.AI.SeedOfAnnihilation.SeedOfAnnihilation;
import gracia.instances.HallOfErosionAttack.HallOfErosionAttack;
import gracia.instances.HallOfErosionDefence.HallOfErosionDefence;
import gracia.instances.HallOfSufferingAttack.HallOfSufferingAttack;
import gracia.instances.HallOfSufferingDefence.HallOfSufferingDefence;
import gracia.instances.HeartInfinityAttack.HeartInfinityAttack;
import gracia.instances.HeartInfinityDefence.HeartInfinityDefence;
import gracia.instances.SecretArea.SecretArea;
import gracia.instances.SeedOfDestruction.SeedOfDestruction;
import gracia.vehicles.AirShipGludioGracia.AirShipGludioGracia;
import gracia.vehicles.KeucereusNorthController.KeucereusNorthController;
import gracia.vehicles.KeucereusSouthController.KeucereusSouthController;
import gracia.vehicles.SoDController.SoDController;
import gracia.vehicles.SoIController.SoIController;
/**
* Gracia class-loader.
* @author Pandragon
*/
public final class GraciaLoader
{
private static final Logger _log = Logger.getLogger(GraciaLoader.class.getName());
private static final Class<?>[] SCRIPTS =
{
// AIs
EnergySeeds.class,
Lindvior.class,
Maguen.class,
StarStones.class,
// NPCs
AbyssGaze.class,
EkimusMouth.class,
FortuneTelling.class,
GeneralDilios.class,
Lekon.class,
Nemo.class,
Nottingale.class,
Seyo.class,
ZealotOfShilen.class,
// Seed of Annihilation
SeedOfAnnihilation.class,
// Instances
SecretArea.class,
SeedOfDestruction.class,
HallOfErosionAttack.class,
HallOfErosionDefence.class,
HallOfSufferingAttack.class,
HallOfSufferingDefence.class,
HeartInfinityAttack.class,
HeartInfinityDefence.class,
// Vehicles
AirShipGludioGracia.class,
KeucereusNorthController.class,
KeucereusSouthController.class,
SoIController.class,
SoDController.class,
};
public static void main(String[] args)
{
_log.info(GraciaLoader.class.getSimpleName() + ": Loading Gracia related scripts.");
for (Class<?> script : SCRIPTS)
{
try
{
script.newInstance();
}
catch (Exception e)
{
_log.log(Level.SEVERE, GraciaLoader.class.getSimpleName() + ": Failed loading " + script.getSimpleName() + ":", e);
}
}
}
}

View File

@@ -0,0 +1,705 @@
/*
* 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 gracia.instances.HallOfErosionAttack;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.instancemanager.SoIManager;
import com.l2jmobius.gameserver.model.L2CommandChannel;
import com.l2jmobius.gameserver.model.L2Party;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Instance;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import com.l2jmobius.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.util.Util;
import com.l2jmobius.util.Rnd;
import ai.npc.AbstractNpcAI;
import quests.Q00696_ConquerTheHallOfErosion.Q00696_ConquerTheHallOfErosion;
public class HallOfErosionAttack extends AbstractNpcAI
{
protected class HEAWorld extends InstanceWorld
{
public List<L2Npc> npcList = new ArrayList<>();
public List<L2Npc> deadTumors = new ArrayList<>();
public int tumorCount = 0;
public L2Npc cohemenes = null;
protected L2Npc deadTumor;
public boolean isBossAttacked = false;
public long startTime = 0;
public synchronized void addTumorCount(int value)
{
tumorCount += value;
}
public synchronized void addTag(int value)
{
tag += value;
}
public HEAWorld()
{
tag = -1;
}
}
private static final int INSTANCEID = 119;
private static final int INSTANCEPENALTY = 24;
private static final int MOUTHOFEKIMUS = 32537;
private static final int TUMOR_ALIVE = 18708;
private static final int TUMOR_DEAD = 32535;
private static int COHEMENES = 25634;
protected boolean conquestEnded = false;
private long tumorRespawnTime;
private static final int[] ENTER_TELEPORT =
{
-179659,
211061,
-12784
};
private static int[] NOTMOVE =
{
18668,
18711,
18708,
TUMOR_DEAD
};
private static final int[] mobs =
{
22516,
22520,
22522,
22524
};
//@formatter:off
private static final int[][] ROOMS_MOBS =
{
{22516, -180364, 211944, -12019, 0, 60, 1},
{22516, -181616, 211413, -12015, 0, 60, 1},
{22520, -181404, 211042, -12023, 0, 60, 1},
{22522, -181558, 212227, -12035, 0, 60, 1},
{22522, -180459, 212322, -12018, 0, 60, 1},
{22524, -180428, 211180, -12014, 0, 60, 1},
{22524, -180718, 212162, -12028, 0, 60, 1},
{22532, -183114, 209397, -11923, 0, 60, 1},
{22532, -182917, 210495, -11925, 0, 60, 1},
{22516, -183918, 210225, -11934, 0, 60, 1},
{22532, -183862, 209909, -11932, 0, 60, 1},
{22532, -183246, 210631, -11923, 0, 60, 1},
{22522, -182971, 210522, -11924, 0, 60, 1},
{22522, -183485, 209406, -11921, 0, 60, 1},
{22516, -183032, 208822, -11923, 0, 60, 1},
{22516, -182709, 207817, -11929, 0, 60, 1},
{22520, -182964, 207746, -11924, 0, 60, 1},
{22520, -183385, 208847, -11922, 0, 60, 1},
{22526, -183684, 208847, -11926, 0, 60, 1},
{22526, -183530, 208725, -11926, 0, 60, 1},
{22532, -183968, 207603, -11928, 0, 60, 1},
{22532, -183608, 208567, -11926, 0, 60, 1},
{22526, -181471, 207159, -12020, 0, 60, 1},
{22526, -180213, 207042, -12013, 0, 60, 1},
{22532, -180213, 206506, -12010, 0, 60, 1},
{22532, -181720, 206643, -12016, 0, 60, 1},
{22516, -181743, 206643, -12018, 0, 60, 1},
{22516, -181028, 205739, -12030, 0, 60, 1},
{22520, -181431, 205980, -12040, 0, 60, 1},
{22524, -178964, 207168, -12014, 0, 60, 1},
{22524, -177658, 207037, -12019, 0, 60, 1},
{22522, -177730, 206558, -12016, 0, 60, 1},
{22522, -179132, 206650, -12011, 0, 60, 1},
{22526, -179132, 206155, -12017, 0, 60, 1},
{22526, -178277, 205754, -12031, 0, 60, 1},
{22516, -178716, 205802, -12020, 0, 60, 1},
{22532, -176565, 207839, -11929, 0, 60, 1},
{22532, -176281, 208822, -11923, 0, 60, 1},
{22520, -175791, 208804, -11923, 0, 60, 1},
{22520, -176259, 207689, -11923, 0, 60, 1},
{22526, -175849, 207508, -11929, 0, 60, 1},
{22526, -175453, 208250, -11930, 0, 60, 1},
{22524, -175738, 207914, -11946, 0, 60, 1},
{22526, -176339, 209425, -11923, 0, 60, 1},
{22526, -176586, 210424, -11928, 0, 60, 1},
{22516, -176586, 210546, -11923, 0, 60, 1},
{22516, -175847, 209365, -11922, 0, 60, 1},
{22520, -175496, 209498, -11924, 0, 60, 1},
{22520, -175538, 210252, -11940, 0, 60, 1},
{22524, -175527, 209744, -11928, 0, 60, 1},
{22520, -177940, 210876, -12005, 0, 60, 1},
{22520, -178935, 210903, -12018, 0, 60, 1},
{22522, -179331, 211365, -12013, 0, 60, 1},
{22522, -177637, 211579, -12015, 0, 60, 1},
{22526, -177837, 212356, -12037, 0, 60, 1},
{22526, -179030, 212261, -12018, 0, 60, 1},
{22532, -178367, 212328, -12031, 0, 60, 1}
};
private static final int[][] ROOMS_TUMORS =
{
{18780, -180911, 211652, -12029, 49151, 240, 1},
{18780, -180911, 206551, -12029, 16384, 240, 1},
{18780, -178417, 206558, -12032, 16384, 240, 1},
{18780, -178418, 211653, -12029, 49151, 240, 1},
{18708, -183290, 210004, -11948, 61439, 0, 1},
{18708, -183288, 208205, -11948, 4096, 0, 1},
{18708, -176039, 208203, -11948, 28672, 0, 1},
{18708, -176036, 210002, -11948, 36863, 0, 1},
{18668, -179664, 209443, -12476, 16384, 120, 1},
{18668, -179093, 209738, -12480, 40279, 120, 1},
{18668, -178248, 209688, -12479, 24320, 120, 1},
{18668, -177998, 209100, -12480, 16304, 120, 1},
{18668, -178246, 208493, -12480, 8968, 120, 1},
{18668, -178808, 208339, -12480, -1540, 120, 1},
{18668, -179663, 208738, -12480, 0, 120, 1},
{18668, -180498, 208330, -12467, 3208, 120, 1},
{18668, -181070, 208502, -12467, -7552, 120, 1},
{18668, -181310, 209097, -12467, -16408, 120, 1},
{18668, -181069, 209698, -12467, -24792, 120, 1},
{18668, -180228, 209744, -12467, 25920, 120, 1}
};
private static int[][] COHEMENES_SPAWN =
{
{25634, -178472, 211823, -12025, 0, 0, -1},
{25634, -180926, 211887, -12029, 0, 0, -1},
{25634, -180906, 206635, -12032, 0, 0, -1},
{25634, -178492, 206426, -12023, 0, 0, -1}
};
//@formatter:on
public HallOfErosionAttack()
{
super(HallOfErosionAttack.class.getSimpleName(), "gracia/instances");
addStartNpc(MOUTHOFEKIMUS);
addTalkId(MOUTHOFEKIMUS);
addStartNpc(TUMOR_DEAD);
addTalkId(TUMOR_DEAD);
addSpawnId(COHEMENES);
addSpawnId(NOTMOVE);
addAggroRangeEnterId(18668);
addAttackId(COHEMENES);
addKillId(TUMOR_ALIVE);
addKillId(COHEMENES);
addKillId(18711);
tumorRespawnTime = 180 * 1000;
}
private void teleportPlayer(L2PcInstance player, int[] coords, int instanceId)
{
player.setInstanceId(instanceId);
player.teleToLocation(coords[0], coords[1], coords[2]);
}
private boolean checkConditions(L2PcInstance player)
{
if (player.isGM())
{
return true;
}
final L2Party party = player.getParty();
if (party == null)
{
player.sendPacket(SystemMessageId.YOU_ARE_NOT_CURRENTLY_IN_A_PARTY_SO_YOU_CANNOT_ENTER);
return false;
}
if (party.getLeader() != player)
{
player.sendPacket(SystemMessageId.ONLY_A_PARTY_LEADER_CAN_MAKE_THE_REQUEST_TO_ENTER);
return false;
}
final L2CommandChannel channel = party.getCommandChannel();
if (channel == null)
{
player.sendPacket(SystemMessageId.YOU_CANNOT_ENTER_BECAUSE_YOU_ARE_NOT_ASSOCIATED_WITH_THE_CURRENT_COMMAND_CHANNEL);
return false;
}
if (channel.getLeader() != player)
{
player.sendPacket(SystemMessageId.ONLY_A_PARTY_LEADER_CAN_MAKE_THE_REQUEST_TO_ENTER);
return false;
}
if ((party.getCommandChannel().getMembers().size() < Config.EROSION_ATTACK_MIN_PLAYERS) || (party.getCommandChannel().getMembers().size() > Config.EROSION_ATTACK_MAX_PLAYERS))// 18 27
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_LEVEL_DOES_NOT_CORRESPOND_TO_THE_REQUIREMENTS_FOR_ENTRY);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
for (L2PcInstance partyMember : party.getCommandChannel().getMembers())
{
if ((partyMember.getLevel() < 75) || (partyMember.getLevel() > 85))
{
final SystemMessage sm = SystemMessage.getSystemMessage(2097);
sm.addPcName(partyMember);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
if (!Util.checkIfInRange(1000, player, partyMember, true))
{
final SystemMessage sm = SystemMessage.getSystemMessage(2096);
sm.addPcName(partyMember);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
final Long reentertime = InstanceManager.getInstance().getInstanceTime(partyMember.getObjectId(), INSTANCEID);
if (System.currentTimeMillis() < reentertime)
{
final SystemMessage sm = SystemMessage.getSystemMessage(2100);
sm.addPcName(partyMember);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
final QuestState qs = partyMember.getQuestState(Q00696_ConquerTheHallOfErosion.class.getSimpleName());
if ((qs == null) || !qs.isCond(1))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_QUEST_REQUIREMENT_IS_NOT_SUFFICIENT_AND_CANNOT_BE_ENTERED);
sm.addPcName(partyMember);
player.getParty().getCommandChannel().broadcastPacket(sm);
return false;
}
}
return true;
}
protected void enterInstance(L2PcInstance player, String template, int[] coords)
{
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (world != null)
{
if (!(world instanceof HEAWorld))
{
player.sendPacket(SystemMessageId.YOU_HAVE_ENTERED_ANOTHER_INSTANCE_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON);
return;
}
teleportPlayer(player, coords, world.getInstanceId());
return;
}
if (checkConditions(player))
{
world = new HEAWorld();
world.setInstanceId(InstanceManager.getInstance().createDynamicInstance(template));
world.setTemplateId(INSTANCEID);
world.setStatus(0);
((HEAWorld) world).startTime = System.currentTimeMillis();
InstanceManager.getInstance().addWorld(world);
_log.info("Hall Of Erosion Attack started " + template + " Instance: " + world.getInstanceId() + " created by player: " + player.getName());
if (player.isInParty())
{
for (L2PcInstance partyMember : player.getParty().isInCommandChannel() ? player.getParty().getCommandChannel().getMembers() : player.getParty().getMembers())
{
teleportPlayer(partyMember, coords, world.getInstanceId());
world.addAllowed(partyMember.getObjectId());
}
}
else
{
teleportPlayer(player, coords, world.getInstanceId());
world.addAllowed(player.getObjectId());
}
runTumors((HEAWorld) world);
}
}
protected void runTumors(HEAWorld world)
{
for (int[] spawn : ROOMS_MOBS)
{
for (int i = 0; i < spawn[6]; i++)
{
final L2Npc npc = addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
npc.getSpawn().setRespawnDelay(spawn[5]);
npc.getSpawn().setAmount(1);
if (spawn[5] > 0)
{
npc.getSpawn().startRespawn();
}
else
{
npc.getSpawn().stopRespawn();
}
}
}
for (int[] spawn : ROOMS_TUMORS)
{
for (int i = 0; i < spawn[6]; i++)
{
final L2Npc npc = addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
npc.getSpawn().setRespawnDelay(spawn[5]);
npc.getSpawn().setAmount(1);
if (spawn[5] > 0)
{
npc.getSpawn().startRespawn();
}
else
{
npc.getSpawn().stopRespawn();
}
world.npcList.add(npc);
}
}
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.YOU_CAN_HEAR_THE_UNDEAD_OF_EKIMUS_RUSHING_TOWARD_YOU_S1_S2_IT_HAS_NOW_BEGUN, 2, 8000));
}
protected void stopTumors(HEAWorld world)
{
if (!world.npcList.isEmpty())
{
for (L2Npc npc : world.npcList)
{
if (npc != null)
{
npc.deleteMe();
}
}
}
world.npcList.clear();
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getPlayerWorld(player);
if (tmpworld instanceof HEAWorld)
{
final HEAWorld world = (HEAWorld) tmpworld;
if (event.startsWith("warp"))
{
L2Npc victim = null;
victim = world.deadTumor;
if (victim != null)
{
world.deadTumors.add(victim);
}
player.destroyItemByItemId("SOI", 13797, 1, player, true);
final Location loc = world.deadTumors.get(Rnd.get(world.deadTumors.size())).getLocation();
if (loc != null)
{
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.S1_S_PARTY_HAS_MOVED_TO_A_DIFFERENT_LOCATION_THROUGH_THE_CRACK_IN_THE_TUMOR, 2, 8000));
for (L2PcInstance partyMember : player.getParty().getMembers())
{
if (partyMember.isInsideRadius(player, 500, true, false))
{
partyMember.teleToLocation(loc, true);
}
}
}
}
}
return "";
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
if (npc.getId() == MOUTHOFEKIMUS)
{
enterInstance(player, "HallOfErosionAttack.xml", ENTER_TELEPORT);
return "";
}
return "";
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HEAWorld)
{
final HEAWorld world = (HEAWorld) tmpworld;
if (npc.getId() == 18668)
{
for (int i = 0; i < Rnd.get(1, 4); i++)
{
addSpawn(mobs[Rnd.get(mobs.length)], npc.getLocation(), world.getInstanceId());
}
npc.doDie(npc);
}
}
return super.onAggroRangeEnter(npc, player, isSummon);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HEAWorld)
{
final HEAWorld world = (HEAWorld) tmpworld;
if (!world.isBossAttacked)
{
world.isBossAttacked = true;
final Calendar reenter = Calendar.getInstance();
reenter.add(Calendar.HOUR, INSTANCEPENALTY);
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.INSTANT_ZONE_S1_S_ENTRY_HAS_BEEN_RESTRICTED_YOU_CAN_CHECK_THE_NEXT_POSSIBLE_ENTRY_TIME_BY_USING_THE_COMMAND_INSTANCEZONE);
sm.addInstanceName(tmpworld.getTemplateId());
for (int objectId : tmpworld.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objectId);
if ((player != null) && player.isOnline())
{
InstanceManager.getInstance().setInstanceTime(objectId, tmpworld.getTemplateId(), reenter.getTimeInMillis());
player.sendPacket(sm);
}
}
}
}
return super.onAttack(npc, attacker, damage, isSummon, skill);
}
@Override
public final String onSpawn(L2Npc npc)
{
if (Util.contains(NOTMOVE, npc.getId()))
{
npc.setIsNoRndWalk(true);
npc.setIsImmobilized(true);
}
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HEAWorld)
{
final HEAWorld world = (HEAWorld) tmpworld;
if (npc.getId() == TUMOR_ALIVE)
{
world.addTumorCount(1);
if ((world.tumorCount == 4) && (world.cohemenes != null))
{
world.cohemenes.deleteMe();
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.YOU_HAVE_FAILED_AT_S1_S2_THE_INSTANCE_WILL_SHORTLY_EXPIRE, 2, 8000));
finishInstance(world);
conquestEnded = true;
stopTumors(world);
}
}
if (npc.getId() == TUMOR_DEAD)
{
world.addTag(1);
}
}
return super.onSpawn(npc);
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HEAWorld)
{
final HEAWorld world = (HEAWorld) tmpworld;
final Location loc = npc.getLocation();
if (npc.getId() == TUMOR_ALIVE)
{
world.addTumorCount(-1);
npc.dropItem(player, 13797, Rnd.get(2, 5));
npc.deleteMe();
world.deadTumor = addSpawn(TUMOR_DEAD, loc, world.getInstanceId());
world.deadTumors.add(world.deadTumor);
ThreadPoolManager.getInstance().scheduleGeneral(new TumorRevival(world.deadTumor, world), tumorRespawnTime);
ThreadPoolManager.getInstance().scheduleGeneral(new RegenerationCoffinSpawn(world.deadTumor, world), 20000);
if (world.tumorCount >= 1)
{
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.THE_TUMOR_INSIDE_S1_HAS_BEEN_DESTROYED_NIN_ORDER_TO_DRAW_OUT_THE_COWARDLY_COHEMENES_YOU_MUST_DESTROY_ALL_THE_TUMORS, 2, 8000));
}
if ((world.tumorCount == 0) && (world.cohemenes == null))
{
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.ALL_THE_TUMORS_INSIDE_S1_HAVE_BEEN_DESTROYED_DRIVEN_INTO_A_CORNER_COHEMENES_APPEARS_CLOSE_BY, 2, 8000));
final int[] spawn = COHEMENES_SPAWN[Rnd.get(0, COHEMENES_SPAWN.length - 1)];
final L2Npc n = addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
n.broadcastPacket(new NpcSay(n.getObjectId(), ChatType.SHOUT, n.getId(), NpcStringId.C_MON_C_MON_SHOW_YOUR_FACE_YOU_LITTLE_RATS_LET_ME_SEE_WHAT_THE_DOOMED_WEAKLINGS_ARE_SCHEMING));
world.cohemenes = n;
}
}
if (npc.getId() == COHEMENES)
{
npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.SHOUT, npc.getId(), NpcStringId.KEU_I_WILL_LEAVE_FOR_NOW_BUT_DON_T_THINK_THIS_IS_OVER_THE_SEED_OF_INFINITY_CAN_NEVER_DIE));
for (int objId : world.getAllowed())
{
final L2PcInstance pl = L2World.getInstance().getPlayer(objId);
if (pl != null)
{
final QuestState st = pl.getQuestState(Q00696_ConquerTheHallOfErosion.class.getSimpleName());
if ((st != null) && (st.getInt("cond") == 1))
{
st.set("cohemenes", "1");
}
}
}
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.CONGRATULATIONS_YOU_HAVE_SUCCEEDED_AT_S1_S2_THE_INSTANCE_WILL_SHORTLY_EXPIRE, 2, 8000));
world.cohemenes = null;
conquestEnded = true;
finishInstance(world);
stopTumors(world);
SoIManager.notifyCohemenesKill();
}
if (npc.getId() == 18711)
{
tumorRespawnTime += 10 * 1000;
}
}
return "";
}
private static final void finishInstance(InstanceWorld world)
{
if (world instanceof HEAWorld)
{
final Calendar reenter = Calendar.getInstance();
reenter.set(Calendar.MINUTE, 30);
if (reenter.get(Calendar.HOUR_OF_DAY) >= 6)
{
reenter.add(Calendar.DATE, 1);
}
reenter.set(Calendar.HOUR_OF_DAY, 6);
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.INSTANT_ZONE_S1_S_ENTRY_HAS_BEEN_RESTRICTED_YOU_CAN_CHECK_THE_NEXT_POSSIBLE_ENTRY_TIME_BY_USING_THE_COMMAND_INSTANCEZONE);
sm.addInstanceName(world.getTemplateId());
for (int objectId : world.getAllowed())
{
final L2PcInstance obj = L2World.getInstance().getPlayer(objectId);
if ((obj != null) && obj.isOnline())
{
InstanceManager.getInstance().setInstanceTime(objectId, world.getTemplateId(), reenter.getTimeInMillis());
obj.sendPacket(sm);
}
}
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
inst.setDuration(5 * 60000);
inst.setEmptyDestroyTime(0);
}
}
private class TumorRevival implements Runnable
{
private final L2Npc _deadTumor;
private final HEAWorld _world;
public TumorRevival(L2Npc deadTumor, HEAWorld world)
{
_deadTumor = world.deadTumor;
_world = world;
}
@Override
public void run()
{
if (conquestEnded)
{
return;
}
final L2Npc tumor = addSpawn(TUMOR_ALIVE, _deadTumor.getLocation(), _world.getInstanceId());
_world.npcList.add(tumor);
_deadTumor.deleteMe();
_world.addTag(-1);
}
}
private class RegenerationCoffinSpawn implements Runnable
{
private final L2Npc _deadTumor;
private final HEAWorld _world;
public RegenerationCoffinSpawn(L2Npc deadTumor, HEAWorld world)
{
_deadTumor = world.deadTumor;
_world = world;
}
@Override
public void run()
{
if (conquestEnded)
{
return;
}
for (int i = 0; i < 4; i++)
{
final L2Npc worm = addSpawn(18710, _deadTumor.getLocation(), _world.getInstanceId());
_world.npcList.add(worm);
}
}
}
protected void broadCastPacket(HEAWorld world, L2GameServerPacket packet)
{
for (int objId : world.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objId);
if ((player != null) && player.isOnline() && (player.getInstanceId() == world.getInstanceId()))
{
player.sendPacket(packet);
}
}
}
}

View File

@@ -0,0 +1,698 @@
/*
* 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 gracia.instances.HallOfErosionDefence;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.L2CommandChannel;
import com.l2jmobius.gameserver.model.L2Party;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Attackable;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2QuestGuardInstance;
import com.l2jmobius.gameserver.model.entity.Instance;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import com.l2jmobius.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.util.Util;
import com.l2jmobius.util.Rnd;
import ai.npc.AbstractNpcAI;
import quests.Q00697_DefendTheHallOfErosion.Q00697_DefendTheHallOfErosion;
public class HallOfErosionDefence extends AbstractNpcAI
{
protected class HEDWorld extends InstanceWorld
{
public List<L2Attackable> npcList = new ArrayList<>();
public List<L2Npc> alivetumor = new ArrayList<>();
public List<L2Npc> deadTumors = new ArrayList<>();
protected L2Npc deadTumor;
public long startTime = 0;
public ScheduledFuture<?> finishTask = null;
public synchronized void addTag(int value)
{
tag += value;
}
public HEDWorld()
{
tag = -1;
}
}
private static final int INSTANCEID = 120;
private static final int MOUTHOFEKIMUS = 32537;
private static final int TUMOR_ALIVE = 18708;
private static final int TUMOR_DEAD = 32535;
private static final int SEED = 32541;
public int tumorKillCount = 0;
protected boolean conquestEnded = false;
private boolean soulwagonSpawned = false;
private static int seedKills = 0;
private long tumorRespawnTime;
private static final int[] ENTER_TELEPORT =
{
-179659,
211061,
-12784
};
private static int[] NOTMOVE =
{
18667,
18668,
18708,
18709,
18711,
TUMOR_DEAD
};
private static final int[] mobs =
{
22516,
22520,
22522,
22524,
22526,
22532
};
//@formatter:off
private static final int[][] SEEDS_SPAWN =
{
{SEED, -178418, 211653, -12029, 49151, 0, 1},
{SEED, -178417, 206558, -12029, 16384, 0, 1},
{SEED, -180911, 206551, -12029, 16384, 0, 1},
{SEED, -180911, 211652, -12029, 49151, 0, 1}
};
private static final int[][] TUMOR_DEAD_SPAWN =
{
{TUMOR_DEAD, -176036, 210002, -11948, 36863, 0, 1},
{TUMOR_DEAD, -176039, 208203, -11948, 28672, 0, 1},
{TUMOR_DEAD, -183288, 208205, -11948, 4096, 0, 1},
{TUMOR_DEAD, -183290, 210004, -11948, 61439, 0, 1}
};
protected static final int[][] TUMOR_ALIVE_SPAWN =
{
{TUMOR_ALIVE, -176036, 210002, -11948, 36863, 0, 1},
{TUMOR_ALIVE, -176039, 208203, -11948, 28672, 0, 1},
{TUMOR_ALIVE, -183288, 208205, -11948, 4096, 0, 1},
{TUMOR_ALIVE, -183290, 210004, -11948, 61439, 0, 1}
};
private static final int[][] ROOMS_MOBS =
{
{22516, -180364, 211944, -12019, 0, 60, 1},
{22516, -181616, 211413, -12015, 0, 60, 1},
{22520, -181404, 211042, -12023, 0, 60, 1},
{22522, -181558, 212227, -12035, 0, 60, 1},
{22522, -180459, 212322, -12018, 0, 60, 1},
{22524, -180428, 211180, -12014, 0, 60, 1},
{22524, -180718, 212162, -12028, 0, 60, 1},
{22532, -183114, 209397, -11923, 0, 60, 1},
{22532, -182917, 210495, -11925, 0, 60, 1},
{22516, -183918, 210225, -11934, 0, 60, 1},
{22532, -183862, 209909, -11932, 0, 60, 1},
{22532, -183246, 210631, -11923, 0, 60, 1},
{22522, -182971, 210522, -11924, 0, 60, 1},
{22522, -183485, 209406, -11921, 0, 60, 1},
{22516, -183032, 208822, -11923, 0, 60, 1},
{22516, -182709, 207817, -11929, 0, 60, 1},
{22520, -182964, 207746, -11924, 0, 60, 1},
{22520, -183385, 208847, -11922, 0, 60, 1},
{22526, -183684, 208847, -11926, 0, 60, 1},
{22526, -183530, 208725, -11926, 0, 60, 1},
{22532, -183968, 207603, -11928, 0, 60, 1},
{22532, -183608, 208567, -11926, 0, 60, 1},
{22526, -181471, 207159, -12020, 0, 60, 1},
{22526, -180213, 207042, -12013, 0, 60, 1},
{22532, -180213, 206506, -12010, 0, 60, 1},
{22532, -181720, 206643, -12016, 0, 60, 1},
{22516, -181743, 206643, -12018, 0, 60, 1},
{22516, -181028, 205739, -12030, 0, 60, 1},
{22520, -181431, 205980, -12040, 0, 60, 1},
{22524, -178964, 207168, -12014, 0, 60, 1},
{22524, -177658, 207037, -12019, 0, 60, 1},
{22522, -177730, 206558, -12016, 0, 60, 1},
{22522, -179132, 206650, -12011, 0, 60, 1},
{22526, -179132, 206155, -12017, 0, 60, 1},
{22526, -178277, 205754, -12031, 0, 60, 1},
{22516, -178716, 205802, -12020, 0, 60, 1},
{22532, -176565, 207839, -11929, 0, 60, 1},
{22532, -176281, 208822, -11923, 0, 60, 1},
{22520, -175791, 208804, -11923, 0, 60, 1},
{22520, -176259, 207689, -11923, 0, 60, 1},
{22526, -175849, 207508, -11929, 0, 60, 1},
{22526, -175453, 208250, -11930, 0, 60, 1},
{22524, -175738, 207914, -11946, 0, 60, 1},
{22526, -176339, 209425, -11923, 0, 60, 1},
{22526, -176586, 210424, -11928, 0, 60, 1},
{22516, -176586, 210546, -11923, 0, 60, 1},
{22516, -175847, 209365, -11922, 0, 60, 1},
{22520, -175496, 209498, -11924, 0, 60, 1},
{22520, -175538, 210252, -11940, 0, 60, 1},
{22524, -175527, 209744, -11928, 0, 60, 1},
{22520, -177940, 210876, -12005, 0, 60, 1},
{22520, -178935, 210903, -12018, 0, 60, 1},
{22522, -179331, 211365, -12013, 0, 60, 1},
{22522, -177637, 211579, -12015, 0, 60, 1},
{22526, -177837, 212356, -12037, 0, 60, 1},
{22526, -179030, 212261, -12018, 0, 60, 1},
{22532, -178367, 212328, -12031, 0, 60, 1},
{18667, -179664, 209443, -12476, 16384, 120, 1},
{18711, -179093, 209738, -12480, 40279, 120, 1},
{18667, -178248, 209688, -12479, 24320, 120, 1},
{18668, -177998, 209100, -12480, 16304, 120, 1},
{18711, -178246, 208493, -12480, 8968, 120, 1},
{18668, -178808, 208339, -12480, -1540, 120, 1},
{18711, -179663, 208738, -12480, 0, 120, 1},
{18711, -180498, 208330, -12467, 3208, 120, 1},
{18667, -181070, 208502, -12467, -7552, 120, 1},
{18668, -181310, 209097, -12467, -16408, 120, 1},
{18711, -181069, 209698, -12467, -24792, 120, 1},
{18668, -180228, 209744, -12467, 25920, 120, 1}
};
//@formatter:on
public HallOfErosionDefence()
{
super(HallOfErosionDefence.class.getSimpleName(), "gracia/instances");
addStartNpc(MOUTHOFEKIMUS);
addTalkId(MOUTHOFEKIMUS);
addStartNpc(TUMOR_DEAD);
addTalkId(TUMOR_DEAD);
addSpawnId(NOTMOVE);
addSpawnId(SEED);
addAggroRangeEnterId(18668);
addKillId(TUMOR_ALIVE);
addKillId(SEED);
addKillId(18711);
tumorRespawnTime = 180 * 1000;
}
private void teleportPlayer(L2PcInstance player, int[] coords, int instanceId)
{
player.setInstanceId(instanceId);
player.teleToLocation(coords[0], coords[1], coords[2]);
}
private boolean checkConditions(L2PcInstance player)
{
if (player.isGM())
{
return true;
}
final L2Party party = player.getParty();
if (party == null)
{
player.sendPacket(SystemMessageId.YOU_ARE_NOT_CURRENTLY_IN_A_PARTY_SO_YOU_CANNOT_ENTER);
return false;
}
if (party.getLeader() != player)
{
player.sendPacket(SystemMessageId.ONLY_A_PARTY_LEADER_CAN_MAKE_THE_REQUEST_TO_ENTER);
return false;
}
final L2CommandChannel channel = party.getCommandChannel();
if (channel == null)
{
player.sendPacket(SystemMessageId.YOU_CANNOT_ENTER_BECAUSE_YOU_ARE_NOT_ASSOCIATED_WITH_THE_CURRENT_COMMAND_CHANNEL);
return false;
}
if (channel.getLeader() != player)
{
player.sendPacket(SystemMessageId.ONLY_A_PARTY_LEADER_CAN_MAKE_THE_REQUEST_TO_ENTER);
return false;
}
if ((party.getCommandChannel().getMembers().size() < Config.EROSION_DEFENCE_MIN_PLAYERS) || (party.getCommandChannel().getMembers().size() > Config.EROSION_DEFENCE_MAX_PLAYERS))// 18 27
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_LEVEL_DOES_NOT_CORRESPOND_TO_THE_REQUIREMENTS_FOR_ENTRY);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
for (L2PcInstance partyMember : party.getCommandChannel().getMembers())
{
if ((partyMember.getLevel() < 75) || (partyMember.getLevel() > 85))
{
final SystemMessage sm = SystemMessage.getSystemMessage(2097);
sm.addPcName(partyMember);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
if (!Util.checkIfInRange(1000, player, partyMember, true))
{
final SystemMessage sm = SystemMessage.getSystemMessage(2096);
sm.addPcName(partyMember);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
final Long reentertime = InstanceManager.getInstance().getInstanceTime(partyMember.getObjectId(), INSTANCEID);
if (System.currentTimeMillis() < reentertime)
{
final SystemMessage sm = SystemMessage.getSystemMessage(2100);
sm.addPcName(partyMember);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
final QuestState qs = partyMember.getQuestState(Q00697_DefendTheHallOfErosion.class.getSimpleName());
if ((qs == null) || !qs.isCond(1))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_QUEST_REQUIREMENT_IS_NOT_SUFFICIENT_AND_CANNOT_BE_ENTERED);
sm.addPcName(partyMember);
player.getParty().getCommandChannel().broadcastPacket(sm);
return false;
}
}
return true;
}
protected void enterInstance(L2PcInstance player, String template, int[] coords)
{
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (world != null)
{
if (!(world instanceof HEDWorld))
{
player.sendPacket(SystemMessageId.YOU_HAVE_ENTERED_ANOTHER_INSTANCE_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON);
return;
}
teleportPlayer(player, coords, world.getInstanceId());
return;
}
if (checkConditions(player))
{
world = new HEDWorld();
world.setInstanceId(InstanceManager.getInstance().createDynamicInstance(template));
world.setTemplateId(INSTANCEID);
world.setStatus(0);
((HEDWorld) world).startTime = System.currentTimeMillis();
InstanceManager.getInstance().addWorld(world);
_log.info("Hall Of Erosion Defence started " + template + " Instance: " + world.getInstanceId() + " created by player: " + player.getName());
if (player.isInParty())
{
for (L2PcInstance partyMember : player.getParty().isInCommandChannel() ? player.getParty().getCommandChannel().getMembers() : player.getParty().getMembers())
{
teleportPlayer(partyMember, coords, world.getInstanceId());
world.addAllowed(partyMember.getObjectId());
}
}
else
{
teleportPlayer(player, coords, world.getInstanceId());
world.addAllowed(player.getObjectId());
}
((HEDWorld) world).finishTask = ThreadPoolManager.getInstance().scheduleGeneral(new FinishTask((HEDWorld) world), 20 * 60000);
runTumors((HEDWorld) world);
}
}
protected void runTumors(HEDWorld world)
{
for (int[] spawn : ROOMS_MOBS)
{
for (int i = 0; i < spawn[6]; i++)
{
world.npcList = new ArrayList<>();
final L2Attackable npc = (L2Attackable) addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
npc.getSpawn().setRespawnDelay(spawn[5]);
npc.getSpawn().setAmount(1);
if (spawn[5] > 0)
{
npc.getSpawn().startRespawn();
}
else
{
npc.getSpawn().stopRespawn();
}
world.npcList.add(npc);
}
}
for (int[] spawn : TUMOR_DEAD_SPAWN)
{
for (int i = 0; i < spawn[6]; i++)
{
final L2Npc npc = addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
world.deadTumors.add(npc);
ThreadPoolManager.getInstance().scheduleGeneral(new RegenerationCoffinSpawn(npc, world), 1000);
}
}
for (int[] spawn : SEEDS_SPAWN)
{
for (int i = 0; i < spawn[6]; i++)
{
addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
}
}
ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
if (!conquestEnded)
{
stopDeadTumors(world);
for (int[] spawn : TUMOR_ALIVE_SPAWN)
{
for (int i = 0; i < spawn[6]; i++)
{
final L2Npc npc = addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
world.alivetumor.add(npc);
}
}
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.THE_TUMOR_INSIDE_S1_HAS_COMPLETELY_REVIVED_NRECOVERED_NEARBY_UNDEAD_ARE_SWARMING_TOWARD_SEED_OF_LIFE, 2, 8000));
}
}, 180 * 1000);
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.YOU_CAN_HEAR_THE_UNDEAD_OF_EKIMUS_RUSHING_TOWARD_YOU_S1_S2_IT_HAS_NOW_BEGUN, 2, 8000));
}
protected void stopDeadTumors(HEDWorld world)
{
if (!world.deadTumors.isEmpty())
{
for (L2Npc npc : world.deadTumors)
{
if (npc != null)
{
npc.deleteMe();
}
}
}
world.deadTumors.clear();
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getPlayerWorld(player);
if (tmpworld instanceof HEDWorld)
{
final HEDWorld world = (HEDWorld) tmpworld;
if (event.startsWith("warp"))
{
L2Npc victim = null;
victim = world.deadTumor;
if (victim != null)
{
world.deadTumors.add(victim);
}
player.destroyItemByItemId("SOI", 13797, 1, player, true);
final Location loc = world.deadTumors.get(Rnd.get(world.deadTumors.size())).getLocation();
if (loc != null)
{
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.S1_S_PARTY_HAS_MOVED_TO_A_DIFFERENT_LOCATION_THROUGH_THE_CRACK_IN_THE_TUMOR, 2, 8000));
for (L2PcInstance partyMember : player.getParty().getMembers())
{
if (partyMember.isInsideRadius(player, 500, true, false))
{
partyMember.teleToLocation(loc, true);
}
}
}
}
}
return "";
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
if (npc.getId() == MOUTHOFEKIMUS)
{
enterInstance(player, "HallOfErosionDefence.xml", ENTER_TELEPORT);
return "";
}
return "";
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HEDWorld)
{
final HEDWorld world = (HEDWorld) tmpworld;
if (npc.getId() == 18668)
{
for (int i = 0; i < Rnd.get(1, 4); i++)
{
addSpawn(mobs[Rnd.get(mobs.length)], npc.getLocation(), world.getInstanceId());
}
npc.deleteMe();
}
}
return super.onAggroRangeEnter(npc, player, isSummon);
}
@Override
public final String onSpawn(L2Npc npc)
{
if (Util.contains(NOTMOVE, npc.getId()))
{
npc.setIsNoRndWalk(true);
npc.setIsImmobilized(true);
}
if (npc.getId() == SEED)
{
((L2QuestGuardInstance) npc).setPassive(true);
}
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HEDWorld)
{
final HEDWorld world = (HEDWorld) tmpworld;
if (npc.getId() == TUMOR_DEAD)
{
world.addTag(1);
}
}
return super.onSpawn(npc);
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HEDWorld)
{
final HEDWorld world = (HEDWorld) tmpworld;
if (npc.getId() == TUMOR_ALIVE)
{
npc.dropItem(player, 13797, Rnd.get(2, 5));
npc.deleteMe();
notifyTumorDeath(npc, world);
world.deadTumor = addSpawn(TUMOR_DEAD, npc.getLocation(), world.getInstanceId());
world.deadTumors.add(world.deadTumor);
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.THE_TUMOR_INSIDE_S1_HAS_BEEN_DESTROYED_NTHE_NEARBY_UNDEAD_THAT_WERE_ATTACKING_SEED_OF_LIFE_START_LOSING_THEIR_ENERGY_AND_RUN_AWAY, 2, 8000));
ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
world.deadTumor.deleteMe();
final L2Npc tumor = addSpawn(TUMOR_ALIVE, world.deadTumor.getLocation(), world.getInstanceId());
world.alivetumor.add(tumor);
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.THE_TUMOR_INSIDE_S1_HAS_COMPLETELY_REVIVED_NRECOVERED_NEARBY_UNDEAD_ARE_SWARMING_TOWARD_SEED_OF_LIFE, 2, 8000));
}, tumorRespawnTime);
}
if (npc.getId() == 18711)
{
tumorRespawnTime += 5 * 1000;
}
}
return super.onKill(npc, player, isSummon);
}
public String onKillByMob(L2Npc npc, L2Npc killer)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HEDWorld)
{
final HEDWorld world = (HEDWorld) tmpworld;
seedKills++;
if (seedKills >= 1)
{
conquestConclusion(world);
}
}
return null;
}
private void notifyTumorDeath(L2Npc npc, HEDWorld world)
{
tumorKillCount++;
if ((tumorKillCount == 4) && !soulwagonSpawned)
{
soulwagonSpawned = true;
final L2Npc soul = addSpawn(25636, npc.getLocation(), world.getInstanceId());
final NpcSay cs = new NpcSay(soul.getObjectId(), ChatType.SHOUT, soul.getId(), NpcStringId.HA_HA_HA);
soul.broadcastPacket(cs);
}
}
private class RegenerationCoffinSpawn implements Runnable
{
private final L2Npc _npc;
private final HEDWorld _world;
public RegenerationCoffinSpawn(L2Npc npc, HEDWorld world)
{
_npc = npc;
_world = world;
}
@Override
public void run()
{
if (conquestEnded)
{
return;
}
for (int i = 0; i < 4; i++)
{
final L2Npc worm = addSpawn(18709, _npc.getLocation(), _world.getInstanceId());
_world.deadTumors.add(worm);
}
}
}
class FinishTask implements Runnable
{
private final HEDWorld _world;
FinishTask(HEDWorld world)
{
_world = world;
}
@Override
public void run()
{
if (_world != null)
{
conquestEnded = true;
final Instance inst = InstanceManager.getInstance().getInstance(_world.getInstanceId());
if (inst != null)
{
for (int objId : _world.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objId);
final QuestState st = player.getQuestState(Q00697_DefendTheHallOfErosion.class.getSimpleName());
if ((st != null) && (st.getInt("cond") == 1))
{
st.set("defenceDone", 1);
}
}
broadCastPacket(_world, new ExShowScreenMessage(NpcStringId.CONGRATULATIONS_YOU_HAVE_SUCCEEDED_AT_S1_S2_THE_INSTANCE_WILL_SHORTLY_EXPIRE, 2, 8000));
inst.removeNpcs();
if (inst.getPlayers().isEmpty())
{
inst.setDuration(5 * 60000);
}
else
{
inst.setDuration(5 * 60000);
inst.setEmptyDestroyTime(5 * 60000);
}
}
}
}
}
private void conquestConclusion(HEDWorld world)
{
if (world.finishTask != null)
{
world.finishTask.cancel(false);
world.finishTask = null;
}
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.YOU_HAVE_FAILED_AT_S1_S2_THE_INSTANCE_WILL_SHORTLY_EXPIRE, 2, 8000));
conquestEnded = true;
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
if (inst != null)
{
inst.removeNpcs();
if (inst.getPlayers().isEmpty())
{
inst.setDuration(5 * 60000);
}
else
{
inst.setDuration(5 * 60000);
inst.setEmptyDestroyTime(5 * 60000);
}
}
}
protected void broadCastPacket(HEDWorld world, L2GameServerPacket packet)
{
for (int objId : world.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objId);
if ((player != null) && player.isOnline() && (player.getInstanceId() == world.getInstanceId()))
{
player.sendPacket(packet);
}
}
}
}

View File

@@ -0,0 +1,596 @@
/*
* 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 gracia.instances.HallOfSufferingAttack;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import com.l2jmobius.gameserver.ai.CtrlEvent;
import com.l2jmobius.gameserver.datatables.SkillData;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2Party;
import com.l2jmobius.gameserver.model.L2World;
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.effects.L2EffectType;
import com.l2jmobius.gameserver.model.entity.Instance;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.util.Util;
import ai.npc.AbstractNpcAI;
import quests.Q00694_BreakThroughTheHallOfSuffering.Q00694_BreakThroughTheHallOfSuffering;
public class HallOfSufferingAttack extends AbstractNpcAI
{
private class HSAWorld extends InstanceWorld
{
public Map<L2Npc, Boolean> npcList = new HashMap<>();
public L2Npc klodekus = null;
public L2Npc klanikus = null;
public boolean isBossesAttacked = false;
public long[] storeTime =
{
0,
0
}; // 0: instance start, 1: finish time
public HSAWorld()
{
tag = -1;
}
protected void calcRewardItemId()
{
final Long finishDiff = storeTime[1] - storeTime[0];
if (finishDiff < 1260000)
{
tag = 13777;
}
else if (finishDiff < 1380000)
{
tag = 13778;
}
else if (finishDiff < 1500000)
{
tag = 13779;
}
else if (finishDiff < 1620000)
{
tag = 13780;
}
else if (finishDiff < 1740000)
{
tag = 13781;
}
else if (finishDiff < 1860000)
{
tag = 13782;
}
else if (finishDiff < 1980000)
{
tag = 13783;
}
else if (finishDiff < 2100000)
{
tag = 13784;
}
else if (finishDiff < 2220000)
{
tag = 13785;
}
else
{
tag = 13786;
}
}
}
private static final int INSTANCEID = 115;
private static final boolean debug = false;
// NPCs
private static final int MOUTHOFEKIMUS = 32537;
private static final int TEPIOS = 32530;
// mobs
private static final int KLODEKUS = 25665;
private static final int KLANIKUS = 25666;
private static final int TUMOR_ALIVE = 18704;
private static final int TUMOR_DEAD = 32531;
//@formatter:off
private static final int[] ENTER_TELEPORT = {-187567,205570,-9538};
private static final int[] TUMOR_MOBIDS = {22509,22510,22511,22512,22513,22514,22515};
private static final int[] TWIN_MOBIDS = {22509,22510,22511,22512,22513};
// Doors/Walls/Zones
private static final int[][] ROOM_1_MOBS =
{
{22509, -186296, 208200, -9544}, {22509, -186161, 208345, -9544}, {22509, -186296, 208403, -9544},
{22510, -186107, 208113, -9528}, {22510, -186350, 208200, -9544}
};
private static final int[][] ROOM_2_MOBS =
{
{22511, -184433, 210953, -9536}, {22511, -184406, 211301, -9536}, {22509, -184541, 211272, -9544},
{22510, -184244, 211098, -9536}, {22510, -184352, 211243, -9536}, {22510, -184298, 211330, -9528}
};
private static final int[][] ROOM_3_MOBS =
{
{22512, -182611, 213984, -9520}, {22512, -182908, 214071, -9520}, {22512, -182962, 213868, -9512},
{22509, -182881, 213955, -9512}, {22511, -182827, 213781, -9504}, {22511, -182530, 213984, -9528},
{22510, -182935, 213723, -9512}, {22510, -182557, 213868, -9520}
};
private static final int[][] ROOM_4_MOBS =
{
{22514, -180958, 216860, -9544}, {22514, -181012, 216628, -9536}, {22514, -181120, 216715, -9536},
{22513, -180661, 216599, -9536}, {22513, -181039, 216599, -9536}, {22511, -180715, 216599, -9536},
{22511, -181012, 216889, -9536}, {22512, -180931, 216918, -9536}, {22512, -180742, 216628, -9536}
};
private static final int[][] ROOM_5_MOBS =
{
{22512, -177372, 217854, -9536}, {22512, -177237, 218140, -9536}, {22512, -177021, 217647, -9528},
{22513, -177372, 217792, -9544}, {22513, -177372, 218053, -9536}, {22514, -177291, 217734, -9544},
{22514, -177264, 217792, -9544}, {22514, -177264, 218053, -9536}, {22515, -177156, 217792, -9536},
{22515, -177075, 217647, -9528}
};
private static final int[][] TUMOR_SPAWNS =
{
{-186327,208286,-9544},{-184429,211155,-9544},{-182811,213871,-9496},
{-181039,216633,-9528},{-177264,217760,-9544}
};
private static final int[][] TWIN_SPAWNS = {{25665,-173727,218169,-9536},{25666,-173727,218049,-9536}};
private static final int[] TEPIOS_SPAWN = {-173727,218109,-9536};
//@formatter:on
private static final int BOSS_INVUL_TIME = 30000;
private static final int BOSS_MINION_SPAWN_TIME = 60000;
private static final int BOSS_RESSURECT_TIME = 20000;
private static final int INSTANCEPENALTY = 24;
public HallOfSufferingAttack()
{
super(HallOfSufferingAttack.class.getSimpleName(), "gracia/instances");
addStartNpc(MOUTHOFEKIMUS);
addStartNpc(TEPIOS);
addTalkId(MOUTHOFEKIMUS);
addTalkId(TEPIOS);
addKillId(TUMOR_ALIVE);
addKillId(KLODEKUS);
addKillId(KLANIKUS);
addAttackId(KLODEKUS);
addAttackId(KLANIKUS);
addSkillSeeId(TUMOR_MOBIDS);
addKillId(TUMOR_MOBIDS);
}
private boolean checkConditions(L2PcInstance player)
{
if (debug || player.isGM())
{
return true;
}
final L2Party party = player.getParty();
if (party == null)
{
player.sendPacket(SystemMessageId.YOU_ARE_NOT_CURRENTLY_IN_A_PARTY_SO_YOU_CANNOT_ENTER);
return false;
}
if (party.getLeader() != player)
{
player.sendPacket(SystemMessageId.ONLY_A_PARTY_LEADER_CAN_MAKE_THE_REQUEST_TO_ENTER);
return false;
}
for (L2PcInstance partyMember : party.getMembers())
{
if ((partyMember.getLevel() < 75) || (partyMember.getLevel() > 82))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_LEVEL_DOES_NOT_CORRESPOND_TO_THE_REQUIREMENTS_FOR_ENTRY);
sm.addPcName(partyMember);
party.broadcastPacket(sm);
return false;
}
if (!Util.checkIfInRange(1000, player, partyMember, true))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_A_LOCATION_WHICH_CANNOT_BE_ENTERED_THEREFORE_IT_CANNOT_BE_PROCESSED);
sm.addPcName(partyMember);
party.broadcastPacket(sm);
return false;
}
final Long reentertime = InstanceManager.getInstance().getInstanceTime(partyMember.getObjectId(), INSTANCEID);
if (System.currentTimeMillis() < reentertime)
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_MAY_NOT_RE_ENTER_YET);
sm.addPcName(partyMember);
party.broadcastPacket(sm);
return false;
}
final QuestState qs = partyMember.getQuestState(Q00694_BreakThroughTheHallOfSuffering.class.getSimpleName());
if ((qs == null) || !qs.isCond(1))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_QUEST_REQUIREMENT_IS_NOT_SUFFICIENT_AND_CANNOT_BE_ENTERED);
sm.addPcName(partyMember);
party.broadcastPacket(sm);
return false;
}
}
return true;
}
private void teleportPlayer(L2PcInstance player, int[] coords, int instanceId)
{
player.setInstanceId(instanceId);
player.teleToLocation(coords[0], coords[1], coords[2]);
}
protected void enterInstance(L2PcInstance player, String template, int[] coords)
{
// check for existing instances for this player
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
// existing instance
if (world != null)
{
if (!(world instanceof HSAWorld))
{
player.sendPacket(SystemMessageId.YOU_HAVE_ENTERED_ANOTHER_INSTANCE_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON);
return;
}
teleportPlayer(player, coords, world.getInstanceId());
return;
}
if (checkConditions(player))
{
world = new HSAWorld();
world.setInstanceId(InstanceManager.getInstance().createDynamicInstance(template));
world.setTemplateId(INSTANCEID);
world.setStatus(0);
((HSAWorld) world).storeTime[0] = System.currentTimeMillis();
InstanceManager.getInstance().addWorld(world);
_log.info("Hall Of Suffering Attack started " + template + " Instance: " + world.getInstanceId() + " created by player: " + player.getName());
runTumors((HSAWorld) world);
if (player.getParty() == null)
{
teleportPlayer(player, coords, world.getInstanceId());
world.addAllowed(player.getObjectId());
}
else
{
for (L2PcInstance partyMember : player.getParty().getMembers())
{
teleportPlayer(partyMember, coords, world.getInstanceId());
world.addAllowed(partyMember.getObjectId());
}
}
}
}
protected boolean checkKillProgress(L2Npc mob, HSAWorld world)
{
if (world.npcList.containsKey(mob))
{
world.npcList.put(mob, true);
}
for (boolean isDead : world.npcList.values())
{
if (!isDead)
{
return false;
}
}
return true;
}
protected int[][] getRoomSpawns(int room)
{
switch (room)
{
case 0:
return ROOM_1_MOBS;
case 1:
return ROOM_2_MOBS;
case 2:
return ROOM_3_MOBS;
case 3:
return ROOM_4_MOBS;
case 4:
return ROOM_5_MOBS;
}
return new int[][] {};
}
protected void runTumors(HSAWorld world)
{
for (int[] mob : getRoomSpawns(world.getStatus()))
{
final L2Npc npc = addSpawn(mob[0], mob[1], mob[2], mob[3], 0, false, 0, false, world.getInstanceId());
world.npcList.put(npc, false);
}
final L2Npc mob = addSpawn(TUMOR_ALIVE, TUMOR_SPAWNS[world.getStatus()][0], TUMOR_SPAWNS[world.getStatus()][1], TUMOR_SPAWNS[world.getStatus()][2], 0, false, 0, false, world.getInstanceId());
mob.disableCoreAI(true);
mob.setIsImmobilized(true);
mob.setCurrentHp(mob.getMaxHp() * 0.5);
world.npcList.put(mob, false);
world.incStatus();
}
protected void runTwins(HSAWorld world)
{
world.incStatus();
world.klodekus = addSpawn(TWIN_SPAWNS[0][0], TWIN_SPAWNS[0][1], TWIN_SPAWNS[0][2], TWIN_SPAWNS[0][3], 0, false, 0, false, world.getInstanceId());
world.klanikus = addSpawn(TWIN_SPAWNS[1][0], TWIN_SPAWNS[1][1], TWIN_SPAWNS[1][2], TWIN_SPAWNS[1][3], 0, false, 0, false, world.getInstanceId());
world.klanikus.setIsMortal(false);
world.klodekus.setIsMortal(false);
}
protected void bossSimpleDie(L2Npc boss)
{
// killing is only possible one time
synchronized (this)
{
if (boss.isDead())
{
return;
}
// now reset currentHp to zero
boss.setCurrentHp(0);
boss.setIsDead(true);
}
// Set target to null and cancel Attack or Cast
boss.setTarget(null);
// Stop movement
boss.stopMove(null);
// Stop HP/MP/CP Regeneration task
boss.getStatus().stopHpMpRegeneration();
boss.stopAllEffectsExceptThoseThatLastThroughDeath();
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
boss.broadcastStatusUpdate();
// Notify L2Character AI
boss.getAI().notifyEvent(CtrlEvent.EVT_DEAD);
if (boss.getWorldRegion() != null)
{
boss.getWorldRegion().onDeath(boss);
}
}
@Override
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
{
if (skill.hasEffectType(L2EffectType.REBALANCE_HP, L2EffectType.HEAL))
{
int hate = 2 * skill.getEffectPoint();
if (hate < 2)
{
hate = 1000;
}
((L2Attackable) npc).addDamageHate(caster, 0, hate);
}
return super.onSkillSee(npc, caster, skill, targets, isSummon);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HSAWorld)
{
final HSAWorld world = (HSAWorld) tmpworld;
if (event.equalsIgnoreCase("spawnBossGuards"))
{
if (!world.klanikus.isInCombat() && !world.klodekus.isInCombat())
{
world.isBossesAttacked = false;
return "";
}
L2Npc mob = addSpawn(TWIN_MOBIDS[getRandom(TWIN_MOBIDS.length)], TWIN_SPAWNS[0][1], TWIN_SPAWNS[0][2], TWIN_SPAWNS[0][3], 0, false, 0, false, npc.getInstanceId());
((L2Attackable) mob).addDamageHate(((L2Attackable) npc).getMostHated(), 0, 1);
if (getRandom(100) < 33)
{
mob = addSpawn(TWIN_MOBIDS[getRandom(TWIN_MOBIDS.length)], TWIN_SPAWNS[1][1], TWIN_SPAWNS[1][2], TWIN_SPAWNS[1][3], 0, false, 0, false, npc.getInstanceId());
((L2Attackable) mob).addDamageHate(((L2Attackable) npc).getMostHated(), 0, 1);
}
startQuestTimer("spawnBossGuards", BOSS_MINION_SPAWN_TIME, npc, null);
}
else if (event.equalsIgnoreCase("isTwinSeparated"))
{
if (Util.checkIfInRange(500, world.klanikus, world.klodekus, false))
{
world.klanikus.setIsInvul(false);
world.klodekus.setIsInvul(false);
}
else
{
world.klanikus.setIsInvul(true);
world.klodekus.setIsInvul(true);
}
startQuestTimer("isTwinSeparated", 10000, npc, null);
}
else if (event.equalsIgnoreCase("ressurectTwin"))
{
final Skill skill = SkillData.getInstance().getSkill(5824, 1);
final L2Npc aliveTwin = (world.klanikus == npc ? world.klodekus : world.klanikus);
npc.doRevive();
npc.doCast(skill);
npc.setCurrentHp(aliveTwin.getCurrentHp());
// get most hated of other boss
final L2Character hated = ((L2MonsterInstance) aliveTwin).getMostHated();
if (hated != null)
{
npc.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, hated, 1000);
}
aliveTwin.setIsInvul(true); // make other boss invul
startQuestTimer("uninvul", BOSS_INVUL_TIME, aliveTwin, null);
}
else if (event.equals("uninvul"))
{
npc.setIsInvul(false);
}
}
return "";
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HSAWorld)
{
final HSAWorld world = (HSAWorld) tmpworld;
if (!world.isBossesAttacked)
{
world.isBossesAttacked = true;
final Calendar reenter = Calendar.getInstance();
reenter.add(Calendar.HOUR, INSTANCEPENALTY);
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.INSTANT_ZONE_S1_S_ENTRY_HAS_BEEN_RESTRICTED_YOU_CAN_CHECK_THE_NEXT_POSSIBLE_ENTRY_TIME_BY_USING_THE_COMMAND_INSTANCEZONE);
sm.addInstanceName(tmpworld.getTemplateId());
// set instance reenter time for all allowed players
for (int objectId : tmpworld.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objectId);
if ((player != null) && player.isOnline())
{
InstanceManager.getInstance().setInstanceTime(objectId, tmpworld.getTemplateId(), reenter.getTimeInMillis());
player.sendPacket(sm);
}
}
startQuestTimer("spawnBossGuards", BOSS_MINION_SPAWN_TIME, npc, null);
startQuestTimer("isTwinSeparated", 10000, npc, null);
}
else if (damage >= npc.getCurrentHp())
{
if (world.klanikus.isDead())
{
world.klanikus.setIsDead(false);
world.klanikus.doDie(attacker);
world.klodekus.doDie(attacker);
}
else if (((HSAWorld) tmpworld).klodekus.isDead())
{
world.klodekus.setIsDead(false);
world.klodekus.doDie(attacker);
world.klanikus.doDie(attacker);
}
else
{
bossSimpleDie(npc);
startQuestTimer("ressurectTwin", BOSS_RESSURECT_TIME, npc, null);
}
}
}
return null;
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HSAWorld)
{
final HSAWorld world = (HSAWorld) tmpworld;
if (npc.getId() == TUMOR_ALIVE)
{
npc.deleteMe();
addSpawn(TUMOR_DEAD, npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), false, 0, false, npc.getInstanceId());
}
if (world.getStatus() < 5)
{
if (checkKillProgress(npc, world))
{
runTumors(world);
}
}
else if (world.getStatus() == 5)
{
if (checkKillProgress(npc, world))
{
runTwins(world);
}
}
else if ((world.getStatus() == 6) && ((npc.getId() == KLODEKUS) || (npc.getId() == KLANIKUS)))
{
if (world.klanikus.isDead() && world.klodekus.isDead())
{
world.incStatus();
world.storeTime[1] = System.currentTimeMillis();
world.calcRewardItemId();
world.klanikus = null;
world.klodekus = null;
cancelQuestTimers("ressurectTwin");
cancelQuestTimers("spawnBossGuards");
cancelQuestTimers("isTwinSeparated");
addSpawn(TEPIOS, TEPIOS_SPAWN[0], TEPIOS_SPAWN[1], TEPIOS_SPAWN[2], 0, false, 0, false, world.getInstanceId());
for (Integer pc : world.getAllowed())
{
final L2PcInstance killer = L2World.getInstance().getPlayer(pc);
if (killer != null)
{
killer.sendPacket(new ExSendUIEvent(killer, true, true, 0, 0, ""));
}
}
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
inst.setDuration(5 * 60000);
inst.setEmptyDestroyTime(0);
}
}
}
return "";
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
if (npc.getId() == MOUTHOFEKIMUS)
{
enterInstance(player, "HallOfSufferingAttack.xml", ENTER_TELEPORT);
return null;
}
return "";
}
}

View File

@@ -0,0 +1,596 @@
/*
* 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 gracia.instances.HallOfSufferingDefence;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import com.l2jmobius.gameserver.ai.CtrlEvent;
import com.l2jmobius.gameserver.datatables.SkillData;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2Party;
import com.l2jmobius.gameserver.model.L2World;
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.effects.L2EffectType;
import com.l2jmobius.gameserver.model.entity.Instance;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.util.Util;
import ai.npc.AbstractNpcAI;
import quests.Q00695_DefendTheHallOfSuffering.Q00695_DefendTheHallOfSuffering;
public class HallOfSufferingDefence extends AbstractNpcAI
{
private class HSDWorld extends InstanceWorld
{
public Map<L2Npc, Boolean> npcList = new HashMap<>();
public L2Npc klodekus = null;
public L2Npc klanikus = null;
public boolean isBossesAttacked = false;
public long[] storeTime =
{
0,
0
}; // 0: instance start, 1: finish time
public HSDWorld()
{
tag = -1;
}
protected void calcRewardItemId()
{
final Long finishDiff = storeTime[1] - storeTime[0];
if (finishDiff < 1260000)
{
tag = 13777;
}
else if (finishDiff < 1380000)
{
tag = 13778;
}
else if (finishDiff < 1500000)
{
tag = 13779;
}
else if (finishDiff < 1620000)
{
tag = 13780;
}
else if (finishDiff < 1740000)
{
tag = 13781;
}
else if (finishDiff < 1860000)
{
tag = 13782;
}
else if (finishDiff < 1980000)
{
tag = 13783;
}
else if (finishDiff < 2100000)
{
tag = 13784;
}
else if (finishDiff < 2220000)
{
tag = 13785;
}
else
{
tag = 13786;
}
}
}
private static final int INSTANCEID = 116; // this is the client number
private static final boolean debug = false;
// NPCs
private static final int MOUTHOFEKIMUS = 32537;
private static final int TEPIOS = 32530;
// mobs
private static final int KLODEKUS = 25665;
private static final int KLANIKUS = 25666;
private static final int TUMOR_ALIVE = 18704;
private static final int TUMOR_DEAD = 32531;
//@formatter:off
private static final int[] ENTER_TELEPORT = {-174701,218109,-9592};
private static final int[] TUMOR_MOBIDS = {22509,22510,22511,22512,22513,22514,22515};
private static final int[] TWIN_MOBIDS = {22509,22510,22511,22512,22513};
// Doors/Walls/Zones
private static final int[][] ROOM_1_MOBS =
{
{22509,-173712,217838,-9559}, {22509,-173489,218281,-9557}, {22509,-173824,218389,-9558},
{22510,-174018,217970,-9559}, {22510,-173382,218198,-9547}
};
private static final int[][] ROOM_2_MOBS =
{
{22511,-173456,217976,-9556}, {22511,-173673,217951,-9547}, {22509,-173622,218233,-9547},
{22510,-173775,218218,-9545}, {22510,-173660,217980,-9542}, {22510,-173712,217838,-9559}
};
private static final int[][] ROOM_3_MOBS =
{
{22512,-173489,218281,-9557}, {22512,-173824,218389,-9558}, {22512,-174018,217970,-9559},
{22509,-173382,218198,-9547}, {22511,-173456,217976,-9556}, {22511,-173673,217951,-9547},
{22510,-173622,218233,-9547}, {22510,-173775,218218,-9545}
};
private static final int[][] ROOM_4_MOBS =
{
{22514,-173660,217980,-9542}, {22514,-173712,217838,-9559}, {22514,-173489,218281,-9557},
{22513,-173824,218389,-9558}, {22513,-174018,217970,-9559}, {22511,-173382,218198,-9547},
{22511,-173456,217976,-9556}, {22512,-173673,217951,-9547}, {22512,-173622,218233,-9547}
};
private static final int[][] ROOM_5_MOBS =
{
{22512,-173775,218218,-9545}, {22512,-173660,217980,-9542}, {22512,-173712,217838,-9559},
{22513,-173489,218281,-9557}, {22513,-173824,218389,-9558}, {22514,-174018,217970,-9559},
{22514,-173382,218198,-9547}, {22514,-173456,217976,-9556}, {22515,-173673,217951,-9547},
{22515,-173622,218233,-9547}
};
private static final int[][] TUMOR_SPAWNS =
{
{-173727,218109,-9536},{-173727,218109,-9536},{-173727,218109,-9536},
{-173727,218109,-9536},{-173727,218109,-9536}
};
private static final int[][] TWIN_SPAWNS = {{25665,-173727,218169,-9536},{25666,-173727,218049,-9536}};
private static final int[] TEPIOS_SPAWN = {-173727,218109,-9536};
//@formatter:on
private static final int BOSS_INVUL_TIME = 30000;
private static final int BOSS_MINION_SPAWN_TIME = 60000;
private static final int BOSS_RESSURECT_TIME = 20000;
private static final int INSTANCEPENALTY = 24;
public HallOfSufferingDefence()
{
super(HallOfSufferingDefence.class.getSimpleName(), "gracia/instances");
addStartNpc(MOUTHOFEKIMUS);
addStartNpc(TEPIOS);
addTalkId(MOUTHOFEKIMUS);
addTalkId(TEPIOS);
addKillId(TUMOR_ALIVE);
addKillId(KLODEKUS);
addKillId(KLANIKUS);
addAttackId(KLODEKUS);
addAttackId(KLANIKUS);
addSkillSeeId(TUMOR_MOBIDS);
addKillId(TUMOR_MOBIDS);
}
private boolean checkConditions(L2PcInstance player)
{
if (debug || player.isGM())
{
return true;
}
final L2Party party = player.getParty();
if (party == null)
{
player.sendPacket(SystemMessageId.YOU_ARE_NOT_CURRENTLY_IN_A_PARTY_SO_YOU_CANNOT_ENTER);
return false;
}
if (party.getLeader() != player)
{
player.sendPacket(SystemMessageId.ONLY_A_PARTY_LEADER_CAN_MAKE_THE_REQUEST_TO_ENTER);
return false;
}
for (L2PcInstance partyMember : party.getMembers())
{
if ((partyMember.getLevel() < 75) || (partyMember.getLevel() > 82))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_LEVEL_DOES_NOT_CORRESPOND_TO_THE_REQUIREMENTS_FOR_ENTRY);
sm.addPcName(partyMember);
party.broadcastPacket(sm);
return false;
}
if (!Util.checkIfInRange(1000, player, partyMember, true))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_A_LOCATION_WHICH_CANNOT_BE_ENTERED_THEREFORE_IT_CANNOT_BE_PROCESSED);
sm.addPcName(partyMember);
party.broadcastPacket(sm);
return false;
}
final Long reentertime = InstanceManager.getInstance().getInstanceTime(partyMember.getObjectId(), INSTANCEID);
if (System.currentTimeMillis() < reentertime)
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_MAY_NOT_RE_ENTER_YET);
sm.addPcName(partyMember);
party.broadcastPacket(sm);
return false;
}
final QuestState qs = partyMember.getQuestState(Q00695_DefendTheHallOfSuffering.class.getSimpleName());
if ((qs == null) || !qs.isCond(1))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_QUEST_REQUIREMENT_IS_NOT_SUFFICIENT_AND_CANNOT_BE_ENTERED);
sm.addPcName(partyMember);
party.broadcastPacket(sm);
return false;
}
}
return true;
}
private void teleportPlayer(L2PcInstance player, int[] coords, int instanceId)
{
player.setInstanceId(instanceId);
player.teleToLocation(coords[0], coords[1], coords[2]);
}
protected void enterInstance(L2PcInstance player, String template, int[] coords)
{
// check for existing instances for this player
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
// existing instance
if (world != null)
{
if (!(world instanceof HSDWorld))
{
player.sendPacket(SystemMessageId.YOU_HAVE_ENTERED_ANOTHER_INSTANCE_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON);
return;
}
teleportPlayer(player, coords, world.getInstanceId());
return;
}
if (checkConditions(player))
{
world = new HSDWorld();
world.setInstanceId(InstanceManager.getInstance().createDynamicInstance(template));
world.setTemplateId(INSTANCEID);
world.setStatus(0);
((HSDWorld) world).storeTime[0] = System.currentTimeMillis();
InstanceManager.getInstance().addWorld(world);
_log.info("Hall Of Suffering Defence started " + template + " Instance: " + world.getInstanceId() + " created by player: " + player.getName());
runTumors((HSDWorld) world);
if (player.getParty() == null)
{
teleportPlayer(player, coords, world.getInstanceId());
world.addAllowed(player.getObjectId());
}
else
{
for (L2PcInstance partyMember : player.getParty().getMembers())
{
teleportPlayer(partyMember, coords, world.getInstanceId());
world.addAllowed(partyMember.getObjectId());
}
}
}
}
protected boolean checkKillProgress(L2Npc mob, HSDWorld world)
{
if (world.npcList.containsKey(mob))
{
world.npcList.put(mob, true);
}
for (boolean isDead : world.npcList.values())
{
if (!isDead)
{
return false;
}
}
return true;
}
protected int[][] getRoomSpawns(int room)
{
switch (room)
{
case 0:
return ROOM_1_MOBS;
case 1:
return ROOM_2_MOBS;
case 2:
return ROOM_3_MOBS;
case 3:
return ROOM_4_MOBS;
case 4:
return ROOM_5_MOBS;
}
return new int[][] {};
}
protected void runTumors(HSDWorld world)
{
for (int[] mob : getRoomSpawns(world.getStatus()))
{
final L2Npc npc = addSpawn(mob[0], mob[1], mob[2], mob[3], 0, false, 0, false, world.getInstanceId());
world.npcList.put(npc, false);
}
final L2Npc mob = addSpawn(TUMOR_ALIVE, TUMOR_SPAWNS[world.getStatus()][0], TUMOR_SPAWNS[world.getStatus()][1], TUMOR_SPAWNS[world.getStatus()][2], 0, false, 0, false, world.getInstanceId());
mob.disableCoreAI(true);
mob.setIsImmobilized(true);
mob.setCurrentHp(mob.getMaxHp() * 0.5);
world.npcList.put(mob, false);
world.incStatus();
}
protected void runTwins(HSDWorld world)
{
world.incStatus();
world.klodekus = addSpawn(TWIN_SPAWNS[0][0], TWIN_SPAWNS[0][1], TWIN_SPAWNS[0][2], TWIN_SPAWNS[0][3], 0, false, 0, false, world.getInstanceId());
world.klanikus = addSpawn(TWIN_SPAWNS[1][0], TWIN_SPAWNS[1][1], TWIN_SPAWNS[1][2], TWIN_SPAWNS[1][3], 0, false, 0, false, world.getInstanceId());
world.klanikus.setIsMortal(false);
world.klodekus.setIsMortal(false);
}
protected void bossSimpleDie(L2Npc boss)
{
// killing is only possible one time
synchronized (this)
{
if (boss.isDead())
{
return;
}
// now reset currentHp to zero
boss.setCurrentHp(0);
boss.setIsDead(true);
}
// Set target to null and cancel Attack or Cast
boss.setTarget(null);
// Stop movement
boss.stopMove(null);
// Stop HP/MP/CP Regeneration task
boss.getStatus().stopHpMpRegeneration();
boss.stopAllEffectsExceptThoseThatLastThroughDeath();
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
boss.broadcastStatusUpdate();
// Notify L2Character AI
boss.getAI().notifyEvent(CtrlEvent.EVT_DEAD);
if (boss.getWorldRegion() != null)
{
boss.getWorldRegion().onDeath(boss);
}
}
@Override
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
{
if (skill.hasEffectType(L2EffectType.REBALANCE_HP, L2EffectType.HEAL))
{
int hate = 2 * skill.getEffectPoint();
if (hate < 2)
{
hate = 1000;
}
((L2Attackable) npc).addDamageHate(caster, 0, hate);
}
return super.onSkillSee(npc, caster, skill, targets, isSummon);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HSDWorld)
{
final HSDWorld world = (HSDWorld) tmpworld;
if (event.equalsIgnoreCase("spawnBossGuards"))
{
if (!world.klanikus.isInCombat() && !world.klodekus.isInCombat())
{
world.isBossesAttacked = false;
return "";
}
L2Npc mob = addSpawn(TWIN_MOBIDS[getRandom(TWIN_MOBIDS.length)], TWIN_SPAWNS[0][1], TWIN_SPAWNS[0][2], TWIN_SPAWNS[0][3], 0, false, 0, false, npc.getInstanceId());
((L2Attackable) mob).addDamageHate(((L2Attackable) npc).getMostHated(), 0, 1);
if (getRandom(100) < 33)
{
mob = addSpawn(TWIN_MOBIDS[getRandom(TWIN_MOBIDS.length)], TWIN_SPAWNS[1][1], TWIN_SPAWNS[1][2], TWIN_SPAWNS[1][3], 0, false, 0, false, npc.getInstanceId());
((L2Attackable) mob).addDamageHate(((L2Attackable) npc).getMostHated(), 0, 1);
}
startQuestTimer("spawnBossGuards", BOSS_MINION_SPAWN_TIME, npc, null);
}
else if (event.equalsIgnoreCase("isTwinSeparated"))
{
if (Util.checkIfInRange(500, world.klanikus, world.klodekus, false))
{
world.klanikus.setIsInvul(false);
world.klodekus.setIsInvul(false);
}
else
{
world.klanikus.setIsInvul(true);
world.klodekus.setIsInvul(true);
}
startQuestTimer("isTwinSeparated", 10000, npc, null);
}
else if (event.equalsIgnoreCase("ressurectTwin"))
{
final Skill skill = SkillData.getInstance().getSkill(5824, 1);
final L2Npc aliveTwin = (world.klanikus == npc ? world.klodekus : world.klanikus);
npc.doRevive();
npc.doCast(skill);
npc.setCurrentHp(aliveTwin.getCurrentHp());
// get most hated of other boss
final L2Character hated = ((L2MonsterInstance) aliveTwin).getMostHated();
if (hated != null)
{
npc.getAI().notifyEvent(CtrlEvent.EVT_AGGRESSION, hated, 1000);
}
aliveTwin.setIsInvul(true); // make other boss invul
startQuestTimer("uninvul", BOSS_INVUL_TIME, aliveTwin, null);
}
else if (event.equals("uninvul"))
{
npc.setIsInvul(false);
}
}
return "";
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HSDWorld)
{
final HSDWorld world = (HSDWorld) tmpworld;
if (!world.isBossesAttacked)
{
world.isBossesAttacked = true;
final Calendar reenter = Calendar.getInstance();
reenter.add(Calendar.HOUR, INSTANCEPENALTY);
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.INSTANT_ZONE_S1_S_ENTRY_HAS_BEEN_RESTRICTED_YOU_CAN_CHECK_THE_NEXT_POSSIBLE_ENTRY_TIME_BY_USING_THE_COMMAND_INSTANCEZONE);
sm.addInstanceName(tmpworld.getTemplateId());
// set instance reenter time for all allowed players
for (int objectId : tmpworld.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objectId);
if ((player != null) && player.isOnline())
{
InstanceManager.getInstance().setInstanceTime(objectId, tmpworld.getTemplateId(), reenter.getTimeInMillis());
player.sendPacket(sm);
}
}
startQuestTimer("spawnBossGuards", BOSS_MINION_SPAWN_TIME, npc, null);
startQuestTimer("isTwinSeparated", 10000, npc, null);
}
else if (damage >= npc.getCurrentHp())
{
if (world.klanikus.isDead())
{
world.klanikus.setIsDead(false);
world.klanikus.doDie(attacker);
world.klodekus.doDie(attacker);
}
else if (((HSDWorld) tmpworld).klodekus.isDead())
{
world.klodekus.setIsDead(false);
world.klodekus.doDie(attacker);
world.klanikus.doDie(attacker);
}
else
{
bossSimpleDie(npc);
startQuestTimer("ressurectTwin", BOSS_RESSURECT_TIME, npc, null);
}
}
}
return null;
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HSDWorld)
{
final HSDWorld world = (HSDWorld) tmpworld;
if (npc.getId() == TUMOR_ALIVE)
{
npc.deleteMe();
addSpawn(TUMOR_DEAD, npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), false, 0, false, npc.getInstanceId());
}
if (world.getStatus() < 5)
{
if (checkKillProgress(npc, world))
{
runTumors(world);
}
}
else if (world.getStatus() == 5)
{
if (checkKillProgress(npc, world))
{
runTwins(world);
}
}
else if ((world.getStatus() == 6) && ((npc.getId() == KLODEKUS) || (npc.getId() == KLANIKUS)))
{
if (world.klanikus.isDead() && world.klodekus.isDead())
{
world.incStatus();
world.storeTime[1] = System.currentTimeMillis();
world.calcRewardItemId();
world.klanikus = null;
world.klodekus = null;
cancelQuestTimers("ressurectTwin");
cancelQuestTimers("spawnBossGuards");
cancelQuestTimers("isTwinSeparated");
addSpawn(TEPIOS, TEPIOS_SPAWN[0], TEPIOS_SPAWN[1], TEPIOS_SPAWN[2], 0, false, 0, false, world.getInstanceId());
for (Integer pc : world.getAllowed())
{
final L2PcInstance killer = L2World.getInstance().getPlayer(pc);
if (killer != null)
{
killer.sendPacket(new ExSendUIEvent(killer, true, true, 0, 0, ""));
}
}
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
inst.setDuration(5 * 60000);
inst.setEmptyDestroyTime(0);
}
}
}
return "";
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
if (npc.getId() == MOUTHOFEKIMUS)
{
enterInstance(player, "HallOfSufferingDefence.xml", ENTER_TELEPORT);
return null;
}
return "";
}
}

View File

@@ -0,0 +1,867 @@
/*
* 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 gracia.instances.HeartInfinityAttack;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.instancemanager.SoIManager;
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
import com.l2jmobius.gameserver.model.L2Party;
import com.l2jmobius.gameserver.model.L2World;
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.entity.Instance;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.quest.Quest;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import com.l2jmobius.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.util.Util;
import com.l2jmobius.util.Rnd;
public class HeartInfinityAttack extends Quest
{
private class HIAWorld extends InstanceWorld
{
public List<L2Npc> npcList = new ArrayList<>();
public List<L2Npc> startroom = new ArrayList<>();
public List<L2Npc> deadTumors = new ArrayList<>();
protected L2Npc ekimus;
protected L2Npc deadTumor;
protected List<L2Npc> hounds = new ArrayList<>(2);
public int tumorCount = 0;
public boolean isBossAttacked = false;
public long startTime = 0;
protected ScheduledFuture<?> timerTask;
public synchronized void addTumorCount(int value)
{
tumorCount += value;
}
public synchronized void addTag(int value)
{
tag += value;
}
public HIAWorld()
{
tag = -1;
}
}
private static final String qn = "HeartInfinityAttack";
private static final int INSTANCEID = 121;
private static final int INSTANCEPENALTY = 24;
private static final int ABYSSGAZE = 32540;
private static final int ALIVETUMOR = 18708;
private static final int DEADTUMOR = 32535;
private static final int EKIMUS = 29150;
private static final int HOUND = 29151;
private static final int COFFIN = 18710;
private long tumorRespawnTime;
private boolean conquestBegun = false;
protected boolean conquestEnded = false;
private boolean houndBlocked = false;
private static final int[] ENTER_TELEPORT =
{
-179284,
205990,
-15520
};
private static int[] NOTMOVE =
{
18668,
18711,
ALIVETUMOR,
DEADTUMOR
};
private static final int[] mobs =
{
22516,
22520,
22522,
22524
};
//@formatter:off
private static final int[][] ROOMS_MOBS =
{
{22520, -179949, 206751, -15521, 0, 60, 1},
{22522, -179949, 206505, -15522, 0, 60, 1},
{22532, -180207, 206362, -15512, 0, 60, 1},
{22520, -180046, 206109, -15511, 0, 60, 1},
{22526, -179843, 205686, -15511, 0, 60, 1},
{22522, -179658, 206002, -15518, 0, 60, 1},
{22526, -179465, 205648, -15498, 0, 60, 1},
{22520, -179262, 205896, -15536, 0, 60, 1},
{22526, -178907, 205950, -15509, 0, 60, 1},
{22532, -179128, 206423, -15528, 0, 60, 1},
{22522, -179262, 206890, -15524, 0, 60, 1},
{22516, -177238, 208020, -15521, 0, 60, 1},
{22522, -177202, 207533, -15516, 0, 60, 1},
{22532, -176900, 207515, -15511, 0, 60, 1},
{22524, -176847, 208022, -15523, 0, 60, 1},
{22516, -176187, 207648, -15499, 0, 60, 1},
{22522, -176044, 208039, -15524, 0, 60, 1},
{22532, -176346, 208233, -15533, 0, 60, 1},
{22524, -176440, 208594, -15527, 0, 60, 1},
{22516, -176938, 208543, -15529, 0, 60, 1},
{22524, -176763, 208108, -15523, 0, 60, 1},
{22522, -176483, 207762, -15520, 0, 60, 1},
{22526, -177125, 210766, -15517, 0, 60, 1},
{22520, -176810, 210587, -15515, 0, 60, 1},
{22522, -176820, 210975, -15528, 0, 60, 1},
{22524, -176412, 210873, -15510, 0, 60, 1},
{22526, -176261, 211197, -15511, 0, 60, 1},
{22520, -176241, 211649, -15503, 0, 60, 1},
{22522, -176656, 211884, -15516, 0, 60, 1},
{22524, -176798, 211540, -15541, 0, 60, 1},
{22526, -177130, 211694, -15533, 0, 60, 1},
{22520, -177436, 211384, -15519, 0, 60, 1},
{22522, -177138, 211159, -15524, 0, 60, 1},
{22526, -179311, 212338, -15521, 0, 60, 1},
{22522, -178985, 212502, -15513, 0, 60, 1},
{22516, -179313, 212730, -15522, 0, 60, 1},
{22520, -178966, 213036, -15510, 0, 60, 1},
{22526, -179352, 213172, -15511, 0, 60, 1},
{22522, -179696, 213427, -15514, 0, 60, 1},
{22516, -180096, 213140, -15519, 0, 60, 1},
{22520, -179957, 212724, -15530, 0, 60, 1},
{22522, -180240, 212578, -15518, 0, 60, 1},
{22520, -179891, 212271, -15520, 0, 60, 1},
{22516, -179593, 212488, -15523, 0, 60, 1},
{22516, -181746, 211163, -15515, 0, 60, 1},
{22522, -182002, 211394, -15522, 0, 60, 1},
{22526, -181796, 211647, -15511, 0, 60, 1},
{22516, -182160, 211615, -15518, 0, 60, 1},
{22520, -182322, 211843, -15510, 0, 60, 1},
{22522, -182720, 211686, -15519, 0, 60, 1},
{22520, -182721, 211231, -15535, 0, 60, 1},
{22516, -182957, 210874, -15515, 0, 60, 1},
{22526, -182705, 210606, -15526, 0, 60, 1},
{22520, -182359, 210871, -15526, 0, 60, 1},
{22522, -182051, 210644, -15521, 0, 60, 1},
{22524, -181994, 208452, -15514, 0, 60, 1},
{22516, -182342, 208661, -15510, 0, 60, 1},
{22526, -182471, 208349, -15519, 0, 60, 1},
{22520, -182960, 208335, -15504, 0, 60, 1},
{22524, -182751, 207925, -15514, 0, 60, 1},
{22516, -182671, 207442, -15531, 0, 60, 1},
{22520, -182276, 207438, -15527, 0, 60, 1},
{22526, -181975, 207353, -15520, 0, 60, 1},
{22524, -181989, 207795, -15527, 0, 60, 1},
{22516, -181744, 207997, -15520, 0, 60, 1},
{22520, -182318, 208070, -15523, 0, 60, 1},
{18667, -178430, 211520, -15504, 28672, 120, 1},
{18668, -177341, 209129, -15504, 16384, 120, 1},
{18711, -178067, 207862, -15504, 8192, 120, 1},
{18667, -180679, 207614, -15520, 61439, 120, 1},
{18668, -181761, 209949, -15520, 49151, 120, 1},
{18711, -180328, 211686, -15504, 36863, 120, 1}
};
private static final int[][] ROOMS_TUMORS =
{
{18708, -179779, 212540, -15520, 49151, 0, 1},
{18708, -177028, 211135, -15520, 36863, 0, 1},
{18708, -176355, 208043, -15520, 28672, 0, 1},
{18708, -179284, 205990, -15520, 16384, 0, 1},
{18708, -182268, 208218, -15520, 4096, 0, 1},
{18708, -182069, 211140, -15520, 61439, 0, 1}
};
protected static final int[][] ROOMS_BOSSES =
{
{25637, -179303, 213090, -15504, 49151, 0, 1},
{25638, -176426, 211219, -15504, 36863, 0, 1},
{25639, -177040, 207870, -15504, 28672, 0, 1},
{25640, -179762, 206479, -15504, 16384, 0, 1},
{25641, -182388, 207599, -15504, 4096, 0, 1},
{25642, -182733, 211096, -15504, 61439, 0, 1}
};
//@formatter:on
public HeartInfinityAttack()
{
super(-1, HeartInfinityAttack.class.getSimpleName(), "gracia/instances");
addStartNpc(ABYSSGAZE);
addTalkId(ABYSSGAZE);
addStartNpc(DEADTUMOR);
addTalkId(DEADTUMOR);
addStartNpc(32536);
addTalkId(32536);
for (int id : NOTMOVE)
{
addSpawnId(id);
}
addAggroRangeEnterId(18668);
addAttackId(EKIMUS);
addKillId(ALIVETUMOR);
addKillId(EKIMUS);
addKillId(18711);
tumorRespawnTime = 180 * 1000;
}
private void teleportPlayer(L2PcInstance player, int[] coords, int instanceId)
{
player.setInstanceId(instanceId);
player.teleToLocation(coords[0], coords[1], coords[2]);
}
private boolean checkConditions(L2PcInstance player)
{
final L2Party party = player.getParty();
if (party == null)
{
player.sendPacket(SystemMessageId.YOU_ARE_NOT_CURRENTLY_IN_A_PARTY_SO_YOU_CANNOT_ENTER);
return false;
}
if (party.getLeader() != player)
{
player.sendPacket(SystemMessageId.ONLY_A_PARTY_LEADER_CAN_MAKE_THE_REQUEST_TO_ENTER);
return false;
}
if ((party.getCommandChannel() == null) || (party.getCommandChannel().getLeader() != player))
{
player.sendPacket(SystemMessageId.ONLY_A_PARTY_LEADER_CAN_MAKE_THE_REQUEST_TO_ENTER);
return false;
}
if ((party.getCommandChannel().getMembers().size() < Config.HEART_ATTACK_MIN_PLAYERS) || (party.getCommandChannel().getMembers().size() > Config.HEART_ATTACK_MAX_PLAYERS))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_LEVEL_DOES_NOT_CORRESPOND_TO_THE_REQUIREMENTS_FOR_ENTRY);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
for (L2PcInstance partyMember : party.getCommandChannel().getMembers())
{
if ((partyMember.getLevel() < 75) || (partyMember.getLevel() > 85))
{
final SystemMessage sm = SystemMessage.getSystemMessage(2097);
sm.addPcName(partyMember);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
if (!Util.checkIfInRange(1000, player, partyMember, true))
{
final SystemMessage sm = SystemMessage.getSystemMessage(2096);
sm.addPcName(partyMember);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
final Long reentertime = InstanceManager.getInstance().getInstanceTime(partyMember.getObjectId(), INSTANCEID);
if (System.currentTimeMillis() < reentertime)
{
final SystemMessage sm = SystemMessage.getSystemMessage(2100);
sm.addPcName(partyMember);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
}
return true;
}
protected void enterInstance(L2PcInstance player, String template, int[] coords)
{
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (world != null)
{
if (!(world instanceof HIAWorld))
{
player.sendPacket(SystemMessageId.YOU_HAVE_ENTERED_ANOTHER_INSTANCE_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON);
return;
}
teleportPlayer(player, coords, world.getInstanceId());
return;
}
if (checkConditions(player))
{
world = new HIAWorld();
world.setInstanceId(InstanceManager.getInstance().createDynamicInstance(template));
world.setTemplateId(INSTANCEID);
world.setStatus(0);
InstanceManager.getInstance().addWorld(world);
_log.info("Heart Infinity Attack started " + template + " Instance: " + world.getInstanceId() + " created by player: " + player.getName());
if ((player.getParty() == null) || (player.getParty().getCommandChannel() == null))
{
teleportPlayer(player, coords, world.getInstanceId());
world.addAllowed(player.getObjectId());
}
else
{
for (L2PcInstance partyMember : player.getParty().getCommandChannel().getMembers())
{
teleportPlayer(partyMember, coords, world.getInstanceId());
world.addAllowed(partyMember.getObjectId());
if (partyMember.getQuestState(qn) == null)
{
newQuestState(partyMember);
}
}
}
broadCastPacket(((HIAWorld) world), new ExShowScreenMessage(NpcStringId.YOU_WILL_PARTICIPATE_IN_S1_S2_SHORTLY_BE_PREPARED_FOR_ANYTHING, 2, 8000));
final L2Npc npc = addSpawn(32536, -179376, 206111, -15538, 16384, false, 0, false, ((HIAWorld) world).getInstanceId());
((HIAWorld) world).startroom.add(npc);
}
}
protected void notifyEchmusEntrance(HIAWorld world)
{
if (conquestBegun)
{
return;
}
conquestBegun = true;
ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
for (int objId : world.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objId);
player.showQuestMovie(2); // ExStartScenePlayer.SCENE_ECHMUS_OPENING
}
ThreadPoolManager.getInstance().scheduleGeneral(() -> conquestBegins(world), 62500);
}, 20000);
}
protected void conquestBegins(HIAWorld world)
{
if (!world.startroom.isEmpty())
{
for (L2Npc npc : world.startroom)
{
if (npc != null)
{
npc.deleteMe();
}
}
world.startroom.clear();
}
for (int[] spawn : ROOMS_TUMORS)
{
for (int i = 0; i < spawn[6]; i++)
{
final L2Npc npc = addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
npc.setCurrentHp(npc.getMaxHp() * .5);
world.npcList.add(npc);
}
}
for (int[] spawn : ROOMS_MOBS)
{
for (int i = 0; i < spawn[6]; i++)
{
final L2Npc npc = addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
npc.getSpawn().setRespawnDelay(spawn[5]);
npc.getSpawn().setAmount(1);
if (spawn[5] > 0)
{
npc.getSpawn().startRespawn();
}
else
{
npc.getSpawn().stopRespawn();
}
}
}
InstanceManager.getInstance().getInstance(world.getInstanceId()).getDoor(14240102).openMe();
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.YOU_CAN_HEAR_THE_UNDEAD_OF_EKIMUS_RUSHING_TOWARD_YOU_S1_S2_IT_HAS_NOW_BEGUN, 2, 8000));
world.ekimus = addSpawn(EKIMUS, -179537, 208854, -15504, 16384, false, 0, false, world.getInstanceId());
final NpcSay cs = new NpcSay(world.ekimus.getObjectId(), ChatType.SHOUT, world.ekimus.getId(), NpcStringId.I_SHALL_ACCEPT_YOUR_CHALLENGE_S1_COME_AND_DIE_IN_THE_ARMS_OF_IMMORTALITY);
world.ekimus.broadcastPacket(cs);
world.hounds.add(addSpawn(HOUND, -179224, 209624, -15504, 16384, false, 0, false, world.getInstanceId()));
world.hounds.add(addSpawn(HOUND, -179880, 209464, -15504, 16384, false, 0, false, world.getInstanceId()));
world.startTime = System.currentTimeMillis();
world.timerTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new TimerTask(world), 298 * 1000, 5 * 60 * 1000);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getPlayerWorld(player);
if (tmpworld instanceof HIAWorld)
{
final HIAWorld world = (HIAWorld) tmpworld;
if (event.startsWith("warpechmus"))
{
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.S1_S_PARTY_HAS_MOVED_TO_A_DIFFERENT_LOCATION_THROUGH_THE_CRACK_IN_THE_TUMOR, 2, 8000));
for (L2PcInstance partyMember : player.getParty().getMembers())
{
if (partyMember.isInsideRadius(player, 800, true, false))
{
partyMember.teleToLocation(-179548, 209584, -15504, true);
}
}
notifyEchmusEntrance(world);
}
else if (event.startsWith("reenterechmus"))
{
player.destroyItemByItemId("SOI", 13797, 3, player, true);
notifyEkimusRoomEntrance(world);
for (L2PcInstance partyMember : player.getParty().getMembers())
{
if (partyMember.isInsideRadius(player, 400, true, false))
{
partyMember.teleToLocation(-179548, 209584, -15504, true);
}
}
}
else if (event.startsWith("warp"))
{
L2Npc victim = null;
victim = world.deadTumor;
if (victim != null)
{
world.deadTumors.add(victim);
}
player.destroyItemByItemId("SOI", 13797, 1, player, true);
final Location loc = world.deadTumors.get(Rnd.get(world.deadTumors.size())).getLocation();
if (loc != null)
{
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.S1_S_PARTY_HAS_MOVED_TO_A_DIFFERENT_LOCATION_THROUGH_THE_CRACK_IN_THE_TUMOR, 2, 8000));
for (L2PcInstance partyMember : player.getParty().getMembers())
{
if (partyMember.isInsideRadius(player, 500, true, false))
{
partyMember.teleToLocation(loc, true);
}
}
}
}
}
return "";
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
final int npcId = npc.getId();
QuestState st = player.getQuestState(qn);
if (st == null)
{
st = newQuestState(player);
}
if (npcId == ABYSSGAZE)
{
enterInstance(player, "HeartInfinityAttack.xml", ENTER_TELEPORT);
}
return "";
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HIAWorld)
{
final HIAWorld world = (HIAWorld) tmpworld;
if (npc.getId() == 18668)
{
for (int i = 0; i < Rnd.get(1, 4); i++)
{
addSpawn(mobs[Rnd.get(mobs.length)], npc.getLocation(), world.getInstanceId());
}
npc.doDie(npc);
}
}
return super.onAggroRangeEnter(npc, player, isSummon);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HIAWorld)
{
final HIAWorld world = (HIAWorld) tmpworld;
if (!world.isBossAttacked)
{
world.isBossAttacked = true;
final Calendar reenter = Calendar.getInstance();
reenter.add(Calendar.HOUR, INSTANCEPENALTY);
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.INSTANT_ZONE_S1_S_ENTRY_HAS_BEEN_RESTRICTED_YOU_CAN_CHECK_THE_NEXT_POSSIBLE_ENTRY_TIME_BY_USING_THE_COMMAND_INSTANCEZONE);
sm.addInstanceName(tmpworld.getTemplateId());
for (int objectId : tmpworld.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objectId);
if ((player != null) && player.isOnline())
{
InstanceManager.getInstance().setInstanceTime(objectId, tmpworld.getTemplateId(), reenter.getTimeInMillis());
player.sendPacket(sm);
}
}
}
if (npc.getId() == EKIMUS)
{
for (L2Npc mob : world.hounds)
{
((L2MonsterInstance) mob).addDamageHate(attacker, 0, 500);
mob.setRunning();
mob.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker);
}
}
}
return super.onAttack(npc, attacker, damage, isSummon, skill);
}
@Override
public final String onSpawn(L2Npc npc)
{
if (Util.contains(NOTMOVE, npc.getId()))
{
npc.setIsNoRndWalk(true);
npc.setIsImmobilized(true);
}
if (npc.getId() == HOUND)
{
npc.setIsNoRndWalk(true);
npc.setIsImmobilized(true);
}
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HIAWorld)
{
final HIAWorld world = (HIAWorld) tmpworld;
if (npc.getId() == ALIVETUMOR)
{
world.addTumorCount(1);
handleEkimusStats(world);
}
if (npc.getId() == DEADTUMOR)
{
world.addTag(1);
}
}
return super.onSpawn(npc);
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HIAWorld)
{
final HIAWorld world = (HIAWorld) tmpworld;
final Location loc = npc.getLocation();
if (npc.getId() == ALIVETUMOR)
{
world.addTumorCount(-1);
npc.dropItem(player, 13797, Rnd.get(2, 5));
npc.deleteMe();
world.deadTumor = addSpawn(DEADTUMOR, loc, world.getInstanceId());
world.deadTumors.add(world.deadTumor);
ThreadPoolManager.getInstance().scheduleGeneral(new TumorRevival(world.deadTumor, world), tumorRespawnTime);
ThreadPoolManager.getInstance().scheduleGeneral(new RegenerationCoffinSpawn(world.deadTumor, world), 20000);
if (world.tumorCount < 1)
{
houndBlocked = true;
for (L2Npc hound : world.hounds)
{
hound.setIsInvul(true);
}
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.WITH_ALL_CONNECTIONS_TO_THE_TUMOR_SEVERED_EKIMUS_HAS_LOST_ITS_POWER_TO_CONTROL_THE_FERAL_HOUND, 2, 8000));
}
else
{
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.THE_TUMOR_INSIDE_S1_THAT_HAS_PROVIDED_ENERGY_N_TO_EKIMUS_IS_DESTROYED, 2, 8000));
}
handleEkimusStats(world);
}
if (npc.getId() == EKIMUS)
{
conquestConclusion(world);
SoIManager.notifyEkimusKill();
}
if (npc.getId() == 18711)
{
tumorRespawnTime += 8 * 1000;
}
}
return "";
}
private class TumorRevival implements Runnable
{
private final L2Npc _deadTumor;
private final HIAWorld _world;
public TumorRevival(L2Npc deadTumor, HIAWorld world)
{
_deadTumor = world.deadTumor;
_world = world;
}
@Override
public void run()
{
if (conquestEnded)
{
return;
}
final L2Npc alivetumor = addSpawn(ALIVETUMOR, _deadTumor.getLocation(), _world.getInstanceId());
alivetumor.setCurrentHp(alivetumor.getMaxHp() * .25);
notifyTumorRevival(_world);
_world.npcList.add(alivetumor);
_deadTumor.deleteMe();
_world.addTag(-1);
}
}
private class TimerTask implements Runnable
{
private final HIAWorld _world;
TimerTask(HIAWorld world)
{
_world = world;
}
@Override
public void run()
{
final long time = ((_world.startTime + (25 * 60 * 1000L)) - System.currentTimeMillis()) / 60000;
if (time == 0)
{
broadCastPacket(_world, new ExShowScreenMessage(NpcStringId.YOU_HAVE_FAILED_AT_S1_S2_THE_INSTANCE_WILL_SHORTLY_EXPIRE, 2, 8000));
if (_world != null)
{
conquestEnded = true;
final Instance inst = InstanceManager.getInstance().getInstance(_world.getInstanceId());
if (inst != null)
{
inst.removeNpcs();
if (inst.getPlayers().isEmpty())
{
inst.setDuration(5 * 60000);
}
else
{
inst.setDuration(5 * 60000);
inst.setEmptyDestroyTime(5 * 60000);
}
}
}
}
else
{
for (int[] spawn : ROOMS_BOSSES)
{
for (int i = 0; i < spawn[6]; i++)
{
addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, _world.getInstanceId());
}
}
}
}
}
protected void notifyTumorRevival(HIAWorld world)
{
if ((world.tumorCount == 1) && houndBlocked)
{
houndBlocked = false;
for (L2Npc hound : world.hounds)
{
hound.setIsInvul(false);
}
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.WITH_THE_CONNECTION_TO_THE_TUMOR_RESTORED_EKIMUS_HAS_REGAINED_CONTROL_OVER_THE_FERAL_HOUND, 2, 8000));
}
else
{
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.THE_TUMOR_INSIDE_S1_HAS_BEEN_COMPLETELY_RESURRECTED_N_AND_STARTED_TO_ENERGIZE_EKIMUS_AGAIN, 2, 8000));
}
handleEkimusStats(world);
}
private class RegenerationCoffinSpawn implements Runnable
{
private final L2Npc _deadTumor;
private final HIAWorld _world;
public RegenerationCoffinSpawn(L2Npc deadTumor, HIAWorld world)
{
_deadTumor = world.deadTumor;
_world = world;
}
@Override
public void run()
{
if (conquestEnded)
{
return;
}
for (int i = 0; i < 4; i++)
{
final L2Npc worm = addSpawn(COFFIN, _deadTumor.getLocation(), _world.getInstanceId());
_world.npcList.add(worm);
}
}
}
private void handleEkimusStats(HIAWorld world)
{
// TODO FIXME
// double[] a = getStatMultiplier(world);
// world.ekimus.removeStatsOwner(this);
// world.ekimus.addStatFunc(new FuncGet(Stats.POWER_ATTACK, 0x30, this, world.ekimus.getTemplate().getBasePAtk() * 3));
// world.ekimus.addStatFunc(new FuncGet(Stats.MAGIC_ATTACK, 0x30, this, world.ekimus.getTemplate().getBaseMAtk() * 10));
// world.ekimus.addStatFunc(new FuncGet(Stats.POWER_DEFENCE, 0x30, this, world.ekimus.getTemplate().getBasePDef() * a[1]));
// world.ekimus.addStatFunc(new FuncGet(Stats.MAGIC_DEFENCE, 0x30, this, world.ekimus.getTemplate().getBaseMDef() * a[0]));
// world.ekimus.addStatFunc(new FuncGet(Stats.REGENERATE_HP_RATE, 0x30, this, world.ekimus.getTemplate().getBaseHpReg() * a[2]));
}
@SuppressWarnings("unused")
private double[] getStatMultiplier(HIAWorld world)
{
final double[] a = new double[3];
switch (world.tumorCount)
{
case 6:
a[0] = 2;
a[1] = 1;
a[2] = 4;
break;
case 5:
a[0] = 1.9;
a[1] = 0.9;
a[2] = 3.5;
break;
case 4:
a[0] = 1.5;
a[1] = 0.6;
a[2] = 3.0;
break;
case 3:
a[0] = 1.0;
a[1] = 0.4;
a[2] = 2.5;
break;
case 2:
a[0] = 0.7;
a[1] = 0.3;
a[2] = 2.0;
break;
case 1:
a[0] = 0.3;
a[1] = 0.15;
a[2] = 1.0;
break;
case 0:
a[0] = 0.12;
a[1] = 0.06;
a[2] = 0.25;
break;
}
return a;
}
public void notifyEkimusRoomEntrance(HIAWorld world)
{
for (L2PcInstance ch : ZoneManager.getInstance().getZoneById(200032).getPlayersInside())
{
if (ch != null)
{
ch.teleToLocation(-179537, 211233, -15472, true);
}
}
ThreadPoolManager.getInstance().scheduleGeneral(() -> broadCastPacket(world, new ExShowScreenMessage(NpcStringId.EKIMUS_HAS_SENSED_ABNORMAL_ACTIVITY_NTHE_ADVANCING_PARTY_IS_FORCEFULLY_EXPELLED, 2, 8000)), 10000);
}
protected void conquestConclusion(HIAWorld world)
{
if (world.timerTask != null)
{
world.timerTask.cancel(false);
}
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.CONGRATULATIONS_YOU_HAVE_SUCCEEDED_AT_S1_S2_THE_INSTANCE_WILL_SHORTLY_EXPIRE, 2, 8000));
conquestEnded = true;
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
if (inst != null)
{
inst.removeNpcs();
if (inst.getPlayers().isEmpty())
{
inst.setDuration(5 * 60000);
}
else
{
inst.setDuration(5 * 60000);
inst.setEmptyDestroyTime(5 * 60000);
}
}
}
protected void broadCastPacket(HIAWorld world, L2GameServerPacket packet)
{
for (int objId : world.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objId);
if ((player != null) && player.isOnline() && (player.getInstanceId() == world.getInstanceId()))
{
player.sendPacket(packet);
}
}
}
}

View File

@@ -0,0 +1,776 @@
/*
* 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 gracia.instances.HeartInfinityDefence;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.L2Party;
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.L2MonsterInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Instance;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.quest.Quest;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import com.l2jmobius.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.util.Util;
import com.l2jmobius.util.Rnd;
import quests.Q00697_DefendTheHallOfErosion.Q00697_DefendTheHallOfErosion;
public class HeartInfinityDefence extends Quest
{
private class HIDWorld extends InstanceWorld
{
public List<L2Npc> npcList = new ArrayList<>();
public List<L2Npc> deadTumors = new ArrayList<>();
protected L2Npc deadTumor;
public long startTime = 0;
protected ScheduledFuture<?> finishTask = null, timerTask = null, wagonSpawnTask = null;
public HIDWorld()
{
}
}
private static final String qn = "HeartInfinityDefence";
private static final int INSTANCEID = 122;
private static final int ABYSSGAZE = 32539;
private static final int ALIVETUMOR = 18708;
private static final int DEADTUMOR = 32535;
private static final int SOULWAGON = 22523;
private static final int REGENERATION_COFFIN = 18709;
private static final int maxCoffins = 20;
L2Npc preawakenedEchmus = null;
protected int coffinsCreated = 0;
protected long tumorRespawnTime = 0;
protected long wagonRespawnTime = 0;
protected boolean conquestBegun = false;
protected boolean conquestEnded = false;
private static final int[] ENTER_TELEPORT =
{
-179284,
205990,
-15520
};
private static int[] NOTMOVE =
{
18668,
18711,
ALIVETUMOR,
DEADTUMOR
};
private static final int[] mobs =
{
22516,
22520,
22522,
22524
};
//@formatter:off
protected static final int[][] ROOMS_MOBS =
{
{22520, -179949, 206751, -15521, 0, 60, 1},
{22522, -179949, 206505, -15522, 0, 60, 1},
{22532, -180207, 206362, -15512, 0, 60, 1},
{22520, -180046, 206109, -15511, 0, 60, 1},
{22526, -179843, 205686, -15511, 0, 60, 1},
{22522, -179658, 206002, -15518, 0, 60, 1},
{22526, -179465, 205648, -15498, 0, 60, 1},
{22520, -179262, 205896, -15536, 0, 60, 1},
{22526, -178907, 205950, -15509, 0, 60, 1},
{22532, -179128, 206423, -15528, 0, 60, 1},
{22522, -179262, 206890, -15524, 0, 60, 1},
{22516, -177238, 208020, -15521, 0, 60, 1},
{22522, -177202, 207533, -15516, 0, 60, 1},
{22532, -176900, 207515, -15511, 0, 60, 1},
{22524, -176847, 208022, -15523, 0, 60, 1},
{22516, -176187, 207648, -15499, 0, 60, 1},
{22522, -176044, 208039, -15524, 0, 60, 1},
{22532, -176346, 208233, -15533, 0, 60, 1},
{22524, -176440, 208594, -15527, 0, 60, 1},
{22516, -176938, 208543, -15529, 0, 60, 1},
{22524, -176763, 208108, -15523, 0, 60, 1},
{22522, -176483, 207762, -15520, 0, 60, 1},
{22526, -177125, 210766, -15517, 0, 60, 1},
{22520, -176810, 210587, -15515, 0, 60, 1},
{22522, -176820, 210975, -15528, 0, 60, 1},
{22524, -176412, 210873, -15510, 0, 60, 1},
{22526, -176261, 211197, -15511, 0, 60, 1},
{22520, -176241, 211649, -15503, 0, 60, 1},
{22522, -176656, 211884, -15516, 0, 60, 1},
{22524, -176798, 211540, -15541, 0, 60, 1},
{22526, -177130, 211694, -15533, 0, 60, 1},
{22520, -177436, 211384, -15519, 0, 60, 1},
{22522, -177138, 211159, -15524, 0, 60, 1},
{22526, -179311, 212338, -15521, 0, 60, 1},
{22522, -178985, 212502, -15513, 0, 60, 1},
{22516, -179313, 212730, -15522, 0, 60, 1},
{22520, -178966, 213036, -15510, 0, 60, 1},
{22526, -179352, 213172, -15511, 0, 60, 1},
{22522, -179696, 213427, -15514, 0, 60, 1},
{22516, -180096, 213140, -15519, 0, 60, 1},
{22520, -179957, 212724, -15530, 0, 60, 1},
{22522, -180240, 212578, -15518, 0, 60, 1},
{22520, -179891, 212271, -15520, 0, 60, 1},
{22516, -179593, 212488, -15523, 0, 60, 1},
{22516, -181746, 211163, -15515, 0, 60, 1},
{22522, -182002, 211394, -15522, 0, 60, 1},
{22526, -181796, 211647, -15511, 0, 60, 1},
{22516, -182160, 211615, -15518, 0, 60, 1},
{22520, -182322, 211843, -15510, 0, 60, 1},
{22522, -182720, 211686, -15519, 0, 60, 1},
{22520, -182721, 211231, -15535, 0, 60, 1},
{22516, -182957, 210874, -15515, 0, 60, 1},
{22526, -182705, 210606, -15526, 0, 60, 1},
{22520, -182359, 210871, -15526, 0, 60, 1},
{22522, -182051, 210644, -15521, 0, 60, 1},
{22524, -181994, 208452, -15514, 0, 60, 1},
{22516, -182342, 208661, -15510, 0, 60, 1},
{22526, -182471, 208349, -15519, 0, 60, 1},
{22520, -182960, 208335, -15504, 0, 60, 1},
{22524, -182751, 207925, -15514, 0, 60, 1},
{22516, -182671, 207442, -15531, 0, 60, 1},
{22520, -182276, 207438, -15527, 0, 60, 1},
{22526, -181975, 207353, -15520, 0, 60, 1},
{22524, -181989, 207795, -15527, 0, 60, 1},
{22516, -181744, 207997, -15520, 0, 60, 1},
{22520, -182318, 208070, -15523, 0, 60, 1},
{18667, -178430, 211520, -15504, 28672, 120, 1},
{18668, -177341, 209129, -15504, 16384, 120, 1},
{18711, -178067, 207862, -15504, 8192, 120, 1},
{18667, -180679, 207614, -15520, 61439, 120, 1},
{18668, -181761, 209949, -15520, 49151, 120, 1},
{18711, -180328, 211686, -15504, 36863, 120, 1}
};
protected static final int[][] ROOMS_TUMORS =
{
{32535, -179779, 212540, -15520, 49151, 0, 1},
{32535, -177028, 211135, -15520, 36863, 0, 1},
{32535, -176355, 208043, -15520, 28672, 0, 1},
{32535, -179284, 205990, -15520, 16384, 0, 1},
{32535, -182268, 208218, -15520, 4096, 0, 1},
{32535, -182069, 211140, -15520, 61439, 0, 1}
};
protected static final int[][] ROOMS_ALIVE_TUMORS =
{
{18708, -179779, 212540, -15520, 49151, 0, 1},
{18708, -177028, 211135, -15520, 36863, 0, 1},
{18708, -176355, 208043, -15520, 28672, 0, 1},
{18708, -179284, 205990, -15520, 16384, 0, 1},
{18708, -182268, 208218, -15520, 4096, 0, 1},
{18708, -182069, 211140, -15520, 61439, 0, 1}
};
protected static final int[][] ROOMS_BOSSES =
{
{25637, -179303, 213090, -15504, 49151, 0, 1},
{25638, -176426, 211219, -15504, 36863, 0, 1},
{25639, -177040, 207870, -15504, 28672, 0, 1},
{25640, -179762, 206479, -15504, 16384, 0, 1},
{25641, -182388, 207599, -15504, 4096, 0, 1},
{25642, -182733, 211096, -15504, 61439, 0, 1}
};
protected static int[][] SOULWAGON_SPAWN =
{
{SOULWAGON, -180003, 206703, -15520, 0, 0, -1},
{SOULWAGON, -180056, 216162, -15511, 0, 0, -1},
{SOULWAGON, -179586, 205657, -15499, 0, 0, -1},
{SOULWAGON, -179029, 205991, -15518, 0, 0, -1},
{SOULWAGON, -178960, 206658, -15526, 0, 0, -1},
{SOULWAGON, -179350, 206484, -15524, 0, 0, -1},
{SOULWAGON, -179526, 206900, -15520, 0, 0, -1},
{SOULWAGON, -179329, 205916, -15532, 0, 0, -1}
};
//@formatter:on
public HeartInfinityDefence()
{
super(-1, HeartInfinityDefence.class.getSimpleName(), "gracia/instances");
addStartNpc(ABYSSGAZE);
addTalkId(ABYSSGAZE);
addStartNpc(DEADTUMOR);
addTalkId(DEADTUMOR);
addStartNpc(32536);
addTalkId(32536);
for (int id : NOTMOVE)
{
addSpawnId(id);
}
addSpawnId(SOULWAGON);
addAggroRangeEnterId(18668);
addKillId(ALIVETUMOR);
addKillId(18711);
tumorRespawnTime = 180 * 1000;
wagonRespawnTime = 60 * 1000;
addEnterZoneId(200032);
}
private void teleportPlayer(L2PcInstance player, int[] coords, int instanceId)
{
player.setInstanceId(instanceId);
player.teleToLocation(coords[0], coords[1], coords[2]);
}
private boolean checkConditions(L2PcInstance player)
{
if (player.isGM())
{
return true;
}
final L2Party party = player.getParty();
if (party == null)
{
player.sendPacket(SystemMessageId.YOU_ARE_NOT_CURRENTLY_IN_A_PARTY_SO_YOU_CANNOT_ENTER);
return false;
}
if (party.getLeader() != player)
{
player.sendPacket(SystemMessageId.ONLY_A_PARTY_LEADER_CAN_MAKE_THE_REQUEST_TO_ENTER);
return false;
}
if ((party.getCommandChannel() == null) || (party.getCommandChannel().getLeader() != player))
{
player.sendPacket(SystemMessageId.ONLY_A_PARTY_LEADER_CAN_MAKE_THE_REQUEST_TO_ENTER);
return false;
}
if ((party.getCommandChannel().getMembers().size() < Config.HEART_DEFENCE_MIN_PLAYERS) || (party.getCommandChannel().getMembers().size() > Config.HEART_DEFENCE_MAX_PLAYERS))// 18 27
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_LEVEL_DOES_NOT_CORRESPOND_TO_THE_REQUIREMENTS_FOR_ENTRY);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
for (L2PcInstance partyMember : party.getCommandChannel().getMembers())
{
if ((partyMember.getLevel() < 75) || (partyMember.getLevel() > 85))
{
final SystemMessage sm = SystemMessage.getSystemMessage(2097);
sm.addPcName(partyMember);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
if (!Util.checkIfInRange(1000, player, partyMember, true))
{
final SystemMessage sm = SystemMessage.getSystemMessage(2096);
sm.addPcName(partyMember);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
final Long reentertime = InstanceManager.getInstance().getInstanceTime(partyMember.getObjectId(), INSTANCEID);
if (System.currentTimeMillis() < reentertime)
{
final SystemMessage sm = SystemMessage.getSystemMessage(2100);
sm.addPcName(partyMember);
party.getCommandChannel().broadcastPacket(sm);
return false;
}
}
return true;
}
protected void enterInstance(L2PcInstance player, String template, int[] coords)
{
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (world != null)
{
if (!(world instanceof HIDWorld))
{
player.sendPacket(SystemMessageId.YOU_HAVE_ENTERED_ANOTHER_INSTANCE_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON);
return;
}
teleportPlayer(player, coords, world.getInstanceId());
return;
}
if (checkConditions(player))
{
world = new HIDWorld();
world.setInstanceId(InstanceManager.getInstance().createDynamicInstance(template));
world.setTemplateId(INSTANCEID);
world.setStatus(0);
InstanceManager.getInstance().addWorld(world);
_log.info("Heart Infinity Defence started " + template + " Instance: " + world.getInstanceId() + " created by player: " + player.getName());
if (player.isGM())
{
teleportPlayer(player, coords, world.getInstanceId());
world.addAllowed(player.getObjectId());
}
if ((player.getParty() == null) || (player.getParty().getCommandChannel() == null))
{
teleportPlayer(player, coords, world.getInstanceId());
world.addAllowed(player.getObjectId());
}
else
{
for (L2PcInstance partyMember : player.getParty().getCommandChannel().getMembers())
{
teleportPlayer(partyMember, coords, world.getInstanceId());
world.addAllowed(partyMember.getObjectId());
if (partyMember.getQuestState(qn) == null)
{
newQuestState(partyMember);
}
}
}
((HIDWorld) world).startTime = System.currentTimeMillis();
((HIDWorld) world).finishTask = ThreadPoolManager.getInstance().scheduleGeneral(new FinishTask((HIDWorld) world), 30 * 60000);
((HIDWorld) world).timerTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new TimerTask((HIDWorld) world), 298 * 1000, 5 * 60 * 1000);
conquestBegins((HIDWorld) world);
}
}
private void conquestBegins(HIDWorld world)
{
ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.YOU_CAN_HEAR_THE_UNDEAD_OF_EKIMUS_RUSHING_TOWARD_YOU_S1_S2_IT_HAS_NOW_BEGUN, 2, 8000));
for (int[] spawn1 : ROOMS_MOBS)
{
for (int i1 = 0; i1 < spawn1[6]; i1++)
{
final L2Npc npc1 = addSpawn(spawn1[0], spawn1[1], spawn1[2], spawn1[3], spawn1[4], false, 0, false, world.getInstanceId());
npc1.getSpawn().setRespawnDelay(spawn1[5]);
npc1.getSpawn().setAmount(1);
if (spawn1[5] > 0)
{
npc1.getSpawn().startRespawn();
}
else
{
npc1.getSpawn().stopRespawn();
}
}
}
for (int[] spawn2 : ROOMS_TUMORS)
{
for (int i2 = 0; i2 < spawn2[6]; i2++)
{
final L2Npc npc2 = addSpawn(spawn2[0], spawn2[1], spawn2[2], spawn2[3], spawn2[4], false, 0, false, world.getInstanceId());
world.deadTumors.add(npc2);
}
}
InstanceManager.getInstance().getInstance(world.getInstanceId()).getDoor(14240102).openMe();
preawakenedEchmus = addSpawn(29161, -179534, 208510, -15496, 16342, false, 0, false, world.getInstanceId());
ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
if (!conquestEnded)
{
if (!world.deadTumors.isEmpty())
{
for (L2Npc npc : world.deadTumors)
{
if (npc != null)
{
spawnCoffin(npc, world);
}
}
}
}
}, 60000);
ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
if (!conquestEnded)
{
if (!world.deadTumors.isEmpty())
{
for (L2Npc npc3 : world.deadTumors)
{
if (npc3 != null)
{
npc3.deleteMe();
}
}
world.deadTumors.clear();
}
for (int[] spawn : ROOMS_ALIVE_TUMORS)
{
for (int i = 0; i < spawn[6]; i++)
{
final L2Npc npc4 = addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, world.getInstanceId());
npc4.setCurrentHp(npc4.getMaxHp() * .5);
world.deadTumors.add(npc4);
}
}
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.THE_TUMOR_INSIDE_S1_HAS_COMPLETELY_REVIVED_NEKIMUS_STARTED_TO_REGAIN_HIS_ENERGY_AND_IS_DESPERATELY_LOOKING_FOR_HIS_PREY, 2, 8000));
}
}, tumorRespawnTime);
world.wagonSpawnTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(() -> addSpawn(SOULWAGON, -179544, 207400, -15496, 0, false, 0, false, world.getInstanceId()), 1000, wagonRespawnTime);
}, 20000);
}
void spawnCoffin(L2Npc npc, HIDWorld world)
{
addSpawn(REGENERATION_COFFIN, npc.getLocation(), world.getInstanceId());
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getPlayerWorld(player);
if (tmpworld instanceof HIDWorld)
{
final HIDWorld world = (HIDWorld) tmpworld;
if (event.startsWith("warpechmus"))
{
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.S1_S_PARTY_HAS_MOVED_TO_A_DIFFERENT_LOCATION_THROUGH_THE_CRACK_IN_THE_TUMOR, 2, 8000));
for (L2PcInstance partyMember : player.getParty().getMembers())
{
if (partyMember.isInsideRadius(player, 800, true, false))
{
partyMember.teleToLocation(-179548, 209584, -15504, true);
}
}
}
else if (event.startsWith("reenterechmus"))
{
player.destroyItemByItemId("SOI", 13797, 3, player, true);
for (L2PcInstance partyMember : player.getParty().getMembers())
{
if (partyMember.isInsideRadius(player, 400, true, false))
{
partyMember.teleToLocation(-179548, 209584, -15504, true);
}
}
}
else if (event.startsWith("warp"))
{
L2Npc victim = null;
victim = world.deadTumor;
if (victim != null)
{
world.deadTumors.add(victim);
}
player.destroyItemByItemId("SOI", 13797, 1, player, true);
final Location loc = world.deadTumors.get(Rnd.get(world.deadTumors.size())).getLocation();
if (loc != null)
{
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.S1_S_PARTY_HAS_MOVED_TO_A_DIFFERENT_LOCATION_THROUGH_THE_CRACK_IN_THE_TUMOR, 2, 8000));
for (L2PcInstance partyMember : player.getParty().getMembers())
{
if (partyMember.isInsideRadius(player, 500, true, false))
{
partyMember.teleToLocation(loc, true);
}
}
}
}
}
return "";
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
final int npcId = npc.getId();
QuestState st = player.getQuestState(qn);
if (st == null)
{
st = newQuestState(player);
}
if (npcId == ABYSSGAZE)
{
enterInstance(player, "HeartInfinityDefence.xml", ENTER_TELEPORT);
}
return "";
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HIDWorld)
{
final HIDWorld world = (HIDWorld) tmpworld;
if (npc.getId() == 18668)
{
for (int i = 0; i < Rnd.get(1, 4); i++)
{
addSpawn(mobs[Rnd.get(mobs.length)], npc.getLocation(), world.getInstanceId());
}
npc.doDie(npc);
}
}
return super.onAggroRangeEnter(npc, player, isSummon);
}
@Override
public final String onSpawn(L2Npc npc)
{
if (Util.contains(NOTMOVE, npc.getId()))
{
npc.setIsNoRndWalk(true);
npc.setIsImmobilized(true);
}
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HIDWorld)
{
if (npc.getId() == SOULWAGON)
{
// ((L2MonsterInstance) npc).setPassive(true);
((L2MonsterInstance) npc).getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
}
}
return super.onSpawn(npc);
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HIDWorld)
{
final HIDWorld world = (HIDWorld) tmpworld;
final Location loc = npc.getLocation();
if (npc.getId() == ALIVETUMOR)
{
npc.dropItem(player, 13797, Rnd.get(2, 5));
npc.deleteMe();
world.deadTumor = addSpawn(DEADTUMOR, loc, world.getInstanceId());
world.deadTumors.add(world.deadTumor);
wagonRespawnTime += 10000;
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.THE_TUMOR_INSIDE_S1_HAS_BEEN_DESTROYED_NTHE_SPEED_THAT_EKIMUS_CALLS_OUT_HIS_PREY_HAS_SLOWED_DOWN, 2, 8000));
ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
world.deadTumor.deleteMe();
final L2Npc alivetumor = addSpawn(ALIVETUMOR, loc, world.getInstanceId());
alivetumor.setCurrentHp(alivetumor.getMaxHp() * .25);
world.npcList.add(alivetumor);
wagonRespawnTime -= 10000;
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.THE_TUMOR_INSIDE_S1_HAS_COMPLETELY_REVIVED_NEKIMUS_STARTED_TO_REGAIN_HIS_ENERGY_AND_IS_DESPERATELY_LOOKING_FOR_HIS_PREY, 2, 8000));
}, tumorRespawnTime);
}
if (npc.getId() == 18711)
{
tumorRespawnTime += 5 * 1000;
}
}
return "";
}
protected void notifyWagonArrived(L2Npc npc, HIDWorld world)
{
coffinsCreated++;
if (coffinsCreated == 20)
{
conquestConclusion(world);
}
else
{
final NpcSay cs = new NpcSay(preawakenedEchmus.getObjectId(), ChatType.SHOUT, preawakenedEchmus.getId(), NpcStringId.BRING_MORE_MORE_SOULS);
preawakenedEchmus.broadcastPacket(cs);
final ExShowScreenMessage message = new ExShowScreenMessage(NpcStringId.THE_SOUL_COFFIN_HAS_AWAKENED_EKIMUS_IF_S1_MORE_SOUL_COFFIN_S_ARE_CREATED_THE_DEFENSE_OF_THE_HEART_OF_IMMORTALITY_WILL_FAIL, 2, 8000);
message.addStringParameter(Integer.toString(maxCoffins - coffinsCreated));
broadCastPacket(world, message);
}
}
private class TimerTask implements Runnable
{
private final HIDWorld _world;
TimerTask(HIDWorld world)
{
_world = world;
}
@Override
public void run()
{
final long time = ((_world.startTime + (25 * 60 * 1000L)) - System.currentTimeMillis()) / 60000;
if (time == 0)
{
conquestConclusion(_world);
}
else
{
if (time == 15)
{
for (int[] spawn : ROOMS_BOSSES)
{
for (int i = 0; i < spawn[6]; i++)
{
addSpawn(spawn[0], spawn[1], spawn[2], spawn[3], spawn[4], false, 0, false, _world.getInstanceId());
}
}
}
}
}
}
class FinishTask implements Runnable
{
private final HIDWorld _world;
FinishTask(HIDWorld world)
{
_world = world;
}
@Override
public void run()
{
if (_world != null)
{
conquestEnded = true;
final Instance inst = InstanceManager.getInstance().getInstance(_world.getInstanceId());
if (inst != null)
{
for (int objId : _world.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objId);
final QuestState st = player.getQuestState(Q00697_DefendTheHallOfErosion.class.getSimpleName());
if ((st != null) && (st.getInt("cond") == 1))
{
st.set("defenceDone", 1);
}
}
broadCastPacket(_world, new ExShowScreenMessage(NpcStringId.CONGRATULATIONS_YOU_HAVE_SUCCEEDED_AT_S1_S2_THE_INSTANCE_WILL_SHORTLY_EXPIRE, 2, 8000));
inst.removeNpcs();
if (inst.getPlayers().isEmpty())
{
inst.setDuration(5 * 60000);
}
else
{
inst.setDuration(5 * 60000);
inst.setEmptyDestroyTime(5 * 60000);
}
}
}
}
}
protected void conquestConclusion(HIDWorld world)
{
if (world.timerTask != null)
{
world.timerTask.cancel(false);
}
if (world.finishTask != null)
{
world.finishTask.cancel(false);
}
if (world.wagonSpawnTask != null)
{
world.wagonSpawnTask.cancel(false);
}
broadCastPacket(world, new ExShowScreenMessage(NpcStringId.YOU_HAVE_FAILED_AT_S1_S2_THE_INSTANCE_WILL_SHORTLY_EXPIRE, 2, 8000));
conquestEnded = true;
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
if (inst != null)
{
inst.removeNpcs();
if (inst.getPlayers().isEmpty())
{
inst.setDuration(5 * 60000);
}
else
{
inst.setDuration(5 * 60000);
inst.setEmptyDestroyTime(5 * 60000);
}
}
}
@Override
public final String onEnterZone(L2Character character, L2ZoneType zone)
{
if (character instanceof L2Attackable)
{
final L2Attackable npc = (L2Attackable) character;
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HIDWorld)
{
final HIDWorld world = (HIDWorld) tmpworld;
if (npc.getId() == SOULWAGON)
{
notifyWagonArrived(npc, world);
npc.deleteMe();
}
}
}
return null;
}
protected void broadCastPacket(HIDWorld world, L2GameServerPacket packet)
{
for (int objId : world.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objId);
if ((player != null) && player.isOnline() && (player.getInstanceId() == world.getInstanceId()))
{
player.sendPacket(packet);
}
}
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Soldier Ginby:<br>
Hurry! Come back before anybody sees you!
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Shilen Priest Lelrikia:<br>
Doomed creature, either you obey the power of Shilen or you fight.Regardless of your decision, the shadow of death will not simply fade away...
</body></html>

View File

@@ -0,0 +1,98 @@
/*
* 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 gracia.instances.SecretArea;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.network.SystemMessageId;
import ai.npc.AbstractNpcAI;
/**
* Secret Area in the Keucereus Fortress instance zone.
* @author Gladicek
*/
public final class SecretArea extends AbstractNpcAI
{
protected class SAWorld extends InstanceWorld
{
}
private static final int TEMPLATE_ID = 117;
private static final int GINBY = 32566;
private static final int LELRIKIA = 32567;
private static final int ENTER = 0;
private static final int EXIT = 1;
private static final Location[] TELEPORTS =
{
new Location(-23758, -8959, -5384),
new Location(-185057, 242821, 1576)
};
public SecretArea()
{
super(SecretArea.class.getSimpleName(), "gracia/instances");
addStartNpc(GINBY);
addTalkId(GINBY);
addTalkId(LELRIKIA);
}
protected void enterInstance(L2PcInstance player)
{
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (world != null)
{
if (world instanceof SAWorld)
{
teleportPlayer(player, TELEPORTS[ENTER], world.getInstanceId());
return;
}
player.sendPacket(SystemMessageId.YOU_HAVE_ENTERED_ANOTHER_INSTANCE_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON);
return;
}
world = new SAWorld();
world.setInstanceId(InstanceManager.getInstance().createDynamicInstance("SecretArea.xml"));
world.setTemplateId(TEMPLATE_ID);
world.addAllowed(player.getObjectId());
world.setStatus(0);
InstanceManager.getInstance().addWorld(world);
teleportPlayer(player, TELEPORTS[ENTER], world.getInstanceId());
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final String htmltext = getNoQuestMsg(player);
if ((npc.getId() == GINBY) && event.equalsIgnoreCase("enter"))
{
enterInstance(player);
return "32566-01.html";
}
else if ((npc.getId() == LELRIKIA) && event.equalsIgnoreCase("exit"))
{
teleportPlayer(player, TELEPORTS[EXIT], 0);
return "32567-01.html";
}
return htmltext;
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Instant Moving Device:<br>
<a action="bypass -h npc_%objectId%_Quest SeedOfDestruction">Teleport to the central region.</a><br>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Instant Moving Device:<br>
Army has blocked all exits.<br>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Instant Moving Device:<br>
<a action="bypass -h npc_%objectId%_Quest SeedofDestruction">Exit.</a><br>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Temporary Teleporter:<br>
Where do you want me you teleported?<br>
<a action="bypass -h npc_%objectId%_goto 3260201">Teleport to the central square.</a><br>
<a action="bypass -h npc_%objectId%_goto 3260202">Teleport to Fort.</a><br>
<a action="bypass -h npc_%objectId%_goto 3260203">Teleport to the throne of the dragon.</a>
</body></html>

View File

@@ -0,0 +1,423 @@
/*
* 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 gracia.vehicles;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.instancemanager.AirShipManager;
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.VehiclePathPoint;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2AirShipInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2ControllableAirShipInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.quest.Quest;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.type.L2ScriptZone;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public abstract class AirShipController extends Quest
{
protected final class DecayTask implements Runnable
{
@Override
public void run()
{
if (_dockedShip != null)
{
_dockedShip.deleteMe();
}
}
}
protected final class DepartTask implements Runnable
{
@Override
public void run()
{
if ((_dockedShip != null) && _dockedShip.isInDock() && !_dockedShip.isMoving())
{
if (_departPath != null)
{
_dockedShip.executePath(_departPath);
}
else
{
_dockedShip.deleteMe();
}
}
}
}
public static final Logger _log = Logger.getLogger(AirShipController.class.getName());
protected int _dockZone = 0;
protected int _shipSpawnX = 0;
protected int _shipSpawnY = 0;
protected int _shipSpawnZ = 0;
protected int _shipHeading = 0;
protected Location _oustLoc = null;
protected int _locationId = 0;
protected VehiclePathPoint[] _arrivalPath = null;
protected VehiclePathPoint[] _departPath = null;
protected VehiclePathPoint[][] _teleportsTable = null;
protected int[] _fuelTable = null;
protected int _movieId = 0;
protected boolean _isBusy = false;
protected L2ControllableAirShipInstance _dockedShip = null;
private final Runnable _decayTask = new DecayTask();
private final Runnable _departTask = new DepartTask();
private Future<?> _departSchedule = null;
private NpcSay _arrivalMessage = null;
private static final int DEPART_INTERVAL = 300000; // 5 min
private static final int LICENSE = 13559;
private static final int STARSTONE = 13277;
private static final int SUMMON_COST = 5;
private static final SystemMessage SM_NEED_MORE = SystemMessage.getSystemMessage(SystemMessageId.AN_AIRSHIP_CANNOT_BE_SUMMONED_BECAUSE_YOU_DON_T_HAVE_ENOUGH_S1).addItemName(STARSTONE);
public AirShipController(int questId, String name, String descr)
{
super(questId, name, descr);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if ("summon".equalsIgnoreCase(event))
{
if (_dockedShip != null)
{
if (_dockedShip.isOwner(player))
{
player.sendPacket(SystemMessageId.THE_CLAN_OWNED_AIRSHIP_ALREADY_EXISTS);
}
return null;
}
if (_isBusy)
{
player.sendPacket(SystemMessageId.ANOTHER_AIRSHIP_HAS_ALREADY_BEEN_SUMMONED_PLEASE_TRY_AGAIN_LATER);
return null;
}
if (!player.hasClanPrivilege(ClanPrivilege.CL_SUMMON_AIRSHIP))
{
player.sendPacket(SystemMessageId.AIRSHIP_SUMMON_LICENSE_REGISTRATION_CAN_ONLY_BE_DONE_BY_THE_CLAN_LEADER);
return null;
}
final int ownerId = player.getClanId();
if (!AirShipManager.getInstance().hasAirShipLicense(ownerId))
{
player.sendPacket(SystemMessageId.AN_AIRSHIP_CANNOT_BE_SUMMONED_BECAUSE_EITHER_YOU_HAVE_NOT_REGISTERED_YOUR_AIRSHIP_LICENSE_OR_THE_AIRSHIP_HAS_NOT_YET_BEEN_SUMMONED);
return null;
}
if (AirShipManager.getInstance().hasAirShip(ownerId))
{
player.sendPacket(SystemMessageId.YOUR_CLAN_S_AIRSHIP_IS_ALREADY_BEING_USED_BY_ANOTHER_CLAN_MEMBER);
return null;
}
if (!player.destroyItemByItemId("AirShipSummon", STARSTONE, SUMMON_COST, npc, true))
{
player.sendPacket(SM_NEED_MORE);
return null;
}
_isBusy = true;
final L2AirShipInstance ship = AirShipManager.getInstance().getNewAirShip(_shipSpawnX, _shipSpawnY, _shipSpawnZ, _shipHeading, ownerId);
if (ship != null)
{
if (_arrivalPath != null)
{
ship.executePath(_arrivalPath);
}
if (_arrivalMessage == null)
{
_arrivalMessage = new NpcSay(npc.getObjectId(), ChatType.NPC_SHOUT, npc.getId(), NpcStringId.THE_AIRSHIP_HAS_BEEN_SUMMONED_IT_WILL_AUTOMATICALLY_DEPART_IN_5_MINUTES);
}
npc.broadcastPacket(_arrivalMessage);
}
else
{
_isBusy = false;
}
return null;
}
else if ("board".equalsIgnoreCase(event))
{
if (player.isTransformed())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_TRANSFORMED);
return null;
}
else if (player.isParalyzed())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_PETRIFIED);
return null;
}
else if (player.isDead() || player.isFakeDeath())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_DEAD);
return null;
}
else if (player.isFishing())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_FISHING);
return null;
}
else if (player.isInCombat())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_IN_BATTLE);
return null;
}
else if (player.isInDuel())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_IN_A_DUEL);
return null;
}
else if (player.isSitting())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_SITTING);
return null;
}
else if (player.isCastingNow())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_CASTING);
return null;
}
else if (player.isCursedWeaponEquipped())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHEN_A_CURSED_WEAPON_IS_EQUIPPED);
return null;
}
else if (player.isCombatFlagEquipped())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_HOLDING_A_FLAG);
return null;
}
else if (player.hasSummon() || player.isMounted())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_A_PET_OR_A_SERVITOR_IS_SUMMONED);
return null;
}
else if (player.isFlyingMounted())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_BECAUSE_YOU_DO_NOT_MEET_THE_REQUIREMENTS);
return null;
}
if (_dockedShip != null)
{
_dockedShip.addPassenger(player);
}
return null;
}
else if ("register".equalsIgnoreCase(event))
{
if ((player.getClan() == null) || (player.getClan().getLevel() < 5))
{
player.sendPacket(SystemMessageId.IN_ORDER_TO_ACQUIRE_AN_AIRSHIP_THE_CLAN_S_LEVEL_MUST_BE_LEVEL_5_OR_HIGHER);
return null;
}
if (!player.isClanLeader())
{
player.sendPacket(SystemMessageId.AIRSHIP_SUMMON_LICENSE_REGISTRATION_CAN_ONLY_BE_DONE_BY_THE_CLAN_LEADER);
return null;
}
final int ownerId = player.getClanId();
if (AirShipManager.getInstance().hasAirShipLicense(ownerId))
{
player.sendPacket(SystemMessageId.THE_AIRSHIP_SUMMON_LICENSE_HAS_ALREADY_BEEN_ACQUIRED);
return null;
}
if (!player.destroyItemByItemId("AirShipLicense", LICENSE, 1, npc, true))
{
player.sendPacket(SM_NEED_MORE);
return null;
}
AirShipManager.getInstance().registerLicense(ownerId);
player.sendPacket(SystemMessageId.THE_AIRSHIP_SUMMON_LICENSE_HAS_BEEN_ENTERED_YOUR_CLAN_CAN_NOW_SUMMON_THE_AIRSHIP);
return null;
}
else
{
return event;
}
}
@Override
public String onEnterZone(L2Character character, L2ZoneType zone)
{
if (character instanceof L2ControllableAirShipInstance)
{
if (_dockedShip == null)
{
_dockedShip = (L2ControllableAirShipInstance) character;
_dockedShip.setInDock(_dockZone);
_dockedShip.setOustLoc(_oustLoc);
// Ship is not empty - display movie to passengers and dock
if (!_dockedShip.isEmpty())
{
if (_movieId != 0)
{
for (L2PcInstance passenger : _dockedShip.getPassengers())
{
if (passenger != null)
{
passenger.showQuestMovie(_movieId);
}
}
}
ThreadPoolManager.getInstance().scheduleGeneral(_decayTask, 1000);
}
else
{
_departSchedule = ThreadPoolManager.getInstance().scheduleGeneral(_departTask, DEPART_INTERVAL);
}
}
}
return null;
}
@Override
public String onExitZone(L2Character character, L2ZoneType zone)
{
if (character instanceof L2ControllableAirShipInstance)
{
if (character.equals(_dockedShip))
{
if (_departSchedule != null)
{
_departSchedule.cancel(false);
_departSchedule = null;
}
_dockedShip.setInDock(0);
_dockedShip = null;
_isBusy = false;
}
}
return null;
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
return npc.getId() + ".htm";
}
protected void validityCheck()
{
final L2ScriptZone zone = ZoneManager.getInstance().getZoneById(_dockZone, L2ScriptZone.class);
if (zone == null)
{
_log.log(Level.WARNING, getName() + ": Invalid zone " + _dockZone + ", controller disabled");
_isBusy = true;
return;
}
VehiclePathPoint p;
if (_arrivalPath != null)
{
if (_arrivalPath.length == 0)
{
_log.log(Level.WARNING, getName() + ": Zero arrival path length.");
_arrivalPath = null;
}
else
{
p = _arrivalPath[_arrivalPath.length - 1];
if (!zone.isInsideZone(p.getLocation()))
{
_log.log(Level.WARNING, getName() + ": Arrival path finish point (" + p.getX() + "," + p.getY() + "," + p.getZ() + ") not in zone " + _dockZone);
_arrivalPath = null;
}
}
}
if (_arrivalPath == null)
{
if (!ZoneManager.getInstance().getZoneById(_dockZone, L2ScriptZone.class).isInsideZone(_shipSpawnX, _shipSpawnY, _shipSpawnZ))
{
_log.log(Level.WARNING, getName() + ": Arrival path is null and spawn point not in zone " + _dockZone + ", controller disabled");
_isBusy = true;
return;
}
}
if (_departPath != null)
{
if (_departPath.length == 0)
{
_log.log(Level.WARNING, getName() + ": Zero depart path length.");
_departPath = null;
}
else
{
p = _departPath[_departPath.length - 1];
if (zone.isInsideZone(p.getLocation()))
{
_log.log(Level.WARNING, getName() + ": Departure path finish point (" + p.getX() + "," + p.getY() + "," + p.getZ() + ") in zone " + _dockZone);
_departPath = null;
}
}
}
if (_teleportsTable != null)
{
if (_fuelTable == null)
{
_log.log(Level.WARNING, getName() + ": Fuel consumption not defined.");
}
else
{
if (_teleportsTable.length != _fuelTable.length)
{
_log.log(Level.WARNING, getName() + ": Fuel consumption not match teleport list.");
}
else
{
AirShipManager.getInstance().registerAirShipTeleportList(_dockZone, _locationId, _teleportsTable, _fuelTable);
}
}
}
}
}

View File

@@ -0,0 +1,6 @@
<html><body>Airship Controller:<br>
You see a floating piece of stone filled with a mysterious power. The green light is flashing, so there doesn't appear to be anything wrong with its function.<br>
Using this should allow you to board the Airship headed for the continent of Gracia.<br>
<a action="bypass -h Quest AirShipGludioGracia board">Board the Airship.</a><br>
<a action="bypass -h npc_%objectId%_Quest">Quest</a>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Airship Controller:<br>
You see a floating piece of stone filled with a mysterious power. The green light is flashing, so there doesn't appear to be anything wrong with its function.<br>
Using this should allow you to board the Airship headed for the continent of Gracia.<br>
<a action="bypass -h Quest AirShipGludioGracia board">Board the Airship.</a><br>
<a action="bypass -h npc_%objectId%_Quest">Quest</a>
</body></html>

View File

@@ -0,0 +1,308 @@
/*
* 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 gracia.vehicles.AirShipGludioGracia;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.instancemanager.AirShipManager;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.VehiclePathPoint;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2AirShipInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.quest.Quest;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
/**
* @author DS
*/
public final class AirShipGludioGracia extends Quest implements Runnable
{
private static final int[] CONTROLLERS =
{
32607,
32609
};
private static final int GLUDIO_DOCK_ID = 10;
private static final int GRACIA_DOCK_ID = 11;
private static final Location OUST_GLUDIO = new Location(-149379, 255246, -80);
private static final Location OUST_GRACIA = new Location(-186563, 243590, 2608);
private static final VehiclePathPoint[] GLUDIO_TO_WARPGATE =
{
new VehiclePathPoint(-151202, 252556, 231),
new VehiclePathPoint(-160403, 256144, 222),
new VehiclePathPoint(-167874, 256731, -509, 0, 41035)
// teleport: x,y,z,speed=0,heading
};
private static final VehiclePathPoint[] WARPGATE_TO_GRACIA =
{
new VehiclePathPoint(-169763, 254815, 282),
new VehiclePathPoint(-171822, 250061, 425),
new VehiclePathPoint(-172595, 247737, 398),
new VehiclePathPoint(-174538, 246185, 39),
new VehiclePathPoint(-179440, 243651, 1337),
new VehiclePathPoint(-182601, 243957, 2739),
new VehiclePathPoint(-184952, 245122, 2694),
new VehiclePathPoint(-186936, 244563, 2617)
};
private static final VehiclePathPoint[] GRACIA_TO_WARPGATE =
{
new VehiclePathPoint(-187801, 244997, 2672),
new VehiclePathPoint(-188520, 245932, 2465),
new VehiclePathPoint(-189932, 245243, 1682),
new VehiclePathPoint(-191192, 242969, 1523),
new VehiclePathPoint(-190408, 239088, 1706),
new VehiclePathPoint(-187475, 237113, 2768),
new VehiclePathPoint(-184673, 238433, 2802),
new VehiclePathPoint(-184524, 241119, 2816),
new VehiclePathPoint(-182129, 243385, 2733),
new VehiclePathPoint(-179440, 243651, 1337),
new VehiclePathPoint(-174538, 246185, 39),
new VehiclePathPoint(-172595, 247737, 398),
new VehiclePathPoint(-171822, 250061, 425),
new VehiclePathPoint(-169763, 254815, 282),
new VehiclePathPoint(-168067, 256626, 343),
new VehiclePathPoint(-157261, 255664, 221, 0, 64781)
// teleport: x,y,z,speed=0,heading
};
private static final VehiclePathPoint[] WARPGATE_TO_GLUDIO =
{
new VehiclePathPoint(-153414, 255385, 221),
new VehiclePathPoint(-149548, 258172, 221),
new VehiclePathPoint(-146884, 257097, 221),
new VehiclePathPoint(-146672, 254239, 221),
new VehiclePathPoint(-147855, 252712, 206),
new VehiclePathPoint(-149378, 252552, 198)
};
private final L2AirShipInstance _ship;
private int _cycle = 0;
private boolean _foundAtcGludio = false;
private L2Npc _atcGludio = null;
private boolean _foundAtcGracia = false;
private L2Npc _atcGracia = null;
public AirShipGludioGracia()
{
super(-1, AirShipGludioGracia.class.getSimpleName(), "gracia/vehicles");
addStartNpc(CONTROLLERS);
addFirstTalkId(CONTROLLERS);
addTalkId(CONTROLLERS);
_ship = AirShipManager.getInstance().getNewAirShip(-149378, 252552, 198, 33837);
_ship.setOustLoc(OUST_GLUDIO);
_ship.setInDock(GLUDIO_DOCK_ID);
_ship.registerEngine(this);
_ship.runEngine(60000);
}
private final void broadcastInGludio(NpcStringId npcString)
{
if (!_foundAtcGludio)
{
_foundAtcGludio = true;
_atcGludio = findController();
}
if (_atcGludio != null)
{
_atcGludio.broadcastPacket(new NpcSay(_atcGludio.getObjectId(), ChatType.NPC_SHOUT, _atcGludio.getId(), npcString));
}
}
private final void broadcastInGracia(NpcStringId npcStringId)
{
if (!_foundAtcGracia)
{
_foundAtcGracia = true;
_atcGracia = findController();
}
if (_atcGracia != null)
{
_atcGracia.broadcastPacket(new NpcSay(_atcGracia.getObjectId(), ChatType.NPC_SHOUT, _atcGracia.getId(), npcStringId));
}
}
private final L2Npc findController()
{
// check objects around the ship
for (L2Object obj : L2World.getInstance().getVisibleObjects(_ship, 600))
{
if (obj.isNpc())
{
for (int id : CONTROLLERS)
{
if (obj.getId() == id)
{
return (L2Npc) obj;
}
}
}
}
return null;
}
@Override
public final String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (player.isTransformed())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_TRANSFORMED);
return null;
}
else if (player.isParalyzed())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_PETRIFIED);
return null;
}
else if (player.isDead() || player.isFakeDeath())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_DEAD);
return null;
}
else if (player.isFishing())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_FISHING);
return null;
}
else if (player.isInCombat())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_IN_BATTLE);
return null;
}
else if (player.isInDuel())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_IN_A_DUEL);
return null;
}
else if (player.isSitting())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_SITTING);
return null;
}
else if (player.isCastingNow())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_CASTING);
return null;
}
else if (player.isCursedWeaponEquipped())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHEN_A_CURSED_WEAPON_IS_EQUIPPED);
return null;
}
else if (player.isCombatFlagEquipped())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_HOLDING_A_FLAG);
return null;
}
else if (player.hasSummon() || player.isMounted())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_BOARD_AN_AIRSHIP_WHILE_A_PET_OR_A_SERVITOR_IS_SUMMONED);
return null;
}
else if (_ship.isInDock() && _ship.isInsideRadius(player, 600, true, false))
{
_ship.addPassenger(player);
}
return null;
}
@Override
public final String onFirstTalk(L2Npc npc, L2PcInstance player)
{
return npc.getId() + ".htm";
}
@Override
public void run()
{
try
{
switch (_cycle)
{
case 0:
broadcastInGludio(NpcStringId.THE_REGULARLY_SCHEDULED_AIRSHIP_THAT_FLIES_TO_THE_GRACIA_CONTINENT_HAS_DEPARTED);
_ship.setInDock(0);
_ship.executePath(GLUDIO_TO_WARPGATE);
break;
case 1:
// _ship.teleToLocation(-167874, 256731, -509, 41035, false);
_ship.setOustLoc(OUST_GRACIA);
ThreadPoolManager.getInstance().scheduleGeneral(this, 5000);
break;
case 2:
_ship.executePath(WARPGATE_TO_GRACIA);
break;
case 3:
broadcastInGracia(NpcStringId.THE_REGULARLY_SCHEDULED_AIRSHIP_HAS_ARRIVED_IT_WILL_DEPART_FOR_THE_ADEN_CONTINENT_IN_1_MINUTE);
_ship.setInDock(GRACIA_DOCK_ID);
_ship.oustPlayers();
ThreadPoolManager.getInstance().scheduleGeneral(this, 60000);
break;
case 4:
broadcastInGracia(NpcStringId.THE_REGULARLY_SCHEDULED_AIRSHIP_THAT_FLIES_TO_THE_ADEN_CONTINENT_HAS_DEPARTED);
_ship.setInDock(0);
_ship.executePath(GRACIA_TO_WARPGATE);
break;
case 5:
// _ship.teleToLocation(-157261, 255664, 221, 64781, false);
_ship.setOustLoc(OUST_GLUDIO);
ThreadPoolManager.getInstance().scheduleGeneral(this, 5000);
break;
case 6:
_ship.executePath(WARPGATE_TO_GLUDIO);
break;
case 7:
broadcastInGludio(NpcStringId.THE_REGULARLY_SCHEDULED_AIRSHIP_HAS_ARRIVED_IT_WILL_DEPART_FOR_THE_GRACIA_CONTINENT_IN_1_MINUTE);
_ship.setInDock(GLUDIO_DOCK_ID);
_ship.oustPlayers();
ThreadPoolManager.getInstance().scheduleGeneral(this, 60000);
break;
}
_cycle++;
if (_cycle > 7)
{
_cycle = 0;
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public boolean unload(boolean removeFromList)
{
if (_ship != null)
{
_ship.oustPlayers();
_ship.deleteMe();
}
return super.unload(removeFromList);
}
}

View File

@@ -0,0 +1,8 @@
<html><body>Airship Controller:<br>
You see a floating piece of stone filled with a mysterious power. The green light is flashing, so there doesn't appear to be anything wrong with its function.<br><br>
By manipulating this, you should be able to control the Airship.<br>
<a action="bypass -h Quest KeucereusNorthController board">Board the Airship.</a><br>
<a action="bypass -h Quest KeucereusNorthController summon">Summon the Airship.</a><br>
<a action="bypass -h Quest KeucereusNorthController register">Register summoning license.</a><br>
<a action="bypass -h npc_%objectId%_Quest">Quest</a>
</body></html>

View File

@@ -0,0 +1,95 @@
/*
* 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 gracia.vehicles.KeucereusNorthController;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.VehiclePathPoint;
import gracia.vehicles.AirShipController;
public final class KeucereusNorthController extends AirShipController
{
private static final int DOCK_ZONE = 50602;
private static final int LOCATION = 100;
private static final int CONTROLLER_ID = 32606;
private static final VehiclePathPoint[] ARRIVAL =
{
new VehiclePathPoint(-183218, 239494, 2500, 280, 2000),
new VehiclePathPoint(-183218, 239494, 1336, 280, 2000)
};
private static final VehiclePathPoint[] DEPART =
{
new VehiclePathPoint(-183218, 239494, 1700, 280, 2000),
new VehiclePathPoint(-181974, 235358, 1700, 280, 2000)
};
private static final VehiclePathPoint[][] TELEPORTS =
{
{
new VehiclePathPoint(-183218, 239494, 1700, 280, 2000),
new VehiclePathPoint(-181974, 235358, 1700, 280, 2000),
new VehiclePathPoint(-186373, 234000, 2500, 0, 0)
},
{
new VehiclePathPoint(-183218, 239494, 1700, 280, 2000),
new VehiclePathPoint(-181974, 235358, 1700, 280, 2000),
new VehiclePathPoint(-206692, 220997, 3000, 0, 0)
},
{
new VehiclePathPoint(-183218, 239494, 1700, 280, 2000),
new VehiclePathPoint(-181974, 235358, 1700, 280, 2000),
new VehiclePathPoint(-235693, 248843, 5100, 0, 0)
}
};
private static final int[] FUEL =
{
0,
50,
100
};
public KeucereusNorthController()
{
super(-1, KeucereusNorthController.class.getSimpleName(), "gracia/vehicles");
addStartNpc(CONTROLLER_ID);
addFirstTalkId(CONTROLLER_ID);
addTalkId(CONTROLLER_ID);
_dockZone = DOCK_ZONE;
addEnterZoneId(DOCK_ZONE);
addExitZoneId(DOCK_ZONE);
_shipSpawnX = -184145;
_shipSpawnY = 242373;
_shipSpawnZ = 3000;
_oustLoc = new Location(-183900, 239384, 1320);
_locationId = LOCATION;
_arrivalPath = ARRIVAL;
_departPath = DEPART;
_teleportsTable = TELEPORTS;
_fuelTable = FUEL;
_movieId = 1001;
validityCheck();
}
}

View File

@@ -0,0 +1,8 @@
<html><body>Airship Controller:<br>
You see a floating piece of stone filled with a mysterious power. The green light is flashing, so there doesn't appear to be anything wrong with its function.<br><br>
By manipulating this, you should be able to control the Airship.<br>
<a action="bypass -h Quest KeucereusSouthController board">Board the Airship.</a><br>
<a action="bypass -h Quest KeucereusSouthController summon">Summon the Airship.</a><br>
<a action="bypass -h Quest KeucereusSouthController register">Register summoning license.</a><br>
<a action="bypass -h npc_%objectId%_Quest">Quest</a>
</body></html>

View File

@@ -0,0 +1,95 @@
/*
* 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 gracia.vehicles.KeucereusSouthController;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.VehiclePathPoint;
import gracia.vehicles.AirShipController;
public final class KeucereusSouthController extends AirShipController
{
private static final int DOCK_ZONE = 50603;
private static final int LOCATION = 100;
private static final int CONTROLLER_ID = 32517;
private static final VehiclePathPoint[] ARRIVAL =
{
new VehiclePathPoint(-185312, 246544, 2500),
new VehiclePathPoint(-185312, 246544, 1336)
};
private static final VehiclePathPoint[] DEPART =
{
new VehiclePathPoint(-185312, 246544, 1700, 280, 2000),
new VehiclePathPoint(-186900, 251699, 1700, 280, 2000)
};
private static final VehiclePathPoint[][] TELEPORTS =
{
{
new VehiclePathPoint(-185312, 246544, 1700, 280, 2000),
new VehiclePathPoint(-186900, 251699, 1700, 280, 2000),
new VehiclePathPoint(-186373, 234000, 2500, 0, 0)
},
{
new VehiclePathPoint(-185312, 246544, 1700, 280, 2000),
new VehiclePathPoint(-186900, 251699, 1700, 280, 2000),
new VehiclePathPoint(-206692, 220997, 3000, 0, 0)
},
{
new VehiclePathPoint(-185312, 246544, 1700, 280, 2000),
new VehiclePathPoint(-186900, 251699, 1700, 280, 2000),
new VehiclePathPoint(-235693, 248843, 5100, 0, 0)
}
};
private static final int[] FUEL =
{
0,
50,
100
};
public KeucereusSouthController()
{
super(-1, KeucereusSouthController.class.getSimpleName(), "gracia/vehicles");
addStartNpc(CONTROLLER_ID);
addFirstTalkId(CONTROLLER_ID);
addTalkId(CONTROLLER_ID);
_dockZone = DOCK_ZONE;
addEnterZoneId(DOCK_ZONE);
addExitZoneId(DOCK_ZONE);
_shipSpawnX = -184527;
_shipSpawnY = 243611;
_shipSpawnZ = 3000;
_locationId = LOCATION;
_arrivalPath = ARRIVAL;
_departPath = DEPART;
_teleportsTable = TELEPORTS;
_fuelTable = FUEL;
_oustLoc = new Location(-186148, 246296, 1360);
_movieId = 1000;
validityCheck();
}
}

View File

@@ -0,0 +1,7 @@
<html><body>Airship Controller:<br>
You see a floating piece of stone filled with a mysterious power. The green light is flashing, so there doesn't appear to be anything wrong with its function.<br><br>
By manipulating this, you should be able to control the Airship.<br>
<a action="bypass -h Quest SoDController board">Board the Airship.</a><br>
<a action="bypass -h Quest SoDController summon">Summon the Airship.</a><br>
<a action="bypass -h npc_%objectId%_Quest">Quest</a>
</body></html>

View File

@@ -0,0 +1,85 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gracia.vehicles.SoDController;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.VehiclePathPoint;
import gracia.vehicles.AirShipController;
public final class SoDController extends AirShipController
{
private static final int DOCK_ZONE = 50601;
private static final int LOCATION = 102;
private static final int CONTROLLER_ID = 32605;
private static final VehiclePathPoint[] ARRIVAL =
{
new VehiclePathPoint(-246445, 252331, 4359, 280, 2000),
};
private static final VehiclePathPoint[] DEPART =
{
new VehiclePathPoint(-245245, 251040, 4359, 280, 2000)
};
private static final VehiclePathPoint[][] TELEPORTS =
{
{
new VehiclePathPoint(-245245, 251040, 4359, 280, 2000),
new VehiclePathPoint(-235693, 248843, 5100, 0, 0)
},
{
new VehiclePathPoint(-245245, 251040, 4359, 280, 2000),
new VehiclePathPoint(-195357, 233430, 2500, 0, 0)
}
};
private static final int[] FUEL =
{
0,
100
};
public SoDController()
{
super(-1, SoDController.class.getSimpleName(), "gracia/vehicles");
addStartNpc(CONTROLLER_ID);
addFirstTalkId(CONTROLLER_ID);
addTalkId(CONTROLLER_ID);
_dockZone = DOCK_ZONE;
addEnterZoneId(DOCK_ZONE);
addExitZoneId(DOCK_ZONE);
_shipSpawnX = -247702;
_shipSpawnY = 253631;
_shipSpawnZ = 4359;
_oustLoc = new Location(-247746, 251079, 4328);
_locationId = LOCATION;
_arrivalPath = ARRIVAL;
_departPath = DEPART;
_teleportsTable = TELEPORTS;
_fuelTable = FUEL;
_movieId = 1003;
validityCheck();
}
}

View File

@@ -0,0 +1,7 @@
<html><body>Airship Controller:<br>
You see a floating piece of stone filled with a mysterious power. The green light is flashing, so there doesn't appear to be anything wrong with its function.<br><br>
By manipulating this, you should be able to control the Airship.<br>
<a action="bypass -h Quest SoIController board">Board the Airship.</a><br>
<a action="bypass -h Quest SoIController summon">Summon the Airship.</a><br>
<a action="bypass -h npc_%objectId%_Quest">Quest</a>
</body></html>

View File

@@ -0,0 +1,89 @@
/*
* 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 gracia.vehicles.SoIController;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.VehiclePathPoint;
import gracia.vehicles.AirShipController;
public final class SoIController extends AirShipController
{
private static final int DOCK_ZONE = 50600;
private static final int LOCATION = 101;
private static final int CONTROLLER_ID = 32604;
private static final VehiclePathPoint[] ARRIVAL =
{
new VehiclePathPoint(-214422, 211396, 5000, 280, 2000),
new VehiclePathPoint(-214422, 211396, 4422, 280, 2000)
};
private static final VehiclePathPoint[] DEPART =
{
new VehiclePathPoint(-214422, 211396, 5000, 280, 2000),
new VehiclePathPoint(-215877, 209709, 5000, 280, 2000)
};
private static final VehiclePathPoint[][] TELEPORTS =
{
{
new VehiclePathPoint(-214422, 211396, 5000, 280, 2000),
new VehiclePathPoint(-215877, 209709, 5000, 280, 2000),
new VehiclePathPoint(-206692, 220997, 3000, 0, 0)
},
{
new VehiclePathPoint(-214422, 211396, 5000, 280, 2000),
new VehiclePathPoint(-215877, 209709, 5000, 280, 2000),
new VehiclePathPoint(-195357, 233430, 2500, 0, 0)
}
};
private static final int[] FUEL =
{
0,
50
};
public SoIController()
{
super(-1, SoIController.class.getSimpleName(), "gracia/vehicles");
addStartNpc(CONTROLLER_ID);
addFirstTalkId(CONTROLLER_ID);
addTalkId(CONTROLLER_ID);
_dockZone = DOCK_ZONE;
addEnterZoneId(DOCK_ZONE);
addExitZoneId(DOCK_ZONE);
_shipSpawnX = -212719;
_shipSpawnY = 213348;
_shipSpawnZ = 5000;
_oustLoc = new Location(-213401, 210401, 4408);
_locationId = LOCATION;
_arrivalPath = ARRIVAL;
_departPath = DEPART;
_teleportsTable = TELEPORTS;
_fuelTable = FUEL;
_movieId = 1002;
validityCheck();
}
}