actual freya branch

This commit is contained in:
2026-09-12 15:39:57 +00:00
parent 9fa534b20e
commit 8049e0a882
18540 changed files with 1228200 additions and 0 deletions
@@ -0,0 +1,7 @@
<html><body>Oracle Guide:<br>
Brilliant five-colored light shines forth from an aquamarine sphere. You hear a loud, dear voice:<br>
Welcome, you who have accomplished the test of the Oracle. Your contributions have led to the downfall of the Demon Balor.<br>
I am the last child of the Oracle, whose mission it is to escort you safely to the place where Parme is being kept. She is still under an evil influence, but the object you carry has the power to heal her.<br>
If you are ready to meet the priests of the Water Dragon, give me your hand.<br>
<a action="bypass -h Quest CrystalCaverns TeleportParme">Go to meet Parme.</a>
</body></html>
@@ -0,0 +1,4 @@
<html><body>Oracle Guide:<br>
Baylor is dead!<br>
<a action="bypass -h Quest CrystalCaverns TeleportOut">Let me out!</a>
</body></html>
@@ -0,0 +1,4 @@
<html><body>[You feel a chill and hear a voice...]<br>
<a action="bypass -h Quest CrystalCaverns CoralGarden">Run Coral Garden.</a><br>
<a action="bypass -h Quest CrystalCaverns EmeraldSteam">Run Emerald Square/Steam Corridor</a>
</body></html>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,3 @@
<html><body>Oracle Guide:<br>
I can't speak with you, while bleeding.
</body></html>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,6 @@
<html><body>Captain Lucas:<br>
What? You want to enter Kamaloka?<br>
<a action="bypass -h Quest Kamaloka 3">Enter Kamaloka, Hall of the Abyss (level 33).</a><br>
<a action="bypass -h Quest Kamaloka 4">Enter Kamaloka, Hall of the Abyss (level 36).</a><br>
<a action="bypass -h Quest Kamaloka 5">Enter Kamaloka, Labyrinth of the Abyss (level 39).</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Captain Mouen:<br>
Hmm? Do you wish to enter Kamaloka?<br>
<a action="bypass -h Quest Kamaloka 9">Enter Kamaloka, Hall of the Abyss (level 53).</a><br>
<a action="bypass -h Quest Kamaloka 10">Enter Kamaloka, Hall of the Abyss (level 56).</a><br>
<a action="bypass -h Quest Kamaloka 11">Enter Kamaloka, Labyrinth of the Abyss (level 59).</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Captain Bathis:<br>
Hmm? Do you wish to enter Kamaloka?<br>
<a action="bypass -h Quest Kamaloka 0">Enter Kamaloka, Hall of the Abyss (level 23).</a><br>
<a action="bypass -h Quest Kamaloka 1">Enter Kamaloka, Hall of the Abyss (level 26).</a><br>
<a action="bypass -h Quest Kamaloka 2">Enter Kamaloka, Labyrinth of the Abyss (level 29).</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Captain Gosta:<br>
What? You want to enter Kamaloka?<br>
<a action="bypass -h Quest Kamaloka 6">Enter Kamaloka, Hall of the Abyss (level 43).</a><br>
<a action="bypass -h Quest Kamaloka 7">Enter Kamaloka, Hall of the Abyss (level 46).</a><br>
<a action="bypass -h Quest Kamaloka 8">Enter Kamaloka, Labyrinth of the Abyss (level 49).</a>
</body></html>
@@ -0,0 +1,7 @@
<html><body>Captain Mathias:<br>
What? You want to enter Kamaloka?<br>
<a action="bypass -h Quest Kamaloka 15">Enter Kamaloka, Hall of the Abyss (level 73).</a><br>
<a action="bypass -h Quest Kamaloka 16">Enter Kamaloka, Labyrinth of the Abyss (level 78).</a><br>
<a action="bypass -h Quest Kamaloka 17">Enter Kamaloka, Labyrinth of the Abyss (level 81).</a><br>
<a action="bypass -h Quest Kamaloka 18">Enter Kamaloka, Labyrinth of the Abyss (level 83).</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Captain Vishotsky:<br>
Hmm? Do you wish to enter Kamaloka? Know that by doing so, you will be risking your life!<br>
<a action="bypass -h Quest Kamaloka 12">Enter Kamaloka, Hall of the Abyss (level 63).</a><br>
<a action="bypass -h Quest Kamaloka 13">Enter Kamaloka, Hall of the Abyss (level 66).</a><br>
<a action="bypass -h Quest Kamaloka 14">Enter Kamaloka, Labyrinth of the Abyss (level 69).</a>
</body></html>
@@ -0,0 +1 @@
<html><body>Gatekeeper:<br>You are not a party leader.</body></html>
@@ -0,0 +1,4 @@
<html><body>Gatekeeper:<br>
Would you like to leave Kamaloka - Labyrinth of the Abyss?<br>
<a action="bypass -h npc_%objectId%_Quest Kamaloka">Leave</a>
</body></html>
@@ -0,0 +1,956 @@
package instances.Kamaloka;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.SkillTable;
import com.l2jserver.gameserver.instancemanager.InstanceManager;
import com.l2jserver.gameserver.instancemanager.InstanceManager.InstanceWorld;
import com.l2jserver.gameserver.model.L2Effect;
import com.l2jserver.gameserver.model.L2Party;
import com.l2jserver.gameserver.model.L2Skill;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Instance;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.Rnd;
public class Kamaloka extends Quest
{
private static String qn = "Kamaloka";
/*
* Reset time for all kamaloka
* Default: 6:30AM on server time
*/
private static final int RESET_HOUR = 6;
private static final int RESET_MIN = 30;
/*
* Time after which instance without players will be destroyed
* Default: 5 minutes
*/
private static final int EMPTY_DESTROY_TIME = 5;
/*
* Time to destroy instance (and eject players away) after boss defeat
* Default: 5 minutes
*/
private static final int EXIT_TIME = 5;
/*
* Maximum level difference between players level and kamaloka level
* Default: 5
*/
private static final int MAX_LEVEL_DIFFERENCE = 5;
/*
* If true shaman in the first room will have same npcId as other mobs, making radar useless
* Default: true (but not retail like)
*/
private static final boolean STEALTH_SHAMAN = true;
/*
* Hardcoded instance ids for kamaloka
*/
private static final int[] INSTANCE_IDS =
{ 57, 58, 73, 60, 61, 74, 63, 64, 75, 66, 67, 76, 69, 70, 77, 72, 78, 79, 134 };
/*
* Level of the kamaloka
*/
private static final int[] LEVEL =
{ 23, 26, 29, 33, 36, 39, 43, 46, 49, 53, 56, 59, 63, 66, 69, 73, 78, 81, 83 };
/*
* Duration of the instance, minutes
*/
private static final int[] DURATION =
{ 30, 30, 45, 30, 30, 45, 30, 30, 45, 30, 30, 45, 30, 30, 45, 30, 45, 45, 45 };
/*
* Maximum party size for the instance
*/
private static final int[] MAX_PARTY_SIZE =
{ 6, 6, 9, 6, 6, 9, 6, 6, 9, 6, 6, 9, 6, 6, 9, 6, 9, 9, 9 };
/*
* List of buffs NOT removed on enter from player and pet
* On retail only newbie guide buffs not removed
* CAUTION: array must be sorted in ascension order !
*/
private static final int[] BUFFS_WHITELIST =
{ 5627, 5628, 5629, 5630, 5631, 5632, 5633, 5634, 5635, 5636, 5637, 5950 };
/*
* Teleport points into instances
*
* x, y, z
*/
private static final int[][] TELEPORTS =
{
{ -88429, -220629, -7903 },
{ -82464, -219532, -7899 },
{ -10700, -174882, -10936 }, // -76280, -185540, -10936
{ -89683, -213573, -8106 },
{ -81413, -213568, -8104 },
{ -10700, -174882, -10936 }, // -76280, -174905, -10936
{ -89759, -206143, -8120 },
{ -81415, -206078, -8107 },
{ -10700, -174882, -10936 },
{ -56999, -219856, -8117 },
{ -48794, -220261, -8075 },
{ -10700, -174882, -10936 },
{ -56940, -212939, -8072 },
{ -55566, -206139, -8120 },
{ -10700, -174882, -10936 },
{ -49805, -206139, -8117 },
{ -10700, -174882, -10936 },
{ -10700, -174882, -10936 },
{ 22010, -174867, -10904 }
};
/*
* Respawn delay for the mobs in the first room, seconds
* Default: 25
*/
private static final int FIRST_ROOM_RESPAWN_DELAY = 25;
/*
* First room information, null if room not spawned
* Skill is casted on the boss when shaman is defeated and mobs respawn stopped
* Default: 5699 (decrease pdef)
*
* shaman npcId, minions npcId, skillId, skillLvl
*/
private static final int[][] FIRST_ROOM =
{
null, null,
{ 22485, 22486, 5699, 1 },
null, null,
{ 22488, 22489, 5699, 2 },
null, null,
{ 22491, 22492, 5699, 3 },
null, null,
{ 22494, 22495, 5699, 4 },
null, null,
{ 22497, 22498, 5699, 5 },
null,
{ 22500, 22501, 5699, 6 },
{ 22503, 22504, 5699, 7 },
{ 25706, 25707, 5699, 7 }
};
/*
* First room spawns, null if room not spawned
*
* x, y, z
*/
private static final int[][][] FIRST_ROOM_SPAWNS =
{
null, null,
{
{ -12381, -174973, -10955 }, { -12413, -174905, -10955 },
{ -12377, -174838, -10953 }, { -12316, -174903, -10953 },
{ -12326, -174786, -10953 }, { -12330, -175024, -10953 },
{ -12211, -174900, -10955 }, { -12238, -174849, -10953 },
{ -12233, -174954, -10953 }
},
null, null,
{
{ -12381, -174973, -10955 }, { -12413, -174905, -10955 },
{ -12377, -174838, -10953 }, { -12316, -174903, -10953 },
{ -12326, -174786, -10953 }, { -12330, -175024, -10953 },
{ -12211, -174900, -10955 }, { -12238, -174849, -10953 },
{ -12233, -174954, -10953 }
},
null, null,
{
{ -12381, -174973, -10955 }, { -12413, -174905, -10955 },
{ -12377, -174838, -10953 }, { -12316, -174903, -10953 },
{ -12326, -174786, -10953 }, { -12330, -175024, -10953 },
{ -12211, -174900, -10955 }, { -12238, -174849, -10953 },
{ -12233, -174954, -10953 }
},
null, null,
{
{ -12381, -174973, -10955 }, { -12413, -174905, -10955 },
{ -12377, -174838, -10953 }, { -12316, -174903, -10953 },
{ -12326, -174786, -10953 }, { -12330, -175024, -10953 },
{ -12211, -174900, -10955 }, { -12238, -174849, -10953 },
{ -12233, -174954, -10953 }
},
null, null,
{
{ -12381, -174973, -10955 }, { -12413, -174905, -10955 },
{ -12377, -174838, -10953 }, { -12316, -174903, -10953 },
{ -12326, -174786, -10953 }, { -12330, -175024, -10953 },
{ -12211, -174900, -10955 }, { -12238, -174849, -10953 },
{ -12233, -174954, -10953 }
},
null,
{
{ -12381, -174973, -10955 }, { -12413, -174905, -10955 },
{ -12377, -174838, -10953 }, { -12316, -174903, -10953 },
{ -12326, -174786, -10953 }, { -12330, -175024, -10953 },
{ -12211, -174900, -10955 }, { -12238, -174849, -10953 },
{ -12233, -174954, -10953 }
},
{
{ -12381, -174973, -10955 }, { -12413, -174905, -10955 },
{ -12377, -174838, -10953 }, { -12316, -174903, -10953 },
{ -12326, -174786, -10953 }, { -12330, -175024, -10953 },
{ -12211, -174900, -10955 }, { -12238, -174849, -10953 },
{ -12233, -174954, -10953 }
},
{
{ 20409, -174827, -10912 }, { 20409, -174947, -10912 },
{ 20494, -174887, -10912 }, { 20494, -174767, -10912 },
{ 20614, -174887, -10912 }, { 20579, -174827, -10912 },
{ 20579, -174947, -10912 }, { 20494, -175007, -10912 },
{ 20374, -174887, -10912 }
}
};
/*
* Second room information, null if room not spawned
* Skill is casted on the boss when all mobs are defeated
* Default: 5700 (decrease mdef)
*
* npcId, skillId, skillLvl
*/
private static final int[][] SECOND_ROOM =
{
null, null,
{ 22487, 5700, 1 },
null, null,
{ 22490, 5700, 2 },
null, null,
{ 22493, 5700, 3 },
null, null,
{ 22496, 5700, 4 },
null, null,
{ 22499, 5700, 5 },
null,
{ 22502, 5700, 6 },
{ 22505, 5700, 7 },
{ 25708, 5700, 7 }
};
/*
* Spawns for second room, null if room not spawned
*
* x, y, z
*/
private static final int[][][] SECOND_ROOM_SPAWNS =
{
null, null,
{
{ -14547, -174901, -10690 }, { -14543, -175030, -10690 },
{ -14668, -174900, -10690 }, { -14538, -174774, -10690 },
{ -14410, -174904, -10690 }
},
null, null,
{
{ -14547, -174901, -10690 }, { -14543, -175030, -10690 },
{ -14668, -174900, -10690 }, { -14538, -174774, -10690 },
{ -14410, -174904, -10690 }
},
null, null,
{
{ -14547, -174901, -10690 }, { -14543, -175030, -10690 },
{ -14668, -174900, -10690 }, { -14538, -174774, -10690 },
{ -14410, -174904, -10690 }
},
null, null,
{
{ -14547, -174901, -10690 }, { -14543, -175030, -10690 },
{ -14668, -174900, -10690 }, { -14538, -174774, -10690 },
{ -14410, -174904, -10690 }
},
null, null,
{
{ -14547, -174901, -10690 }, { -14543, -175030, -10690 },
{ -14668, -174900, -10690 }, { -14538, -174774, -10690 },
{ -14410, -174904, -10690 }
},
null,
{
{ -14547, -174901, -10690 }, { -14543, -175030, -10690 },
{ -14668, -174900, -10690 }, { -14538, -174774, -10690 },
{ -14410, -174904, -10690 }
},
{
{ -14547, -174901, -10690 }, { -14543, -175030, -10690 },
{ -14668, -174900, -10690 }, { -14538, -174774, -10690 },
{ -14410, -174904, -10690 }
},
{
{ 18175, -174991, -10653 }, { 18070, -174890, -10655 },
{ 18157, -174886, -10655 }, { 18249, -174885, -10653 },
{ 18144, -174821, -10648 }
}
};
// miniboss info
// skill is casted on the boss when miniboss is defeated
// npcId, x, y, z, skill id, skill level
/*
* Miniboss information, null if miniboss not spawned
* Skill is casted on the boss when miniboss is defeated
* Default: 5701 (decrease patk)
*
* npcId, x, y, z, skillId, skillLvl
*/
private static final int[][] MINIBOSS =
{
null, null,
{ 25616, -16874, -174900, -10427, 5701, 1 },
null, null,
{ 25617, -16874, -174900, -10427, 5701, 2 },
null, null,
{ 25618, -16874, -174900, -10427, 5701, 3 },
null, null,
{ 25619, -16874, -174900, -10427, 5701, 4 },
null, null,
{ 25620, -16874, -174900, -10427, 5701, 5 },
null,
{ 25621, -16874, -174900, -10427, 5701, 6 },
{ 25622, -16874, -174900, -10427, 5701, 7 },
{ 25709, 15828, -174885, -10384, 5701, 7 }
};
/*
* Bosses of the kamaloka
* Instance ends when boss is defeated
*
* npcId, x, y, z
*/
private static final int[][] BOSS =
{
{ 18554, -88998, -220077, -7892 },
{ 18555, -81891, -220078, -7893 },
{ 29129, -20659, -174903, -9983 },
{ 18558, -89183, -213564, -8100 },
{ 18559, -81937, -213566, -8100 },
{ 29132, -20659, -174903, -9983 },
{ 18562, -89054, -206144, -8115 },
{ 18564, -81937, -206077, -8100 },
{ 29135, -20659, -174903, -9983 },
{ 18566, -56281, -219859, -8115 },
{ 18568, -49336, -220260, -8068 },
{ 29138, -20659, -174903, -9983 },
{ 18571, -56415, -212939, -8068 },
{ 18573, -56281, -206140, -8115 },
{ 29141, -20659, -174903, -9983 },
{ 18577, -49084, -206140, -8115 },
{ 29144, -20659, -174903, -9983 },
{ 29147, -20659, -174903, -9983 },
{ 25710, 12047, -174887, -9944 }
};
/*
* Escape telepoters spawns, null if not spawned
*
* x, y, z
*/
private static final int[][] TELEPORTERS =
{
null, null,
{ -10865, -174905, -10944 },
null, null,
{ -10865, -174905, -10944 },
null, null,
{ -10865, -174905, -10944 },
null, null,
{ -10865, -174905, -10944 },
null, null,
{ -10865, -174905, -10944 },
null,
{ -10865, -174905, -10944 },
{ -10865, -174905, -10944 },
{ 21837, -174885, -10904 }
};
/*
* Escape teleporter npcId
*/
private static final int TELEPORTER = 32496;
/*
* Kamaloka captains (start npc's) npcIds.
*/
private static final int[] CAPTAINS =
{ 30332, 30071, 30916, 30196, 31981, 31340 };
private class KamaWorld extends InstanceWorld
{
public int index; // 0-18 index of the kama type in arrays
public int shaman = 0; // objectId of the shaman
public List<L2Spawn> firstRoom; // list of the spawns in the first room (excluding shaman)
public List<Integer> secondRoom;// list of objectIds mobs in the second room
public int miniBoss = 0; // objectId of the miniboss
public L2Npc boss = null; // boss
public KamaWorld()
{
}
}
/**
* Check if party with player as leader allowed to enter
*
* @param player party leader
* @param index (0-18) index of the kamaloka in arrays
*
* @return true if party allowed to enter
*/
private static final boolean checkConditions(L2PcInstance player, int index)
{
final L2Party party = player.getParty();
// player must be in party
if (party == null)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.NOT_IN_PARTY_CANT_ENTER));
return false;
}
// ...and be party leader
if (party.getLeader() != player)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ONLY_PARTY_LEADER_CAN_ENTER));
return false;
}
// party must not exceed max size for selected instance
if (party.getMemberCount() > MAX_PARTY_SIZE[index])
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.PARTY_EXCEEDED_THE_LIMIT_CANT_ENTER));
return false;
}
// get level of the instance
final int level = LEVEL[index];
// and client name
final String instanceName = InstanceManager.getInstance().getInstanceIdName(INSTANCE_IDS[index]);
Map<Integer, Long> instanceTimes;
// for each party member
for (L2PcInstance partyMember : party.getPartyMembers())
{
// player level must be in range
if (Math.abs(partyMember.getLevel() - level) > MAX_LEVEL_DIFFERENCE)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_LEVEL_REQUIREMENT_NOT_SUFFICIENT);
sm.addPcName(partyMember);
player.sendPacket(sm);
return false;
}
// player must be near party leader
if (!partyMember.isInsideRadius(player, 1000, true, true))
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_LOCATION_THAT_CANNOT_BE_ENTERED);
sm.addPcName(partyMember);
player.sendPacket(sm);
return false;
}
// get instances reenter times for player
instanceTimes = InstanceManager.getInstance().getAllInstanceTimes(partyMember.getObjectId());
if (instanceTimes != null)
{
for (int id : instanceTimes.keySet())
{
// find instance with same name (kamaloka or labyrinth)
if (!instanceName.equals(InstanceManager.getInstance().getInstanceIdName(id)))
continue;
// if found instance still can't be reentered - exit
if (System.currentTimeMillis() < instanceTimes.get(id))
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_MAY_NOT_REENTER_YET);
sm.addPcName(partyMember);
player.sendPacket(sm);
return false;
}
}
}
}
return true;
}
/**
* Removing all buffs from player and pet except BUFFS_WHITELIST
*
* @param ch player
*/
private static final void removeBuffs(L2Character ch)
{
for (L2Effect e : ch.getAllEffects())
{
if (e == null)
continue;
L2Skill skill = e.getSkill();
if (skill.isDebuff() || skill.isStayAfterDeath())
continue;
if (Arrays.binarySearch(BUFFS_WHITELIST, skill.getId()) >= 0)
continue;
e.exit();
}
if (ch.getPet() != null)
{
for (L2Effect e : ch.getPet().getAllEffects())
{
if (e == null)
continue;
L2Skill skill = e.getSkill();
if (skill.isDebuff() || skill.isStayAfterDeath())
continue;
if (Arrays.binarySearch(BUFFS_WHITELIST, skill.getId()) >= 0)
continue;
e.exit();
}
}
}
/**
* Teleport player and pet to/from instance
*
* @param player
* @param coords x,y,z
* @param instanceId
*/
private static final void teleportPlayer(L2PcInstance player, int[] coords, int instanceId)
{
player.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
player.setInstanceId(instanceId);
player.teleToLocation(coords[0], coords[1], coords[2], true);
}
/**
* Handling enter of the players into kamaloka
*
* @param player party leader
* @param index (0-18) kamaloka index in arrays
*/
private final synchronized void enterInstance(L2PcInstance player, int index)
{
int templateId;
try
{
templateId = INSTANCE_IDS[index];
}
catch (ArrayIndexOutOfBoundsException e)
{
throw e;
}
// check for existing instances for this player
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
// player already in the instance
if (world != null)
{
// but not in kamaloka
if (!(world instanceof KamaWorld)
|| world.templateId != templateId)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ALREADY_ENTERED_ANOTHER_INSTANCE_CANT_ENTER));
return;
}
// check for level difference again on reenter
if (Math.abs(player.getLevel() - LEVEL[((KamaWorld)world).index]) > MAX_LEVEL_DIFFERENCE)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_LEVEL_REQUIREMENT_NOT_SUFFICIENT);
sm.addPcName(player);
player.sendPacket(sm);
return;
}
// check what instance still exist
Instance inst = InstanceManager.getInstance().getInstance(world.instanceId);
if (inst != null)
{
removeBuffs(player);
teleportPlayer(player, TELEPORTS[index], world.instanceId);
}
return;
}
// Creating new kamaloka instance
else
{
if (!checkConditions(player, index))
return;
// Creating dynamic instance without template
final int instanceId = InstanceManager.getInstance().createDynamicInstance(null);
final Instance inst = InstanceManager.getInstance().getInstance(instanceId);
// set name for the kamaloka
inst.setName(InstanceManager.getInstance().getInstanceIdName(templateId));
// set return location
final int[] returnLoc = { player.getX(), player.getY(), player.getZ() };
inst.setSpawnLoc(returnLoc);
// disable summon friend into instance
inst.setAllowSummon(false);
// set duration and empty destroy time
inst.setDuration(DURATION[index] * 60000);
inst.setEmptyDestroyTime(EMPTY_DESTROY_TIME * 60000);
// Creating new instanceWorld, using our instanceId and templateId
world = new KamaWorld();
world.instanceId = instanceId;
world.templateId = templateId;
// set index for easy access to the arrays
((KamaWorld)world).index = index;
InstanceManager.getInstance().addWorld(world);
world.status = 0;
// spawn npcs
spawnKama((KamaWorld)world);
// and finally teleport party into instance
final L2Party party = player.getParty();
for (L2PcInstance partyMember : party.getPartyMembers())
{
if (partyMember.getQuestState(qn) == null)
newQuestState(partyMember);
world.allowed.add(partyMember.getObjectId());
removeBuffs(partyMember);
teleportPlayer(partyMember, TELEPORTS[index], instanceId);
}
return;
}
}
/**
* Called on instance finish and handles reenter time for instance
* @param world instanceWorld
*/
private static final void finishInstance(InstanceWorld world)
{
if (world instanceof KamaWorld)
{
Calendar reenter = Calendar.getInstance();
reenter.set(Calendar.MINUTE, RESET_MIN);
// if time is >= RESET_HOUR - roll to the next day
if (reenter.get(Calendar.HOUR_OF_DAY) >= RESET_HOUR)
reenter.add(Calendar.DATE, 1);
reenter.set(Calendar.HOUR_OF_DAY, RESET_HOUR);
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.INSTANT_ZONE_S1_RESTRICTED);
sm.addString(InstanceManager.getInstance().getInstanceIdName(world.templateId));
// set instance reenter time for all allowed players
for (int objectId : world.allowed)
{
L2PcInstance obj = L2World.getInstance().getPlayer(objectId);
if (obj != null && obj.isOnline())
{
InstanceManager.getInstance().setInstanceTime(objectId, world.templateId, reenter.getTimeInMillis());
obj.sendPacket(sm);
}
}
// destroy instance after EXIT_TIME
Instance inst = InstanceManager.getInstance().getInstance(world.instanceId);
inst.setDuration(EXIT_TIME * 60000);
inst.setEmptyDestroyTime(0);
}
}
/**
* Spawn all NPCs in kamaloka
* @param world instanceWorld
*/
@SuppressWarnings("all")
private final void spawnKama(KamaWorld world)
{
int[] npcs;
int[][] spawns;
L2Npc npc;
final int index = world.index;
// first room
npcs = FIRST_ROOM[index];
spawns = FIRST_ROOM_SPAWNS[index];
if (npcs != null)
{
world.firstRoom = new ArrayList<L2Spawn>(spawns.length - 1);
int shaman = Rnd.get(spawns.length); // random position for shaman
for (int i = 0; i < spawns.length; i++)
{
if (i == shaman)
{
// stealth shaman use same npcId as other mobs
npc = addSpawn(STEALTH_SHAMAN ? npcs[1] : npcs[0], spawns[i][0], spawns[i][1], spawns[i][2], 0, false, 0, false, world.instanceId);
world.shaman = npc.getObjectId();
}
else
{
npc = addSpawn(npcs[1], spawns[i][0], spawns[i][1], spawns[i][2], 0, false, 0, false, world.instanceId);
L2Spawn spawn = npc.getSpawn();
spawn.setRespawnDelay(FIRST_ROOM_RESPAWN_DELAY);
spawn.setAmount(1);
spawn.startRespawn();
world.firstRoom.add(spawn); //store mobs spawns
}
npc.setIsNoRndWalk(true);
}
}
// second room
npcs = SECOND_ROOM[index];
spawns = SECOND_ROOM_SPAWNS[index];
if (npcs != null)
{
world.secondRoom = new ArrayList<Integer>(spawns.length);
for (int i = 0; i < spawns.length; i++)
{
npc = addSpawn(npcs[0], spawns[i][0], spawns[i][1], spawns[i][2], 0, false, 0, false, world.instanceId);
npc.setIsNoRndWalk(true);
world.secondRoom.add(npc.getObjectId());
}
}
// miniboss
if (MINIBOSS[index] != null)
{
npc = addSpawn(MINIBOSS[index][0], MINIBOSS[index][1], MINIBOSS[index][2], MINIBOSS[index][3], 0, false, 0, false, world.instanceId);
npc.setIsNoRndWalk(true);
world.miniBoss = npc.getObjectId();
}
// escape teleporter
if (TELEPORTERS[index] != null)
addSpawn(TELEPORTER, TELEPORTERS[index][0], TELEPORTERS[index][1], TELEPORTERS[index][2], 0, false, 0, false, world.instanceId);
// boss
npc = addSpawn(BOSS[index][0], BOSS[index][1], BOSS[index][2], BOSS[index][3], 0, false, 0, false, world.instanceId);
((L2MonsterInstance)npc).setOnKillDelay(100);
world.boss = npc;
}
/**
* Handles only player's enter, single parameter - integer kamaloka index
*/
@Override
public final String onAdvEvent (String event, L2Npc npc, L2PcInstance player)
{
if (npc == null)
return "";
try
{
enterInstance(player, Integer.parseInt(event));
}
catch (Exception e)
{
_log.log(Level.WARNING, "", e);
}
return "";
}
/**
* Talk with captains and using of the escape teleporter
*/
@Override
public final String onTalk(L2Npc npc, L2PcInstance player)
{
QuestState st = player.getQuestState(qn);
if (st == null)
newQuestState(player);
final int npcId = npc.getNpcId();
if (npcId == TELEPORTER)
{
final L2Party party = player.getParty();
// only party leader can talk with escape teleporter
if (party != null && party.isLeader(player))
{
final InstanceWorld world = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (world instanceof KamaWorld)
{
// party members must be in the instance
if (world.allowed.contains(player.getObjectId()))
{
Instance inst = InstanceManager.getInstance().getInstance(world.instanceId);
// teleports entire party away
for (L2PcInstance partyMember : party.getPartyMembers())
if (partyMember != null && partyMember.getInstanceId() == world.instanceId)
teleportPlayer(partyMember, inst.getSpawnLoc(), 0);
}
}
}
}
else
return npcId + ".htm";
return "";
}
/**
* Only escape teleporters first talk handled
*/
@Override
public final String onFirstTalk (L2Npc npc, L2PcInstance player)
{
if (npc.getNpcId() == TELEPORTER)
{
if (player.isInParty() && player.getParty().isLeader(player))
return "32496.htm";
else
return "32496-no.htm";
}
return "";
}
@Override
public final String onKill(L2Npc npc, L2PcInstance player, boolean isPet)
{
final InstanceWorld tmpWorld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpWorld instanceof KamaWorld)
{
final KamaWorld world = (KamaWorld)tmpWorld;
final int objectId = npc.getObjectId();
// first room was spawned ?
if (world.firstRoom != null)
{
// is shaman killed ?
if (world.shaman != 0 && world.shaman == objectId)
{
world.shaman = 0;
// stop respawn of the minions
for (L2Spawn spawn : world.firstRoom)
{
if (spawn != null)
spawn.stopRespawn();
}
world.firstRoom.clear();
world.firstRoom = null;
if (world.boss != null)
{
final int skillId = FIRST_ROOM[world.index][2];
final int skillLvl = FIRST_ROOM[world.index][3];
if (skillId != 0 && skillLvl != 0)
{
final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);
if (skill != null)
skill.getEffects(world.boss, world.boss);
}
}
return super.onKill(npc, player, isPet);
}
}
// second room was spawned ?
if (world.secondRoom != null)
{
boolean all = true;
// check for all mobs in the second room
for (int i = 0; i < world.secondRoom.size(); i++)
{
// found killed now mob
if (world.secondRoom.get(i) == objectId)
world.secondRoom.set(i, 0);
// found alive mob
else if (world.secondRoom.get(i) != 0)
all = false;
}
// all mobs killed ?
if (all)
{
world.secondRoom.clear();
world.secondRoom = null;
if (world.boss != null)
{
final int skillId = SECOND_ROOM[world.index][1];
final int skillLvl = SECOND_ROOM[world.index][2];
if (skillId != 0 && skillLvl != 0)
{
final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);
if (skill != null)
skill.getEffects(world.boss, world.boss);
}
}
return super.onKill(npc, player, isPet);
}
}
// miniboss spawned ?
if (world.miniBoss != 0 && world.miniBoss == objectId)
{
world.miniBoss = 0;
if (world.boss != null)
{
final int skillId = MINIBOSS[world.index][4];
final int skillLvl = MINIBOSS[world.index][5];
if (skillId != 0 && skillLvl != 0)
{
final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);
if (skill != null)
skill.getEffects(world.boss, world.boss);
}
}
return super.onKill(npc, player, isPet);
}
// boss was killed, finish instance
if (world.boss != null && world.boss == npc)
{
world.boss = null;
finishInstance(world);
}
}
return super.onKill(npc, player, isPet);
}
public Kamaloka(int questId, String name, String descr)
{
super(questId, name, descr);
addFirstTalkId(TELEPORTER);
addTalkId(TELEPORTER);
for (int cap : CAPTAINS)
{
addStartNpc(cap);
addTalkId(cap);
}
for (int[] mob : FIRST_ROOM) //shaman
if (mob != null)
if (STEALTH_SHAMAN)
addKillId(mob[1]);
else
addKillId(mob[0]);
for (int[] mob : SECOND_ROOM)
if (mob != null)
addKillId(mob[0]);
for (int[] mob : MINIBOSS)
if (mob != null)
addKillId(mob[0]);
for (int[] mob : BOSS)
addKillId(mob[0]);
}
public static void main(String[] args)
{
new Kamaloka(-1, qn, "instances");
}
}
@@ -0,0 +1,4 @@
<html><body>Past Door Control Device:<br>
You failed to enter the correct password.<br>
<a action="bypass -h Quest NornilsGarden 32260-02.html">Enter the password again.</a><br>
</body></html>
@@ -0,0 +1,4 @@
<html><body>Past Door Control Unit:<br>
Hmm... So... The password is supposed to be the same as the one for the Goddess of the Past Statue, right?<br>
<a action="bypass -h Quest NornilsGarden 32260-02.html">Enter the password.</a><br>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Past Door Control Unit:<br>
So the first letter of the password must be...<br>
<a action="bypass -h Quest NornilsGarden 32260-03.html">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-03.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 1">C</a><br>
<a action="bypass -h Quest NornilsGarden 32260-03.html">H</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-03.html">I</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-03.html">J</a><br>
<a action="bypass -h Quest NornilsGarden 32260-03.html">R</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-03.html">S</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-03.html">T</a><br>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Past Door Control Device:<br>
The second letter of the password is...<br>
<a action="bypass -h Quest NornilsGarden 32260-04.html">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-04.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-04.html">C</a><br>
<a action="bypass -h Quest NornilsGarden 32260-04.html">H</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-04.html">I</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-04.html">J</a><br>
<a action="bypass -h Quest NornilsGarden 2">R</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-04.html">S</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-04.html">T</a><br>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Past Door Control Device:<br>
The third letter of the password is...<br>
<a action="bypass -h Quest NornilsGarden 32260-05.html">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-05.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-05.html">C</a><br>
<a action="bypass -h Quest NornilsGarden 32260-05.html">H</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-05.html">I</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-05.html">J</a><br>
<a action="bypass -h Quest NornilsGarden 32260-05.html">R</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-05.html">S</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 3">T</a><br>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Past Door Control Device:<br>
The final letter of the password is...<br>
<a action="bypass -h Quest NornilsGarden 32260-00.html">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-00.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-00.html">C</a><br>
<a action="bypass -h Quest NornilsGarden 32260-00.html">H</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-00.html">I</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-00.html">J</a><br>
<a action="bypass -h Quest NornilsGarden check">R</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-00.html">S</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32260-00.html">T</a><br>
</body></html>
@@ -0,0 +1,4 @@
<html><body>Present Door Control Device:<br>
You have entered an incorrect password.<br>
<a action="bypass -h Quest NornilsGarden 32261-02.html">Enter the password again.</a><br>
</body></html>
@@ -0,0 +1,4 @@
<html><body>Present Door Control Unit:<br>
Hmm... So the password is supposed to be the same as the one for the Goddess of the Present Statue, right?<br>
<a action="bypass -h Quest NornilsGarden 32261-02.html">Enter the password.</a><br>
</body></html>
@@ -0,0 +1,5 @@
<html><body>Present Door Control Unit:<br>Eh, so the first letter of the password must be...<br>
<a action="bypass -h Quest NornilsGarden 32261-03.html">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-03.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 1">C</a><br>
<a action="bypass -h Quest NornilsGarden 32261-03.html">L</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-03.html">M</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-03.html">N</a><br>
<a action="bypass -h Quest NornilsGarden 32261-03.html">X</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-03.html">Y</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-03.html">Z</a><br>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Present Door Control Device:<br>
The second letter of the password is...<br>
<a action="bypass -h Quest NornilsGarden 32261-04.html">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-04.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-04.html">C</a><br>
<a action="bypass -h Quest NornilsGarden 32261-04.html">L</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-04.html">M</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 2">N</a><br>
<a action="bypass -h Quest NornilsGarden 32261-04.html">X</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-04.html">Y</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-04.html">Z</a><br>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Present Door Control Device:<br>
The third letter of the password is...<br>
<a action="bypass -h Quest NornilsGarden 32261-05.html">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-05.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 3">C</a><br>
<a action="bypass -h Quest NornilsGarden 32261-05.html">L</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-05.html">M</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-05.html">N</a><br>
<a action="bypass -h Quest NornilsGarden 32261-05.html">X</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-05.html">Y</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-05.html">Z</a><br>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Present Door Control Device:<br>
The final letter of the password is...<br>
<a action="bypass -h Quest NornilsGarden 32261-00.html">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-00.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-00.html">C</a><br>
<a action="bypass -h Quest NornilsGarden check">L</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-00.html">M</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-00.html">N</a><br>
<a action="bypass -h Quest NornilsGarden 32261-00.html">X</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-00.html">Y</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32261-00.html">Z</a><br>
</body></html>
@@ -0,0 +1,4 @@
<html><body>Gate of Future Control Device:<br>
You failed to enter the correct password.<br>
<a action="bypass -h Quest NornilsGarden 32262-02.html">Enter the password again.</a><br>
</body></html>
@@ -0,0 +1,4 @@
<html><body>Gate of Future Control Device:<br>
Umm...so... you're saying...the password is the same as that used to communicate with the Statue of Future?<br>
<a action="bypass -h Quest NornilsGarden 32262-02.html">Enter Password.</a><br>
</body></html>
@@ -0,0 +1,7 @@
<html><body>Gate of Future Control Device:<br>
Uhhh... I remember the first letter of the password was...<br>
<a action="bypass -h Quest NornilsGarden 32262-03.html">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-03.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 1">C</a><br>
<a action="bypass -h Quest NornilsGarden 32262-03.html">H</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-03.html">I</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-03.html">J</a><br>
<a action="bypass -h Quest NornilsGarden 32262-03.html">O</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-03.html">P</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-03.html">Q</a><br>
<a action="bypass -h Quest NornilsGarden 32262-03.html">R</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-03.html">S</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-03.html">T</a><br>
</body></html>
@@ -0,0 +1,7 @@
<html><body>Gate of Future Control Device:<br>
The second letter of the password is...<br>
<a action="bypass -h Quest NornilsGarden 32262-04.html">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-04.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-04.html">C</a><br>
<a action="bypass -h Quest NornilsGarden 2">H</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-04.html">I</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-04.html">J</a><br>
<a action="bypass -h Quest NornilsGarden 32262-04.html">O</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-04.html">P</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-04.html">Q</a><br>
<a action="bypass -h Quest NornilsGarden 32262-04.html">R</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-04.html">S</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-04.html">T</a><br>
</body></html>
@@ -0,0 +1,7 @@
<html><body>Gate of Future Control Device:<br>
The third letter of the password is...<br>
<a action="bypass -h Quest NornilsGarden 3">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-05.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-05.html">C</a><br>
<a action="bypass -h Quest NornilsGarden 32262-05.html">H</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-05.html">I</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-05.html">J</a><br>
<a action="bypass -h Quest NornilsGarden 32262-05.html">O</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-05.html">P</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-05.html">Q</a><br>
<a action="bypass -h Quest NornilsGarden 32262-05.html">R</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-05.html">S</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-05.html">T</a><br>
</body></html>
@@ -0,0 +1,7 @@
<html><body>Gate of Future Control Device:<br>
The fourth letter of the password is...<br>
<a action="bypass -h Quest NornilsGarden 32262-06.html">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-06.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-06.html">C</a><br>
<a action="bypass -h Quest NornilsGarden 32262-06.html">H</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-06.html">I</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-06.html">J</a><br>
<a action="bypass -h Quest NornilsGarden 4">O</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-06.html">P</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-06.html">Q</a><br>
<a action="bypass -h Quest NornilsGarden 32262-06.html">R</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-06.html">S</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-06.html">T</a><br>
</body></html>
@@ -0,0 +1,7 @@
<html><body>Gate of Future Control Device:<br>
The final letter of the password is...<br>
<a action="bypass -h Quest NornilsGarden 32262-00.html">A</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-00.html">B</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-00.html">C</a><br>
<a action="bypass -h Quest NornilsGarden 32262-00.html">H</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-00.html">I</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-00.html">J</a><br>
<a action="bypass -h Quest NornilsGarden 32262-00.html">O</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-00.html">P</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-00.html">Q</a><br>
<a action="bypass -h Quest NornilsGarden 32262-00.html">R</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden check">S</a>&nbsp;&nbsp;&nbsp;<a action="bypass -h Quest NornilsGarden 32262-00.html">T</a><br>
</body></html>
@@ -0,0 +1,9 @@
<html><body>Garden Guard:<br>
Firstly, no one can enter unless accompanied by a Kamael.<br1>
Secondly, you must be at least two in number.<br1>
Thirdly, you must be sufficiently skilled to undertake this test, but not so overqualified as to make this test meaningless.<br1>
Last -- but certainly not least -- any Kamael who wishes to take the test must first obtain permission from the Hierarch.<br1>
Have you met all these requirements?<br>
(In order to challenge, you must be pursuing a quest or belong to a party with at least one Kamael member, and all party members must be between levels 15-22 and not have completed the 1st class transfer.)<br>
<a action="bypass -h Quest NornilsGarden enter_instance">Say that you are qualified.</a><br>
</body></html>
@@ -0,0 +1,4 @@
<html><body>Garden Guard:<br>
Before you may enter, you must recruit comrades whose strengths compensate for your areas of weakness.<br>
You can overcome the trials here only if they are with you.<br>
</body></html>
@@ -0,0 +1,3 @@
<html><body>Garden Guard:<br>
The power of you and your comrades has already exceeded the capacities of this test. For a more suitable challenge, you should leave this island and travel to the Human kingdoms on the mainland. Go!<br>
</body></html>
@@ -0,0 +1,3 @@
<html><body>Garden Guard:<br>
You are not yet ready for this test. Return here when you are.<br>
</body></html>
@@ -0,0 +1,4 @@
<html><body>Garden Guard:<br>
Now is not the right time for you to face this challenge.<br>
(You are unable to enter the instance zone.)<br>
</body></html>
@@ -0,0 +1,5 @@
<html><body>Garden Guard:<br>
Welcome! This final test will judge whether you are truly ready to leave the safety of your island and travel to the outer world. It is a difficult challenge, so I will only administer it to those who meet the necessary requirements. Do you think that you are ready?<br>
<a action="bypass -h Quest NornilsGarden 32330-01.html">Ask about the requirements.</a><br>
<a action="bypass -h Quest NornilsGarden enter_instance">Tell her you are ready to take the test.</a><br>
</body></html>
@@ -0,0 +1,655 @@
/*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.NornilsGarden;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.SkillTable;
import com.l2jserver.gameserver.instancemanager.InstanceManager;
import com.l2jserver.gameserver.instancemanager.InstanceManager.InstanceWorld;
import com.l2jserver.gameserver.instancemanager.QuestManager;
import com.l2jserver.gameserver.model.L2Effect;
import com.l2jserver.gameserver.model.L2Party;
import com.l2jserver.gameserver.model.L2Skill;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Instance;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.model.quest.State;
import com.l2jserver.gameserver.model.zone.L2ZoneType;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.util.Util;
import com.l2jserver.util.Rnd;
/**
** @author Gnacik
**
** 2010-10-15 Based on official server Naia
*/
public class NornilsGarden extends Quest
{
private class NornilsWorld extends InstanceWorld
{
public L2Npc first_npc = null;
public boolean spawned_1 = false;
public boolean spawned_2 = false;
public boolean spawned_3 = false;
public boolean spawned_4 = false;
public NornilsWorld()
{
}
}
private static final String qn = "NornilsGarden";
private static final int INSTANCE_ID = 11;
private static final int DURATION_TIME = 70;
private static final int EMPTY_DESTROY_TIME = 5;
private static final int INSTANCE_LVL_MIN = 18;
private static final int INSTANCE_LVL_MAX = 22;
private static final int _garden_guard = 32330;
private static final int[] _final_gates = { 32260, 32261, 32262 };
private static final int[] SPAWN_PPL = { -111184, 74540, -12430 };
private static final int[] EXIT_PPL = { -74058, 52040, -3680 };
private static final int[][] _auto_gates =
{
{ 20110, 16200001 }, // Warriors gate
{ 20111, 16200004 }, // Midway gate
{ 20112, 16200013 } // Gate
};
private static final L2Skill skill1 = SkillTable.getInstance().getInfo(4322, 1);
private static final L2Skill skill2 = SkillTable.getInstance().getInfo(4327, 1);
private static final L2Skill skill3 = SkillTable.getInstance().getInfo(4329, 1);
private static final L2Skill skill4 = SkillTable.getInstance().getInfo(4324, 1);
private static final int _herb_jar = 18478;
private static final int[][] _gatekeepers =
{
{ 18352, 9703, 0 }, // Kamael Guard
{ 18353, 9704, 0 }, // Guardian of Records
{ 18354, 9705, 0 }, // Guardian of Observation
{ 18355, 9706, 0 }, // Spicula's Guard
{ 18356, 9707, 16200024 }, // Harkilgamed's Gatekeeper
{ 18357, 9708, 16200025 }, // Rodenpicula's Gatekeeper
{ 18358, 9713, 0 }, // Guardian of Secrets
{ 18359, 9709, 16200023 }, // Arviterre's Guardian
{ 18360, 9710, 0 }, // Katenar's Gatekeeper
{ 18361, 9711, 0 }, // Guardian of Prediction
{ 25528, 9712, 0 } // Tiberias
};
private static final int[][] HP_HERBS_DROPLIST =
{
// itemId, count, chance
{ 8602, 1, 10 }, { 8601, 2, 40 }, { 8600, 3, 70 }
};
private static final int[][] _group_1 =
{
{ 18363, -109899, 74431, -12528, 16488 },
{ 18483, -109701, 74501, -12528, 24576 },
{ 18483, -109892, 74886, -12528, 0 },
{ 18363, -109703, 74879, -12528, 49336 }
};
private static final int[][] _group_2 =
{
{ 18363, -110393, 78276, -12848, 49152 },
{ 18363, -110561, 78276, -12848, 49152 },
{ 18362, -110414, 78495, -12905, 48112 },
{ 18362, -110545, 78489, -12903, 48939 },
{ 18483, -110474, 78601, -12915, 49488 },
{ 18362, -110474, 78884, -12915, 49338 },
{ 18483, -110389, 79131, -12915, 48539 },
{ 18483, -110551, 79134, -12915, 49151 }
};
private static final int[][] _group_3 =
{
{ 18483, -107798, 80721, -12912, 0 },
{ 18483, -107798, 80546, -12912, 0 },
{ 18347, -108033, 80644, -12912, 0 },
{ 18363, -108520, 80647, -12912, 0 },
{ 18483, -108740, 80752, -12912, 0 },
{ 18363, -109016, 80642, -12912, 0 },
{ 18483, -108740, 80546, -12912, 0 }
};
private static final int[][] _group_4 =
{
{ 18362, -110082, 83998, -12928, 0 },
{ 18362, -110082, 84210, -12928, 0 },
{ 18363, -109963, 84102, -12896, 0 },
{ 18347, -109322, 84102, -12880, 0 },
{ 18362, -109131, 84097, -12880, 0 },
{ 18483, -108932, 84101, -12880, 0 },
{ 18483, -109313, 84488, -12880, 0 },
{ 18362, -109122, 84490, -12880, 0 },
{ 18347, -108939, 84489, -12880, 0 }
};
private static final int[][] MP_HERBS_DROPLIST =
{
// itemId, count, chance
{ 8605, 1, 10 }, { 8604, 2, 40 }, { 8603, 3, 70 }
};
private static final void dropHerb(L2Npc mob, L2PcInstance player, int[][] drop)
{
final int chance = Rnd.get(100);
for (int i = 0; i < drop.length; i++)
{
if (chance < drop[i][2])
((L2MonsterInstance)mob).dropItem(player, drop[i][0], drop[i][1]);
}
}
private static final void removeBuffs(L2Character ch)
{
for (L2Effect e : ch.getAllEffects())
{
if (e == null)
continue;
L2Skill skill = e.getSkill();
if (skill.isDebuff() || skill.isStayAfterDeath())
continue;
e.exit();
}
}
private static final void giveBuffs(L2Character ch)
{
if(skill1 != null)
skill1.getEffects(ch, ch);
if(skill2 != null)
skill2.getEffects(ch, ch);
if(skill3 != null)
skill3.getEffects(ch, ch);
if(skill4 != null)
skill4.getEffects(ch, ch);
}
private static final void teleportPlayer(L2PcInstance player, int[] coords, int instanceId)
{
QuestState st = player.getQuestState(qn);
if (st == null)
{
Quest q = QuestManager.getInstance().getQuest(qn);
st = q.newQuestState(player);
}
removeBuffs(player);
giveBuffs(player);
if (player.getPet() != null)
{
removeBuffs(player.getPet());
giveBuffs(player.getPet());
}
player.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
player.setInstanceId(instanceId);
player.teleToLocation(coords[0], coords[1], coords[2], true);
}
private void exitInstance(L2PcInstance player)
{
InstanceWorld inst = InstanceManager.getInstance().getWorld(player.getInstanceId());
if (inst instanceof NornilsWorld)
{
NornilsWorld world = ((NornilsWorld) inst);
world.allowed.remove(Integer.valueOf(player.getObjectId()));
player.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
player.setInstanceId(0);
player.teleToLocation(EXIT_PPL[0], EXIT_PPL[1], EXIT_PPL[2], true);
}
}
private final synchronized String enterInstance(L2Npc npc, L2PcInstance player)
{
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (world != null)
{
if (!(world instanceof NornilsWorld) || world.templateId != INSTANCE_ID)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ALREADY_ENTERED_ANOTHER_INSTANCE_CANT_ENTER));
return null;
}
// check for level difference again on reenter
if (player.getLevel() > INSTANCE_LVL_MAX || player.getLevel() < INSTANCE_LVL_MIN)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_LEVEL_REQUIREMENT_NOT_SUFFICIENT);
sm.addPcName(player);
player.sendPacket(sm);
return null;
}
// check what instance still exist
Instance inst = InstanceManager.getInstance().getInstance(world.instanceId);
if (inst != null)
{
teleportPlayer(player, SPAWN_PPL , world.instanceId);
}
return null;
}
// Creating new instance
else
{
String result = checkConditions(npc, player);
if (!(result.equalsIgnoreCase("ok")))
return result;
final int instanceId = InstanceManager.getInstance().createDynamicInstance("NornilsGarden.xml");
final Instance inst = InstanceManager.getInstance().getInstance(instanceId);
inst.setName(InstanceManager.getInstance().getInstanceIdName(INSTANCE_ID));
final int[] returnLoc = { player.getX(), player.getY(), player.getZ() };
inst.setSpawnLoc(returnLoc);
inst.setAllowSummon(false);
inst.setDuration(DURATION_TIME * 60000);
inst.setEmptyDestroyTime(EMPTY_DESTROY_TIME * 60000);
world = new NornilsWorld();
world.instanceId = instanceId;
world.templateId = INSTANCE_ID;
InstanceManager.getInstance().addWorld(world);
_log.info("Nornils Garden: started, Instance: " + instanceId + " created by player: " + player.getName());
prepareInstance((NornilsWorld) world);
// and finally teleport party into instance
final L2Party party = player.getParty();
if(party != null)
{
for (L2PcInstance partyMember : party.getPartyMembers())
{
world.allowed.add(partyMember.getObjectId());
teleportPlayer(partyMember, SPAWN_PPL, instanceId);
}
}
return null;
}
}
private void prepareInstance(NornilsWorld world)
{
world.first_npc = addSpawn(18362,-109702,74696,-12528, 49568, false, 0, false, world.instanceId);
L2DoorInstance door = InstanceManager.getInstance().getInstance(world.instanceId).getDoor(16200010);
if (door != null)
{
door.setTargetable(false);
door.setMeshIndex(2);
}
}
private void spawn1(L2Npc npc)
{
InstanceWorld inst = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (inst instanceof NornilsWorld)
{
NornilsWorld world = ((NornilsWorld) inst);
if (npc.equals(world.first_npc) && !world.spawned_1)
{
world.spawned_1 = true;
for (int mob[] : _group_1)
{
addSpawn(mob[0], mob[1], mob[2], mob[3], mob[4], false, 0, false, world.instanceId);
}
}
}
}
private void spawn2(L2Npc npc)
{
InstanceWorld inst = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (inst instanceof NornilsWorld)
{
NornilsWorld world = ((NornilsWorld) inst);
if (!world.spawned_2)
{
world.spawned_2 = true;
for (int mob[] : _group_2)
{
addSpawn(mob[0], mob[1], mob[2], mob[3], mob[4], false, 0, false, world.instanceId);
}
}
}
}
private void spawn3(L2Character cha)
{
InstanceWorld inst = InstanceManager.getInstance().getWorld(cha.getInstanceId());
if (inst instanceof NornilsWorld)
{
NornilsWorld world = ((NornilsWorld) inst);
if (!world.spawned_3)
{
world.spawned_3 = true;
for (int mob[] : _group_3)
{
addSpawn(mob[0], mob[1], mob[2], mob[3], mob[4], false, 0, false, world.instanceId);
}
}
}
}
private void spawn4(L2Character cha)
{
InstanceWorld inst = InstanceManager.getInstance().getWorld(cha.getInstanceId());
if (inst instanceof NornilsWorld)
{
NornilsWorld world = ((NornilsWorld) inst);
if (!world.spawned_4)
{
world.spawned_4 = true;
for (int mob[] : _group_4)
{
addSpawn(mob[0], mob[1], mob[2], mob[3], mob[4], false, 0, false, world.instanceId);
}
}
}
}
private void openDoor(QuestState st, L2PcInstance player, int doorId)
{
st.unset("correct");
InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(player.getInstanceId());
if (tmpworld instanceof NornilsWorld)
{
L2DoorInstance door = InstanceManager.getInstance().getInstance(tmpworld.instanceId).getDoor(doorId);
if (door != null)
door.openMe();
}
}
private static final String checkConditions(L2Npc npc, L2PcInstance player)
{
final L2Party party = player.getParty();
// player must be in party
if (party == null)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.NOT_IN_PARTY_CANT_ENTER));
return "32330-05.html";
}
// ...and be party leader
if (party.getLeader() != player)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ONLY_PARTY_LEADER_CAN_ENTER));
return "32330-08.html";
}
boolean _kamael = false;
// for each party member
for (L2PcInstance partyMember : party.getPartyMembers())
{
// player level must be in range
if (partyMember.getLevel() > INSTANCE_LVL_MAX)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_LEVEL_REQUIREMENT_NOT_SUFFICIENT);
sm.addPcName(partyMember);
player.sendPacket(sm);
return "32330-06.html";
}
if (partyMember.getLevel() < INSTANCE_LVL_MIN)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_LEVEL_REQUIREMENT_NOT_SUFFICIENT);
sm.addPcName(partyMember);
player.sendPacket(sm);
return "32330-07.html";
}
if ( partyMember.getClassId().level() != 0)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_LEVEL_REQUIREMENT_NOT_SUFFICIENT);
sm.addPcName(partyMember);
player.sendPacket(sm);
return "32330-06.html";
}
// player must be near party leader
if (!partyMember.isInsideRadius(player, 500, true, true))
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_LOCATION_THAT_CANNOT_BE_ENTERED);
sm.addPcName(partyMember);
player.sendPacket(sm);
return "32330-08.html";
}
if (partyMember.getRace().ordinal() == 5)
{
QuestState checkst = partyMember.getQuestState("179_IntoTheLargeCavern");
if(checkst != null && checkst.getState() == State.STARTED)
{
_kamael = true;
}
else
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_QUEST_REQUIREMENT_NOT_SUFFICIENT);
sm.addPcName(partyMember);
player.sendPacket(sm);
return "32330-08.html";
}
}
}
if (!_kamael)
{
return "32330-08.html";
}
return "ok";
}
@Override
public String onEnterZone(L2Character character, L2ZoneType zone)
{
if (character instanceof L2PcInstance
&& !character.isDead()
&& !character.isTeleporting()
&& ((L2PcInstance)character).isOnline())
{
InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(character.getInstanceId());
if (tmpworld instanceof NornilsWorld)
{
for (int _auto[] : _auto_gates)
{
if (zone.getId() == _auto[0])
{
L2DoorInstance door = InstanceManager.getInstance().getInstance(tmpworld.instanceId).getDoor(_auto[1]);
if (door != null)
door.openMe();
}
if (zone.getId() == 20111)
spawn3(character);
else if(zone.getId() == 20112)
spawn4(character);
}
}
}
return super.onEnterZone(character,zone);
}
@Override
public final String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
player.sendMessage("On Event");
String htmltext = event;
QuestState st = player.getQuestState(qn);
if(st == null)
return getNoQuestMsg(player);
if(npc.getNpcId() == _garden_guard && event.equalsIgnoreCase("enter_instance"))
{
try
{
htmltext = enterInstance(npc, player);
}
catch (Exception e)
{
}
}
else if (npc.getNpcId() == 32258 && event.equalsIgnoreCase("exit"))
{
try
{
exitInstance(player);
}
catch (Exception e)
{
}
}
else if (Util.contains(_final_gates, npc.getNpcId()))
{
if(event.equalsIgnoreCase("32260-02.html") || event.equalsIgnoreCase("32261-02.html") || event.equalsIgnoreCase("32262-02.html"))
{
st.unset("correct");
}
else if(Util.isDigit(event))
{
int correct = st.getInt("correct");
correct++;
st.set("correct", String.valueOf(correct));
htmltext = npc.getNpcId()+"-0"+String.valueOf(correct+2)+".html";
}
else if (event.equalsIgnoreCase("check"))
{
int correct = st.getInt("correct");
if(npc.getNpcId() == 32260 && correct == 3)
openDoor(st, player, 16200014);
else if (npc.getNpcId() == 32261 && correct == 3)
openDoor(st, player, 16200015);
else if (npc.getNpcId() == 32262 && correct == 4)
openDoor(st, player, 16200016);
else
return npc.getNpcId()+"-00.html";
}
}
return htmltext;
}
@Override
public final String onTalk(L2Npc npc, L2PcInstance player)
{
if (Util.contains(_final_gates, npc.getNpcId()))
{
QuestState cst = player.getQuestState("179_IntoTheLargeCavern");
if (cst != null && cst.getState() == State.STARTED)
{
return npc.getNpcId()+"-01.html";
}
else
return getNoQuestMsg(player);
}
return null;
}
@Override
public final String onFirstTalk (L2Npc npc, L2PcInstance player)
{
QuestState st = player.getQuestState(qn);
if (st == null)
{
Quest q = QuestManager.getInstance().getQuest(qn);
st = q.newQuestState(player);
}
return npc.getNpcId()+".html";
}
@Override
public final String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isPet)
{
if (npc.getNpcId() == _herb_jar && !npc.isDead())
{
dropHerb(npc, attacker, HP_HERBS_DROPLIST);
dropHerb(npc, attacker, MP_HERBS_DROPLIST);
npc.doDie(attacker);
}
else if (npc.getNpcId() == 18362 && npc.getInstanceId() > 0)
{
spawn1(npc);
}
return null;
}
@Override
public final String onKill(L2Npc npc, L2PcInstance player, boolean isPet)
{
QuestState st = player.getQuestState(qn);
if (st == null)
return null;
for (int _gk[] : _gatekeepers)
{
if (npc.getNpcId() == _gk[0])
{
// Drop key
((L2MonsterInstance)npc).dropItem(player, _gk[1], 1);
// Check if gatekeeper should open bridge, and open it
if (_gk[2] > 0)
{
InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(player.getInstanceId());
if (tmpworld instanceof NornilsWorld)
{
L2DoorInstance door = InstanceManager.getInstance().getInstance(tmpworld.instanceId).getDoor(_gk[2]);
if (door != null)
{
door.openMe();
door.sendInfo(player);
}
}
}
}
if(npc.getNpcId() == 18355)
spawn2(npc);
}
return super.onKill(npc, player, isPet);
}
public NornilsGarden(int questId, String name, String descr)
{
super(questId, name, descr);
addStartNpc(_garden_guard);
addFirstTalkId(_garden_guard);
addTalkId(_garden_guard);
for(int i[] : _gatekeepers)
addKillId(i[0]);
for(int i[] : _auto_gates)
addEnterZoneId(i[0]);
for(int i : _final_gates)
addTalkId(i);
addAttackId(_herb_jar);
addAttackId(18362); // first garden guard
}
public static void main(String[] args)
{
new NornilsGarden(-1, qn, "instances");
}
}
@@ -0,0 +1,585 @@
package instances.Pailaka;
import java.util.List;
import java.util.logging.Logger;
import javolution.util.FastList;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.SkillTable;
import com.l2jserver.gameserver.instancemanager.InstanceManager;
import com.l2jserver.gameserver.instancemanager.InstanceManager.InstanceWorld;
import com.l2jserver.gameserver.model.L2Skill;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.L2Playable;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Instance;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.model.quest.State;
import com.l2jserver.gameserver.model.zone.L2ZoneType;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.Rnd;
public class PailakaDevilsLegacy extends Quest
{
private static final String qn = "129_PailakaDevilsLegacy";
protected static final Logger _log = Logger.getLogger(PailakaDevilsLegacy.class.getName());
private static final int MIN_LEVEL = 61;
private static final int MAX_LEVEL = 67;
private static final int EXIT_TIME = 5;
private static final int INSTANCE_ID = 44;
private static final int[] TELEPORT = { 76428, -219038, -3752 };
private static final int ZONE = 20109;
private static final int SURVIVOR = 32498;
private static final int SUPPORTER = 32501;
private static final int ADVENTURER1 = 32508;
private static final int ADVENTURER2 = 32511;
private static final int[] NPCS = { SURVIVOR, SUPPORTER, ADVENTURER1, ADVENTURER2 };
private static final int KAMS = 18629;
private static final int HIKORO = 18630;
private static final int ALKASO = 18631;
private static final int GERBERA = 18632;
private static final int LEMATAN = 18633;
private static final int FOLLOWERS = 18634;
private static final int TREASURE_BOX = 32495;
private static final int POWDER_KEG = 18622;
private static final int[] MONSTERS =
{ KAMS, HIKORO, ALKASO, GERBERA, LEMATAN, FOLLOWERS, TREASURE_BOX, POWDER_KEG,
18623, 18624, 18625, 18626, 18627 };
private static final int SWORD = 13042;
private static final int ENH_SWORD1 = 13043;
private static final int ENH_SWORD2 = 13044;
private static final int SCROLL_1 = 13046;
private static final int SCROLL_2 = 13047;
private static final int HEALING_POTION = 13033;
private static final int ANTIDOTE_POTION = 13048;
private static final int DIVINE_POTION = 13049;
private static final int DEFENCE_POTION = 13059;
private static final int PAILAKA_KEY = 13150;
private static boolean _isTeleportScheduled = false;
private static boolean _isOnShip = false;
private static L2Npc _lematanNpc = null;
private List<L2Npc> _followerslist;
private static final int[] ITEMS = { SWORD, ENH_SWORD1, ENH_SWORD2, SCROLL_1, SCROLL_2, HEALING_POTION, ANTIDOTE_POTION, DIVINE_POTION, DEFENCE_POTION, PAILAKA_KEY };
private static final int[][] DROPLIST =
{
// must be sorted by npcId !
// npcId, itemId, chance, max
{ TREASURE_BOX, HEALING_POTION, 20 },
{ TREASURE_BOX, DIVINE_POTION, 40 },
{ TREASURE_BOX, DEFENCE_POTION, 60 },
{ TREASURE_BOX, PAILAKA_KEY, 80 },
{ TREASURE_BOX, ANTIDOTE_POTION,100 }
};
private static final int[][] HP_HERBS_DROPLIST =
{
// itemId, count, chance
{ 8602, 1, 10 }, { 8601, 1, 40 }, { 8600, 1, 70 }
};
private static final int[][] MP_HERBS_DROPLIST =
{
// itemId, count, chance
{ 8605, 1, 10 }, { 8604, 1, 40 }, { 8603, 1, 70 }
};
private static final int[] REWARDS = { 13295, 13129 };
private static final int[][] FOLLOWERS_SPAWNS = {
{ 85067, -208943, -3336, 20106, 60 },
{ 84904, -208944, -3336, 10904, 60 },
{ 85062, -208538, -3336, 44884, 60 },
{ 84897, -208542, -3336, 52973, 60 },
{ 84808, -208633, -3339, 65039, 60 },
{ 84808, -208856, -3339, 0, 60 },
{ 85144, -208855, -3341, 33380, 60 },
{ 85139, -208630, -3339, 31777, 60 }
};
private static L2Skill boom_skill = SkillTable.getInstance().getInfo(5714, 1);
private static L2Skill energy_skill = SkillTable.getInstance().getInfo(5712, 1);
private void attackPlayer(L2Attackable npc, L2Playable attacker)
{
npc.setIsRunning(true);
npc.addDamageHate(attacker, 0, 999);
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker);
}
private static final void dropHerb(L2Npc mob, L2PcInstance player, int[][] drop)
{
final int chance = Rnd.get(100);
for (int i = 0; i < drop.length; i++)
{
if (chance < drop[i][2])
{
((L2MonsterInstance)mob).dropItem(player, drop[i][0], drop[i][1]);
return;
}
}
}
private static final void dropItem(L2Npc mob, L2PcInstance player)
{
final int npcId = mob.getNpcId();
final int chance = Rnd.get(100);
for (int i = 0; i < DROPLIST.length; i++)
{
int[] drop = DROPLIST[i];
if (npcId == drop[0])
{
if (chance < drop[2])
{
((L2MonsterInstance)mob).dropItem(player, drop[1], Rnd.get(1,6));
return;
}
}
if (npcId < drop[0])
return; // not found
}
}
private static final void teleportPlayer(L2PcInstance player, int[] coords, int instanceId)
{
player.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
player.setInstanceId(instanceId);
player.teleToLocation(coords[0], coords[1], coords[2], true);
}
private final synchronized void enterInstance(L2PcInstance player)
{
//check for existing instances for this player
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (world != null)
{
if (world.templateId != INSTANCE_ID)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ALREADY_ENTERED_ANOTHER_INSTANCE_CANT_ENTER));
return;
}
Instance inst = InstanceManager.getInstance().getInstance(world.instanceId);
if (inst != null)
teleportPlayer(player, TELEPORT, world.instanceId);
return;
}
//New instance
else
{
final int instanceId = InstanceManager.getInstance().createDynamicInstance("PailakaDevilsLegacy.xml");
world = new InstanceWorld();
world.instanceId = instanceId;
world.templateId = INSTANCE_ID;
InstanceManager.getInstance().addWorld(world);
world.allowed.add(player.getObjectId());
teleportPlayer(player, TELEPORT, instanceId);
_lematanNpc = addSpawn(LEMATAN, 88108, -209252, -3744, 64255, false, 0, false, instanceId);
}
}
@Override
public final String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
// Must be here, because of player == null
if (npc.getNpcId() == FOLLOWERS && event.equals("follower_cast"))
{
if (!npc.isCastingNow() && !npc.isDead() && !_lematanNpc.isDead())
{
npc.setTarget(_lematanNpc);
npc.doCast(energy_skill);
}
startQuestTimer("follower_cast", 2000+Rnd.get(100, 1000), npc, null);
return null;
}
else if (npc.getNpcId() == POWDER_KEG && event.equalsIgnoreCase("keg_trigger"))
{
onAttack(npc, player, 600, false);
}
final QuestState st = player.getQuestState(qn);
if (st == null)
return getNoQuestMsg(player);
final int cond = st.getInt("cond");
if (event.equalsIgnoreCase("enter"))
{
enterInstance(player);
if(st.getInt("cond") == 1)
{
st.set("cond","2");
return "32498-07.htm";
}
else
{
return "32498-09.htm";
}
}
else if (event.equalsIgnoreCase("32498-05.htm"))
{
if (cond == 0)
{
st.set("cond","1");
st.setState(State.STARTED);
st.playSound("ItemSound.quest_accept");
}
}
else if (event.equalsIgnoreCase("32501-03.htm"))
{
if (cond == 2)
{
st.giveItems(SWORD, 1);
st.set("cond","3");
st.playSound("ItemSound.quest_middle");
}
}
else if (event.equalsIgnoreCase("32510-02.htm"))
{
st.unset("cond");
st.playSound("ItemSound.quest_finish");
st.exitQuest(false);
Instance inst = InstanceManager.getInstance().getInstance(npc.getInstanceId());
inst.setDuration(EXIT_TIME * 60000);
inst.setEmptyDestroyTime(0);
if (inst.containsPlayer(player.getObjectId()))
{
player.setVitalityPoints(20000, true);
st.addExpAndSp(810000, 50000);
for (int id : REWARDS)
st.giveItems(id, 1);
}
}
else if (event.equalsIgnoreCase("lematan_teleport"))
{
if (npc.getNpcId() == LEMATAN && !npc.isMovementDisabled()&& !_isOnShip)
{
// Reduce Hate
((L2Attackable)npc).reduceHate(player, 9999);
((L2Attackable)npc).abortAttack();
((L2Attackable)npc).abortCast();
// Broadcast Escape
npc.broadcastPacket(new MagicSkillUse(npc, 2100, 1, 1000, 0));
// Schedule telport - when Lematan Finish casting
startQuestTimer("lematan_finish_teleport", 1500, npc, player);
}
else
_isTeleportScheduled = false;
return null;
}
else if (npc.getNpcId() == LEMATAN && event.equalsIgnoreCase("lematan_finish_teleport") && !_isOnShip)
{
// Teleport Lematan
npc.teleToLocation(84973, -208721, -3340);
// Set onShip
_isOnShip = true;
// Set Spawn loc to ship. If he loose aggro he should stay on board ;)
npc.getSpawn().setLocx(84973);
npc.getSpawn().setLocy(-208721);
npc.getSpawn().setLocz(-3340);
// To be sure, reduce again
((L2Attackable)npc).reduceHate(player, 9999);
// Spawn followers
_followerslist = new FastList<L2Npc>();
for (int i = 0; i < FOLLOWERS_SPAWNS.length; i++)
{
int[] SPAWN = FOLLOWERS_SPAWNS[i];
L2Npc _follower = addSpawn(FOLLOWERS, SPAWN[0], SPAWN[1], SPAWN[2], SPAWN[3], false, 0, true, player.getInstanceId());
if (_follower != null)
_followerslist.add(_follower);
}
return null;
}
return event;
}
@Override
public final String onFirstTalk(L2Npc npc, L2PcInstance player)
{
final QuestState st = player.getQuestState(qn);
if (st != null && npc.getNpcId() == ADVENTURER2 && st.getState() == State.COMPLETED)
return "32511-03.htm";
else
return npc.getNpcId() + ".htm";
}
@Override
public final String onTalk(L2Npc npc, L2PcInstance player)
{
final QuestState st = player.getQuestState(qn);
if (st == null)
return getNoQuestMsg(player);
final int cond = st.getInt("cond");
switch (npc.getNpcId())
{
case SURVIVOR:
switch (st.getState())
{
case State.CREATED:
if (player.getLevel() < MIN_LEVEL)
return "32498-11.htm";
if (player.getLevel() > MAX_LEVEL)
return "32498-12.htm";
return "32498-01.htm";
case State.STARTED:
if (cond > 1)
return "32498-08.htm";
else
return "32498-06.htm";
case State.COMPLETED:
return "32498-10.htm";
default:
return "32498-01.htm";
}
case SUPPORTER:
if(st.getInt("cond") > 2)
return "32501-04.htm";
else
return "32501-01.htm";
case ADVENTURER1:
if(player.getPet() == null)
{
if (st.getQuestItemsCount(SWORD) > 0)
{
if(st.getQuestItemsCount(SCROLL_1) > 0)
{
st.takeItems(SWORD, -1);
st.takeItems(SCROLL_1, -1);
st.giveItems(ENH_SWORD1, 1);
return "32508-03.htm";
}
else
return "32508-02.htm";
}
else if (st.getQuestItemsCount(ENH_SWORD1) > 0)
{
if(st.getQuestItemsCount(SCROLL_2) > 0)
{
st.takeItems(ENH_SWORD1, -1);
st.takeItems(SCROLL_2, -1);
st.giveItems(ENH_SWORD2, 1);
return "32508-05.htm";
}
else
return "32508-04.htm";
}
else if (st.getQuestItemsCount(ENH_SWORD2) > 0)
return "32508-06.htm";
else
return "32508-00.htm";
}
else
return "32508-07.htm";
case ADVENTURER2:
if (player.getPet() == null)
{
st.unset("cond");
st.playSound("ItemSound.quest_finish");
st.exitQuest(false);
Instance inst = InstanceManager.getInstance().getInstance(npc.getInstanceId());
inst.setDuration(EXIT_TIME * 60000);
inst.setEmptyDestroyTime(0);
if (inst.containsPlayer(player.getObjectId()))
{
player.setVitalityPoints(20000, true);
st.addExpAndSp(10800000, 950000);
for (int id : REWARDS)
st.giveItems(id, 1);
}
return "32511-01.htm";
}
else
return "32511-02.htm";
}
return getNoQuestMsg(player);
}
@Override
public final String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isPet)
{
if(npc.getNpcId() == POWDER_KEG && !npc.isDead())
{
npc.doCast(boom_skill);
if( npc.getKnownList() != null)
{
for (L2Character target : npc.getKnownList().getKnownCharactersInRadius(900))
{
target.reduceCurrentHp(500+Rnd.get(0,200), npc, boom_skill);
if (target instanceof L2MonsterInstance)
{
if (((L2MonsterInstance) target).getNpcId() == POWDER_KEG )
{
startQuestTimer("keg_trigger", 500, (L2Npc)target, attacker);
}
else
{
if(isPet)
attackPlayer((L2Attackable) npc, attacker.getPet());
else
attackPlayer((L2Attackable) npc, attacker);
}
}
}
}
if (!npc.isDead())
npc.doDie(attacker);
}
else if (npc.getNpcId() == LEMATAN && npc.getCurrentHp() < (npc.getMaxHp()/2) && !_isTeleportScheduled)
{
startQuestTimer("lematan_teleport", 1000, npc, attacker);
}
else if (npc.getNpcId() == TREASURE_BOX)
{
dropItem(npc, attacker);
npc.doDie(attacker);
}
return super.onAttack(npc, attacker, damage, isPet);
}
@Override
public final String onKill(L2Npc npc, L2PcInstance player, boolean isPet)
{
QuestState st = player.getQuestState(qn);
if (st == null || st.getState() != State.STARTED)
return null;
switch (npc.getNpcId())
{
case KAMS:
if (st.getQuestItemsCount(SWORD) > 0)
{
st.playSound("ItemSound.quest_itemget");
st.giveItems(SCROLL_1, 1);
}
break;
case ALKASO:
if (st.getQuestItemsCount(ENH_SWORD1) > 0)
{
st.playSound("ItemSound.quest_itemget");
st.giveItems(SCROLL_2, 1);
}
break;
case LEMATAN:
if (_followerslist != null && !_followerslist.isEmpty())
{
for (L2Npc _follower : _followerslist)
_follower.deleteMe();
_followerslist.clear();
}
st.set("cond", "4");
st.playSound("ItemSound.quest_middle");
addSpawn(ADVENTURER2, 84983, -208736, -3336, 49915, false, 0, false, npc.getInstanceId());
break;
case POWDER_KEG:
case TREASURE_BOX:
case FOLLOWERS:
// do nothing
break;
default:
// hardcoded herb drops
dropHerb(npc, player, HP_HERBS_DROPLIST);
dropHerb(npc, player, MP_HERBS_DROPLIST);
break;
}
return super.onKill(npc, player, isPet);
}
@Override
public final String onSpawn(L2Npc npc)
{
startQuestTimer("follower_cast", 1000+Rnd.get(100, 1000), npc, null);
npc.disableCoreAI(true);
return null;
}
@Override
public String onEnterZone(L2Character character, L2ZoneType zone)
{
if (character instanceof L2PcInstance
&& !character.isDead()
&& !character.isTeleporting()
&& ((L2PcInstance)character).isOnline())
{
InstanceWorld world = InstanceManager.getInstance().getWorld(character.getInstanceId());
if (world != null && world.templateId == INSTANCE_ID)
ThreadPoolManager.getInstance().scheduleGeneral(new Teleport(character, world.instanceId), 1000);
}
return super.onEnterZone(character,zone);
}
static final class Teleport implements Runnable
{
private final L2Character _char;
private final int _instanceId;
public Teleport(L2Character c, int id)
{
_char = c;
_instanceId = id;
}
public void run()
{
try
{
teleportPlayer((L2PcInstance)_char, TELEPORT, _instanceId);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
public PailakaDevilsLegacy(int questId, String name, String descr)
{
super(questId, name, descr);
addStartNpc(SURVIVOR);
for (int npcId : NPCS)
{
addFirstTalkId(npcId);
addTalkId(npcId);
}
addAttackId(TREASURE_BOX);
addAttackId(POWDER_KEG);
addAttackId(LEMATAN);
for (int mobId : MONSTERS)
addKillId(mobId);
addEnterZoneId(ZONE);
addSpawnId(FOLLOWERS);
questItemIds = ITEMS;
}
public static void main(String[] args)
{
new PailakaDevilsLegacy(129, qn, "Pailaka - Devil's Legacy");
}
}
@@ -0,0 +1,457 @@
package instances.Pailaka;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.instancemanager.InstanceManager;
import com.l2jserver.gameserver.instancemanager.InstanceManager.InstanceWorld;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Instance;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.model.quest.State;
import com.l2jserver.gameserver.model.zone.L2ZoneType;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.Rnd;
public class PailakaSongOfIceAndFire extends Quest
{
private static final String qn = "128_PailakaSongOfIceAndFire";
private static final int MIN_LEVEL = 36;
private static final int MAX_LEVEL = 42;
private static final int EXIT_TIME = 5;
private static final int INSTANCE_ID = 43;
private static final int[] TELEPORT = { -52875, 188232, -4696 };
private static final int ZONE = 20108;
private static final int ADLER1 = 32497;
private static final int ADLER2 = 32510;
private static final int SINAI = 32500;
private static final int INSPECTOR = 32507;
private static final int[] NPCS = { ADLER1, ADLER2, SINAI, INSPECTOR };
private static final int HILLAS = 18610;
private static final int PAPION = 18609;
private static final int KINSUS = 18608;
private static final int GARGOS = 18607;
private static final int ADIANTUM = 18620;
private static final int BLOOM = 18616;
private static final int BOTTLE = 32492;
private static final int BRAZIER = 32493;
private static final int[] MONSTERS =
{ HILLAS, PAPION, KINSUS, GARGOS, ADIANTUM, BLOOM, BOTTLE, BRAZIER,
18611, 18612, 18613, 18614, 18615 };
private static final int SWORD = 13034;
private static final int ENH_SWORD1 = 13035;
private static final int ENH_SWORD2 = 13036;
private static final int BOOK1 = 13130;
private static final int BOOK2 = 13131;
private static final int BOOK3 = 13132;
private static final int BOOK4 = 13133;
private static final int BOOK5 = 13134;
private static final int BOOK6 = 13135;
private static final int BOOK7 = 13136;
private static final int WATER_ESSENCE = 13038;
private static final int FIRE_ESSENCE = 13039;
private static final int SHIELD_POTION = 13032;
private static final int HEAL_POTION = 13033;
private static final int FIRE_ENHANCER = 13040;
private static final int WATER_ENHANCER = 13041;
private static final int[] ITEMS = { SWORD, ENH_SWORD1, ENH_SWORD2, BOOK1, BOOK2, BOOK3, BOOK4, BOOK5, BOOK6, BOOK7,
WATER_ESSENCE, FIRE_ESSENCE, SHIELD_POTION, HEAL_POTION, FIRE_ENHANCER, WATER_ENHANCER };
private static final int[][] DROPLIST =
{
// must be sorted by npcId !
// npcId, itemId, chance
{ BLOOM, SHIELD_POTION, 30 },
{ BLOOM, HEAL_POTION, 80 },
{ BOTTLE, SHIELD_POTION, 10 },
{ BOTTLE, WATER_ENHANCER, 40 },
{ BOTTLE, HEAL_POTION, 80 },
{ BRAZIER, SHIELD_POTION, 10 },
{ BRAZIER, FIRE_ENHANCER, 40 },
{ BRAZIER, HEAL_POTION, 80 }
};
private static final int[][] HP_HERBS_DROPLIST =
{
// itemId, count, chance
{ 8602, 1, 10 }, { 8601, 1, 40 }, { 8600, 1, 70 }
};
private static final int[][] MP_HERBS_DROPLIST =
{
// itemId, count, chance
{ 8605, 1, 10 }, { 8604, 1, 40 }, { 8603, 1, 70 }
};
private static final int[] REWARDS = { 13294, 13293, 13129 };
private static final void dropHerb(L2Npc mob, L2PcInstance player, int[][] drop)
{
final int chance = Rnd.get(100);
for (int i = 0; i < drop.length; i++)
{
if (chance < drop[i][2])
{
((L2MonsterInstance)mob).dropItem(player, drop[i][0], drop[i][1]);
return;
}
}
}
private static final void dropItem(L2Npc mob, L2PcInstance player)
{
final int npcId = mob.getNpcId();
final int chance = Rnd.get(100);
for (int i = 0; i < DROPLIST.length; i++)
{
int[] drop = DROPLIST[i];
if (npcId == drop[0])
{
if (chance < drop[2])
{
((L2MonsterInstance)mob).dropItem(player, drop[1], Rnd.get(1,6));
return;
}
}
if (npcId < drop[0])
return; // not found
}
}
private static final void teleportPlayer(L2PcInstance player, int[] coords, int instanceId)
{
player.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
player.setInstanceId(instanceId);
player.teleToLocation(coords[0], coords[1], coords[2], true);
}
private final synchronized void enterInstance(L2PcInstance player)
{
//check for existing instances for this player
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (world != null)
{
if (world.templateId != INSTANCE_ID)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ALREADY_ENTERED_ANOTHER_INSTANCE_CANT_ENTER));
return;
}
Instance inst = InstanceManager.getInstance().getInstance(world.instanceId);
if (inst != null)
teleportPlayer(player, TELEPORT, world.instanceId);
return;
}
//New instance
else
{
final int instanceId = InstanceManager.getInstance().createDynamicInstance("PailakaSongOfIceAndFire.xml");
world = new InstanceWorld();
world.instanceId = instanceId;
world.templateId = INSTANCE_ID;
InstanceManager.getInstance().addWorld(world);
world.allowed.add(player.getObjectId());
teleportPlayer(player, TELEPORT, instanceId);
}
}
@Override
public final String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final QuestState st = player.getQuestState(qn);
if (st == null)
return getNoQuestMsg(player);
final int cond = st.getInt("cond");
if (event.equalsIgnoreCase("enter"))
{
enterInstance(player);
return null;
}
else if (event.equalsIgnoreCase("32497-03.htm"))
{
if (cond == 0)
{
st.set("cond","1");
st.setState(State.STARTED);
st.playSound("ItemSound.quest_accept");
}
}
else if (event.equalsIgnoreCase("32500-06.htm"))
{
if (cond == 1)
{
st.set("cond","2");
st.playSound("ItemSound.quest_itemget");
st.giveItems(SWORD, 1);
st.giveItems(BOOK1, 1);
}
}
else if (event.equalsIgnoreCase("32507-04.htm"))
{
if (cond == 3)
{
st.set("cond","4");
st.playSound("ItemSound.quest_middle");
st.takeItems(SWORD, -1);
st.takeItems(WATER_ESSENCE, -1);
st.takeItems(BOOK2, -1);
st.giveItems(BOOK3, 1);
st.giveItems(ENH_SWORD1, 1);
}
}
else if (event.equalsIgnoreCase("32507-08.htm"))
{
if (cond == 6)
{
st.set("cond","7");
st.playSound("ItemSound.quest_itemget");
st.takeItems(ENH_SWORD1, -1);
st.takeItems(BOOK5, -1);
st.takeItems(FIRE_ESSENCE, -1);
st.giveItems(ENH_SWORD2, 1);
st.giveItems(BOOK6, 1);
}
}
else if (event.equalsIgnoreCase("32510-02.htm"))
{
st.unset("cond");
st.playSound("ItemSound.quest_finish");
st.exitQuest(false);
Instance inst = InstanceManager.getInstance().getInstance(npc.getInstanceId());
inst.setDuration(EXIT_TIME * 60000);
inst.setEmptyDestroyTime(0);
if (inst.containsPlayer(player.getObjectId()))
{
player.setVitalityPoints(20000, true);
st.addExpAndSp(810000, 50000);
for (int id : REWARDS)
st.giveItems(id, 1);
}
}
return event;
}
@Override
public final String onFirstTalk(L2Npc npc, L2PcInstance player)
{
return npc.getNpcId() + ".htm";
}
@Override
public final String onTalk(L2Npc npc, L2PcInstance player)
{
final QuestState st = player.getQuestState(qn);
if (st == null)
return getNoQuestMsg(player);
final int cond = st.getInt("cond");
switch (npc.getNpcId())
{
case ADLER1:
switch (st.getState())
{
case State.CREATED:
if (player.getLevel() < MIN_LEVEL)
return "32497-05.htm";
if (player.getLevel() > MAX_LEVEL)
return "32497-06.htm";
return "32497-01.htm";
case State.STARTED:
if (cond > 1)
return "32497-00.htm";
else
return "32497-03.htm";
case State.COMPLETED:
return "32497-07.htm";
default:
return "32497-01.htm";
}
case SINAI:
if (cond > 1)
return "32500-00.htm";
else
return "32500-01.htm";
case INSPECTOR:
switch (st.getInt("cond"))
{
case 1:
return "32507-01.htm";
case 2:
return "32507-02.htm";
case 3:
return "32507-03.htm";
case 4:
case 5:
return "32507-05.htm";
case 6:
return "32507-06.htm";
default:
return "32507-09.htm";
}
case ADLER2:
if (st.getState() == State.COMPLETED)
return "32510-00.htm";
else if (cond == 9)
return "32510-01.htm";
}
return getNoQuestMsg(player);
}
@Override
public final String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isPet)
{
if (!npc.isDead())
npc.doDie(attacker);
return super.onAttack(npc, attacker, damage, isPet);
}
@Override
public final String onKill(L2Npc npc, L2PcInstance player, boolean isPet)
{
QuestState st = player.getQuestState(qn);
if (st == null || st.getState() != State.STARTED)
return null;
final int cond = st.getInt("cond");
switch (npc.getNpcId())
{
case HILLAS:
if (cond == 2)
{
st.set("cond", "3");
st.playSound("ItemSound.quest_itemget");
st.takeItems(BOOK1, -1);
st.giveItems(BOOK2, 1);
st.giveItems(WATER_ESSENCE, 1);
}
addSpawn(PAPION, -53903, 181484, -4555, 30456, false, 0, false, npc.getInstanceId());
break;
case PAPION:
if (cond == 4)
{
st.takeItems(BOOK3, -1);
st.giveItems(BOOK4, 1);
st.set("cond", "5");
st.playSound("ItemSound.quest_itemget");
}
addSpawn(KINSUS, -61415, 181418, -4818, 63852, false, 0, false, npc.getInstanceId());
break;
case KINSUS:
if (cond == 5)
{
st.set("cond", "6");
st.playSound("ItemSound.quest_itemget");
st.takeItems(BOOK4, -1);
st.giveItems(BOOK5, 1);
st.giveItems(FIRE_ESSENCE, 1);
}
addSpawn(GARGOS, -61354, 183624, -4821, 63613, false, 0, false, npc.getInstanceId());
break;
case GARGOS:
if (cond == 7)
{
st.set("cond", "8");
st.playSound("ItemSound.quest_itemget");
st.takeItems(BOOK6, -1);
st.giveItems(BOOK7, 1);
}
addSpawn(ADIANTUM, -53297, 185027, -4617, 1512, false, 0, false, npc.getInstanceId());
break;
case ADIANTUM:
if (cond == 8)
{
st.set("cond", "9");
st.playSound("ItemSound.quest_middle");
st.takeItems(BOOK7, -1);
addSpawn(ADLER2, -53297, 185027, -4617, 33486, false, 0, false, npc.getInstanceId());
}
break;
case BOTTLE:
case BRAZIER:
case BLOOM:
dropItem(npc, player);
break;
default:
// hardcoded herb drops
dropHerb(npc, player, HP_HERBS_DROPLIST);
dropHerb(npc, player, MP_HERBS_DROPLIST);
break;
}
return super.onKill(npc, player, isPet);
}
@Override
public String onExitZone(L2Character character, L2ZoneType zone)
{
if (character instanceof L2PcInstance
&& !character.isDead()
&& !character.isTeleporting()
&& ((L2PcInstance)character).isOnline())
{
InstanceWorld world = InstanceManager.getInstance().getWorld(character.getInstanceId());
if (world != null && world.templateId == INSTANCE_ID)
ThreadPoolManager.getInstance().scheduleGeneral(new Teleport(character, world.instanceId), 1000);
}
return super.onExitZone(character,zone);
}
static final class Teleport implements Runnable
{
private final L2Character _char;
private final int _instanceId;
public Teleport(L2Character c, int id)
{
_char = c;
_instanceId = id;
}
public void run()
{
try
{
teleportPlayer((L2PcInstance)_char, TELEPORT, _instanceId);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
public PailakaSongOfIceAndFire(int questId, String name, String descr)
{
super(questId, name, descr);
addStartNpc(ADLER1);
for (int npcId : NPCS)
{
addFirstTalkId(npcId);
addTalkId(npcId);
}
addAttackId(BOTTLE);
addAttackId(BRAZIER);
for (int mobId : MONSTERS)
addKillId(mobId);
addExitZoneId(ZONE);
questItemIds = ITEMS;
}
public static void main(String[] args)
{
new PailakaSongOfIceAndFire(128, qn, "Pailaka - Song of Ice and Fire");
}
}
@@ -0,0 +1,911 @@
/*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.SeedOfDestruction;
import gnu.trove.TIntObjectHashMap;
import java.io.File;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import javolution.util.FastList;
import javolution.util.FastMap;
import com.l2jserver.Config;
import com.l2jserver.gameserver.GeoData;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.instancemanager.GraciaSeedsManager;
import com.l2jserver.gameserver.instancemanager.InstanceManager;
import com.l2jserver.gameserver.instancemanager.InstanceManager.InstanceWorld;
import com.l2jserver.gameserver.model.L2CharPosition;
import com.l2jserver.gameserver.model.L2CommandChannel;
import com.l2jserver.gameserver.model.L2Party;
import com.l2jserver.gameserver.model.L2Skill;
import com.l2jserver.gameserver.model.L2Territory;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.L2Object.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.L2Trap;
import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ExShowScreenMessage;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.skills.SkillHolder;
import com.l2jserver.gameserver.util.Util;
import com.l2jserver.util.Rnd;
/**
* TODO:
* <ul>
* <li>No random mob spawns after mob kill.</li>
* <li>Implement Seed of Destruction Defense state and one party instances.</li>
* <li>Use proper zone spawn system.</li>
* </ul>
* Please maintain consistency between the Seed scripts.
* @author Gigiikun
*/
public class Stage1 extends Quest
{
private class SOD1World extends InstanceWorld
{
public Map<L2Npc,Boolean> npcList = new FastMap<L2Npc,Boolean>();
public int deviceSpawnedMobCount = 0;
public Lock lock = new ReentrantLock();
public SOD1World()
{
}
}
private static class SODSpawn
{
public boolean isZone = false;
public boolean isNeededNextFlag = false;
public int npcId;
public int x = 0;
public int y = 0;
public int z = 0;
public int h = 0;
public int zone = 0;
public int count = 0;
}
private static final String qn = "SoDStage1";
private static final int INSTANCEID = 110; // this is the client number
private static final int MIN_PLAYERS = 36;
private static final int MAX_PLAYERS = 45;
private static final int MAX_DEVICESPAWNEDMOBCOUNT = 100; // prevent too much mob spawn
private TIntObjectHashMap<L2Territory> _spawnZoneList = new TIntObjectHashMap<L2Territory>();
private TIntObjectHashMap<List<SODSpawn>> _spawnList = new TIntObjectHashMap<List<SODSpawn>>();
private List<Integer> _mustKillMobsId = new FastList<Integer>();
// teleports
private static final int[] ENTER_TELEPORT_1 = {-242759,219981,-9986};
private static final int[] ENTER_TELEPORT_2 = {-245800,220488,-12112};
private static final int[] CENTER_TELEPORT = {-245802,220528,-12104};
//Traps/Skills
private static final SkillHolder TRAP_HOLD = new SkillHolder(4186, 9); // 18720-18728
private static final SkillHolder TRAP_STUN = new SkillHolder(4072, 10); // 18729-18736
private static final SkillHolder TRAP_DAMAGE = new SkillHolder(5340, 4); // 18737-18770
private static final SkillHolder TRAP_SPAWN = new SkillHolder(10002, 1); // 18771-18774 : handled in this script
private static final int[] TRAP_18771_NPCS = { 22541, 22544, 22541, 22544 };
private static final int[] TRAP_OTHER_NPCS = { 22546, 22546, 22538, 22537 };
//NPCs
private static final int ALENOS = 32526;
private static final int TELEPORT = 32601;
//mobs
private static final int OBELISK = 18776;
private static final int POWERFUL_DEVICE = 18777;
private static final int THRONE_POWERFUL_DEVICE = 18778;
private static final int SPAWN_DEVICE = 18696;
private static final int TIAT = 29163;
private static final int TIAT_GUARD = 29162;
private static final int TIAT_GUARD_NUMBER = 5;
private static final int TIAT_VIDEO_NPC = 29169;
private static final L2CharPosition MOVE_TO_TIAT = new L2CharPosition( -250403, 207273, -11952, 16384 );
private static final L2CharPosition MOVE_TO_DOOR = new L2CharPosition( -251432, 214905, -12088, 16384 );
// TODO: handle this better
private static final int[] SPAWN_MOB_IDS = { 22536, 22537, 22538, 22539, 22540, 22541, 22542, 22543, 22544, 22547, 22550, 22551, 22552, 22596 };
// Doors/Walls/Zones
private static final int[] ATTACKABLE_DOORS = { 12240005, 12240006, 12240007, 12240008, 12240009, 12240010,
12240013, 12240014, 12240015, 12240016, 12240017, 12240018, 12240021, 12240022, 12240023, 12240024, 12240025,
12240026, 12240028, 12240029, 12240030
};
private static final int[] ENTRANCE_ROOM_DOORS = { 12240001, 12240002 };
private static final int[] SQUARE_DOORS = { 12240003, 12240004, 12240011, 12240012, 12240019, 12240020 };
private static final int SCOUTPASS_DOOR = 12240027;
private static final int FORTRESS_DOOR = 12240030;
private static final int THRONE_DOOR = 12240031;
// spawns
// Initialization at 6:30 am on Wednesday and Saturday
private static final int RESET_HOUR = 6;
private static final int RESET_MIN = 30;
private static final int RESET_DAY_1 = 4;
private static final int RESET_DAY_2 = 7;
private void load()
{
int spawnCount = 0;
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
File file = new File(Config.DATAPACK_ROOT + "/data/scripts/instances/SeedOfDestruction/data.xml");
if (!file.exists())
{
_log.severe("[Seed of Destruction] Missing data.xml. The quest wont work without it!");
return;
}
Document doc = factory.newDocumentBuilder().parse(file);
Node first = doc.getFirstChild();
if (first != null && "list".equalsIgnoreCase(first.getNodeName()))
{
for (Node n = first.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("npc".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("spawn".equalsIgnoreCase(d.getNodeName()))
{
NamedNodeMap attrs = d.getAttributes();
Node att = attrs.getNamedItem("npcId");
if (att == null)
{
_log.severe("[Seed of Destruction] Missing npcId in npc List, skipping");
continue;
}
int npcId = Integer.parseInt(attrs.getNamedItem("npcId").getNodeValue());
att = attrs.getNamedItem("flag");
if (att == null)
{
_log.severe("[Seed of Destruction] Missing flag in npc List npcId: "+npcId+", skipping");
continue;
}
int flag = Integer.parseInt(attrs.getNamedItem("flag").getNodeValue());
if (!_spawnList.contains(flag))
_spawnList.put(flag, new FastList<SODSpawn>());
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
if ("loc".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
SODSpawn spw = new SODSpawn();
spw.npcId = npcId;
att = attrs.getNamedItem("x");
if (att != null)
spw.x = Integer.parseInt(att.getNodeValue());
else
continue;
att = attrs.getNamedItem("y");
if (att != null)
spw.y = Integer.parseInt(att.getNodeValue());
else
continue;
att = attrs.getNamedItem("z");
if (att != null)
spw.z = Integer.parseInt(att.getNodeValue());
else
continue;
att = attrs.getNamedItem("heading");
if (att != null)
spw.h = Integer.parseInt(att.getNodeValue());
else
continue;
att = attrs.getNamedItem("mustKill");
if (att != null)
spw.isNeededNextFlag = Boolean.parseBoolean(att.getNodeValue());
if (spw.isNeededNextFlag)
_mustKillMobsId.add(npcId);
_spawnList.get(flag).add(spw);
spawnCount++;
}
else if ("zone".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
SODSpawn spw = new SODSpawn();
spw.npcId = npcId;
spw.isZone = true;
att = attrs.getNamedItem("id");
if (att != null)
spw.zone = Integer.parseInt(att.getNodeValue());
else
continue;
att = attrs.getNamedItem("count");
if (att != null)
spw.count = Integer.parseInt(att.getNodeValue());
else
continue;
att = attrs.getNamedItem("mustKill");
if (att != null)
spw.isNeededNextFlag = Boolean.parseBoolean(att.getNodeValue());
if (spw.isNeededNextFlag)
_mustKillMobsId.add(npcId);
_spawnList.get(flag).add(spw);
spawnCount++;
}
}
}
}
}
else if ("spawnZones".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("zone".equalsIgnoreCase(d.getNodeName()))
{
NamedNodeMap attrs = d.getAttributes();
Node att = attrs.getNamedItem("id");
if (att == null)
{
_log.severe("[Seed of Destruction] Missing id in spawnZones List, skipping");
continue;
}
int id = Integer.parseInt(att.getNodeValue());
att = attrs.getNamedItem("minZ");
if (att == null)
{
_log.severe("[Seed of Destruction] Missing minZ in spawnZones List id: "+id+", skipping");
continue;
}
int minz = Integer.parseInt(att.getNodeValue());
att = attrs.getNamedItem("maxZ");
if (att == null)
{
_log.severe("[Seed of Destruction] Missing maxZ in spawnZones List id: "+id+", skipping");
continue;
}
int maxz = Integer.parseInt(att.getNodeValue());
L2Territory ter = new L2Territory(id);
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
if ("point".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
int x,y;
att = attrs.getNamedItem("x");
if (att != null)
x = Integer.parseInt(att.getNodeValue());
else
continue;
att = attrs.getNamedItem("y");
if (att != null)
y = Integer.parseInt(att.getNodeValue());
else
continue;
ter.add(x, y, minz, maxz, 0);
}
}
_spawnZoneList.put(id, ter);
}
}
}
}
}
}
catch(Exception e)
{
_log.log(Level.WARNING, "[Seed of Destruction] Could not parse data.xml file: " + e.getMessage(), e);
}
if (Config.DEBUG)
{
_log.info("[Seed of Destruction] Loaded " + spawnCount + " spawns data.");
_log.info("[Seed of Destruction] Loaded " + _spawnZoneList.size() + " spawn zones data.");
}
}
protected void openDoor(int doorId,int instanceId)
{
for (L2DoorInstance door : InstanceManager.getInstance().getInstance(instanceId).getDoors())
if (door.getDoorId() == doorId)
door.openMe();
}
protected void closeDoor(int doorId,int instanceId)
{
for (L2DoorInstance door : InstanceManager.getInstance().getInstance(instanceId).getDoors())
if (door.getDoorId() == doorId)
if (door.getOpen())
door.closeMe();
}
private boolean checkConditions(L2PcInstance player)
{
final L2Party party = player.getParty();
if (party == null)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.NOT_IN_PARTY_CANT_ENTER));
return false;
}
final L2CommandChannel channel = player.getParty().getCommandChannel();
if (channel == null)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.NOT_IN_COMMAND_CHANNEL_CANT_ENTER));
return false;
}
else if (channel.getChannelLeader() != player)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ONLY_PARTY_LEADER_CAN_ENTER));
return false;
}
else if (channel.getMemberCount() < MIN_PLAYERS || channel.getMemberCount() > MAX_PLAYERS)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.PARTY_EXCEEDED_THE_LIMIT_CANT_ENTER));
return false;
}
for (L2PcInstance partyMember : channel.getMembers())
{
if (partyMember.getLevel() < 75)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_LEVEL_REQUIREMENT_NOT_SUFFICIENT);
sm.addPcName(partyMember);
party.broadcastToPartyMembers(sm);
return false;
}
if (!Util.checkIfInRange(1000, player, partyMember, true))
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_LOCATION_THAT_CANNOT_BE_ENTERED);
sm.addPcName(partyMember);
party.broadcastToPartyMembers(sm);
return false;
}
Long reentertime = InstanceManager.getInstance().getInstanceTime(partyMember.getObjectId(), INSTANCEID);
if (System.currentTimeMillis() < reentertime)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_MAY_NOT_REENTER_YET);
sm.addPcName(partyMember);
party.broadcastToPartyMembers(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 int enterInstance(L2PcInstance player, String template, int[] coords)
{
int instanceId = 0;
//check for existing instances for this player
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
//existing instance
if (world != null)
{
if (!(world instanceof SOD1World))
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ALREADY_ENTERED_ANOTHER_INSTANCE_CANT_ENTER));
return 0;
}
teleportPlayer(player, coords, world.instanceId);
return world.instanceId;
}
//New instance
else
{
if (!checkConditions(player))
return 0;
instanceId = InstanceManager.getInstance().createDynamicInstance(template);
world = new SOD1World();
world.instanceId = instanceId;
world.status = 0;
InstanceManager.getInstance().addWorld(world);
spawnState((SOD1World)world);
for (L2DoorInstance door : InstanceManager.getInstance().getInstance(instanceId).getDoors())
if (Util.contains(ATTACKABLE_DOORS, door.getDoorId()))
door.setIsAttackableDoor(true);
_log.info("Seed of Destruction started " + template + " Instance: " + instanceId + " created by player: " + player.getName());
// teleport players
if (player.getParty() == null || player.getParty().getCommandChannel() == null)
{
teleportPlayer(player, coords, instanceId);
world.allowed.add(player.getObjectId());
}
else
{
for (L2PcInstance channelMember : player.getParty().getCommandChannel().getMembers())
{
teleportPlayer(channelMember, coords, instanceId);
world.allowed.add(channelMember.getObjectId());
}
}
return instanceId;
}
}
protected boolean checkKillProgress(L2Npc mob, SOD1World world)
{
if (world.npcList.containsKey(mob))
world.npcList.put(mob, true);
for(boolean isDead: world.npcList.values())
if (!isDead)
return false;
return true;
}
private void spawnFlaggedNPCs(SOD1World world, int flag)
{
if (world.lock.tryLock())
{
try
{
for(SODSpawn spw : _spawnList.get(flag))
{
if (spw.isZone)
{
for(int i = 0; i < spw.count; i++)
{
if (_spawnZoneList.contains(spw.zone))
{
int[] point = _spawnZoneList.get(spw.zone).getRandomPoint();
spawn(world, spw.npcId, point[0], point[1], GeoData.getInstance().getSpawnHeight(point[0], point[1], point[2], point[3],null), Rnd.get(65535), spw.isNeededNextFlag);
}
else
_log.info("[Seed of Destruction] Missing zone: " + spw.zone);
}
}
else
spawn(world, spw.npcId, spw.x, spw.y, spw.z, spw.h, spw.isNeededNextFlag);
}
}
finally
{
world.lock.unlock();
}
}
}
protected boolean spawnState(SOD1World world)
{
if (world.lock.tryLock())
{
try
{
world.npcList.clear();
switch(world.status)
{
case 0:
spawnFlaggedNPCs(world, 0);
break;
case 1:
ExShowScreenMessage message1 = new ExShowScreenMessage(1,0,5,0,1,0,0,false,10000,1,"The enemies have attacked. Everyone come out and fight!!!! ... Urgh~!");
sendScreenMessage(world, message1);
for(int i : ENTRANCE_ROOM_DOORS)
openDoor(i,world.instanceId);
spawnFlaggedNPCs(world, 1);
break;
case 2:
case 3:
// handled elsewhere
return true;
case 4:
ExShowScreenMessage message2 = new ExShowScreenMessage(1,0,5,0,1,0,0,false,10000,1,"Obelisk has collapsed. Don't let the enemies jump around wildly anymore!!!!");
sendScreenMessage(world, message2);
for(int i : SQUARE_DOORS)
openDoor(i,world.instanceId);
spawnFlaggedNPCs(world, 4);
break;
case 5:
openDoor(SCOUTPASS_DOOR,world.instanceId);
spawnFlaggedNPCs(world, 3);
spawnFlaggedNPCs(world, 5);
break;
case 6:
openDoor(THRONE_DOOR,world.instanceId);
break;
case 7:
spawnFlaggedNPCs(world, 7);
break;
case 8:
ExShowScreenMessage message4 = new ExShowScreenMessage(1,0,5,0,1,0,0,false,10000,1,"Come out, warriors. Protect Seed of Destruction");
sendScreenMessage(world, message4);
world.deviceSpawnedMobCount = 0;
spawnFlaggedNPCs(world, 8);
break;
case 9:
// instance end
break;
}
world.status++;
return true;
}
finally
{
world.lock.unlock();
}
}
return false;
}
protected void spawn(SOD1World world, int npcId, int x, int y, int z, int h, boolean addToKillTable)
{
// traps
if (npcId >= 18720 && npcId <= 18774)
{
L2Skill skill = null;
if (npcId <= 18728)
skill = TRAP_HOLD.getSkill();
else if (npcId <= 18736)
skill = TRAP_STUN.getSkill();
else if (npcId <= 18770)
skill = TRAP_DAMAGE.getSkill();
else
skill = TRAP_SPAWN.getSkill();
addTrap(npcId, x, y, z, h, skill, world.instanceId);
return;
}
L2Npc npc = addSpawn(npcId, x, y, z, h, false,0,false,world.instanceId);
if (addToKillTable)
world.npcList.put(npc, false);
npc.setIsNoRndWalk(true);
if (npc.isInstanceType(InstanceType.L2Attackable))
((L2Attackable)npc).setSeeThroughSilentMove(true);
if (npcId == TIAT_VIDEO_NPC)
{
startQuestTimer("DoorCheck", 10000, npc, null);
}
else if (npcId == SPAWN_DEVICE)
{
npc.disableCoreAI(true);
startQuestTimer("Spawn", 10000, npc, null, true);
}
else if (npcId == TIAT)
{
for(int i = 0; i < TIAT_GUARD_NUMBER; i++)
addMinion((L2MonsterInstance) npc, TIAT_GUARD);
}
}
protected void setInstanceTimeRestrictions(SOD1World world)
{
Calendar reenter = Calendar.getInstance();
reenter.set(Calendar.MINUTE, RESET_MIN);
reenter.set(Calendar.HOUR_OF_DAY, RESET_HOUR);
// if time is >= RESET_HOUR - roll to the next day
if (reenter.getTimeInMillis() <= System.currentTimeMillis())
reenter.add(Calendar.DAY_OF_MONTH, 1);
if (reenter.get(Calendar.DAY_OF_WEEK) <= RESET_DAY_1)
while(reenter.get(Calendar.DAY_OF_WEEK) != RESET_DAY_1)
reenter.add(Calendar.DAY_OF_MONTH, 1);
else
while(reenter.get(Calendar.DAY_OF_WEEK) != RESET_DAY_2)
reenter.add(Calendar.DAY_OF_MONTH, 1);
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.INSTANT_ZONE_S1_RESTRICTED);
sm.addString(InstanceManager.getInstance().getInstanceIdName(INSTANCEID));
// set instance reenter time for all allowed players
for (int objectId : world.allowed)
{
L2PcInstance player = L2World.getInstance().getPlayer(objectId);
InstanceManager.getInstance().setInstanceTime(objectId, INSTANCEID, reenter.getTimeInMillis());
if (player != null && player.isOnline())
player.sendPacket(sm);
}
}
private void sendScreenMessage(SOD1World world, ExShowScreenMessage message)
{
for(int objId : world.allowed)
{
L2PcInstance player = L2World.getInstance().getPlayer(objId);
if (player != null)
player.sendPacket(message);
}
}
@Override
public String onSpawn (L2Npc npc)
{
if (npc.getNpcId() == TIAT_GUARD)
startQuestTimer("GuardThink", 2500 + Rnd.get(-200, 200), npc, null, true);
else
npc.disableCoreAI(true);
return super.onSpawn(npc);
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isPet)
{
if (isPet == false && player != null)
{
InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(player.getInstanceId());
if (tmpworld instanceof SOD1World)
{
SOD1World world = (SOD1World) tmpworld;
if (world.status == 7)
{
if (spawnState(world))
{
for(int objId : world.allowed)
{
L2PcInstance pl = L2World.getInstance().getPlayer(objId);
if (pl != null)
pl.showQuestMovie(5);
}
npc.deleteMe();
}
}
}
}
return null;
}
@Override
public String onAttack (L2Npc npc, L2PcInstance attacker, int damage, boolean isPet, L2Skill skill)
{
InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof SOD1World)
{
SOD1World world = (SOD1World) tmpworld;
if (world.status == 2 && npc.getNpcId() == OBELISK)
{
world.status = 4;
spawnFlaggedNPCs(world, 3);
}
else if (world.status == 3 && npc.getNpcId() == OBELISK)
{
world.status = 4;
spawnFlaggedNPCs(world, 2);
}
else if (world.status <= 8 && npc.getNpcId() == TIAT)
{
if (npc.getCurrentHp() < (npc.getMaxHp() / 2))
{
if (spawnState(world))
{
startQuestTimer("TiatFullHp", 3000, npc, null);
setInstanceTimeRestrictions(world);
}
}
}
}
return null;
}
@Override
public String onAdvEvent (String event, L2Npc npc, L2PcInstance player)
{
InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof SOD1World)
{
SOD1World world = (SOD1World) tmpworld;
if (event.equalsIgnoreCase("Spawn"))
{
L2PcInstance target = L2World.getInstance().getPlayer(world.allowed.get(Rnd.get(world.allowed.size())));
if (world.deviceSpawnedMobCount < MAX_DEVICESPAWNEDMOBCOUNT
&& target != null && target.getInstanceId() == npc.getInstanceId()
&& !target.isDead())
{
L2Attackable mob = (L2Attackable) addSpawn(SPAWN_MOB_IDS[Rnd.get(SPAWN_MOB_IDS.length)], npc.getSpawn().getLocx(), npc.getSpawn().getLocy(), npc.getSpawn().getLocz(), npc.getSpawn().getHeading(), false,0,false,world.instanceId);
world.deviceSpawnedMobCount++;
mob.setSeeThroughSilentMove(true);
mob.setRunning();
if (world.status >= 7)
mob.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, MOVE_TO_TIAT);
else
mob.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, MOVE_TO_DOOR);
}
}
else if (event.equalsIgnoreCase("DoorCheck"))
{
L2DoorInstance tmp = InstanceManager.getInstance().getInstance(npc.getInstanceId()).getDoor(FORTRESS_DOOR);
if (tmp.getCurrentHp() < tmp.getMaxHp())
{
world.deviceSpawnedMobCount = 0;
spawnFlaggedNPCs(world,6);
ExShowScreenMessage message3 = new ExShowScreenMessage(1,0,5,0,1,0,0,false,10000,1,"Enemies are trying to destroy the fortress. Everyone defend the fortress!!!!");
sendScreenMessage(world, message3);
}
else
startQuestTimer("DoorCheck", 10000, npc, null);
}
else if (event.equalsIgnoreCase("TiatFullHp"))
{
if (!npc.isStunned() && !npc.isInvul())
npc.setCurrentHp(npc.getMaxHp());
}
else if (event.equalsIgnoreCase("BodyGuardThink"))
{
L2Character mostHate = ((L2Attackable)npc).getMostHated();
if (mostHate != null)
{
double dist = Util.calculateDistance(mostHate.getXdestination(), mostHate.getYdestination(), npc.getSpawn().getLocx(), npc.getSpawn().getLocy());
if (dist > 900)
((L2Attackable)npc).reduceHate(mostHate, ((L2Attackable)npc).getHating(mostHate));
mostHate = ((L2Attackable)npc).getMostHated();
if (mostHate != null || ((L2Attackable)npc).getHating(mostHate) < 5)
((L2Attackable)npc).returnHome();
}
}
}
return "";
}
@Override
public String onKill( L2Npc npc, L2PcInstance player, boolean isPet)
{
if (npc.getNpcId() == SPAWN_DEVICE)
{
this.cancelQuestTimer("Spawn", npc, null);
return "";
}
InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof SOD1World)
{
SOD1World world = (SOD1World) tmpworld;
if (world.status == 1)
{
if (checkKillProgress(npc, world))
spawnState(world);
}
else if (world.status == 2)
{
if (checkKillProgress(npc, world))
world.status++;
}
else if (world.status == 4 && npc.getNpcId() == OBELISK)
{
spawnState(world);
}
else if (world.status == 5 && npc.getNpcId() == POWERFUL_DEVICE)
{
if (checkKillProgress(npc, world))
spawnState(world);
}
else if (world.status == 6 && npc.getNpcId() == THRONE_POWERFUL_DEVICE)
{
if (checkKillProgress(npc, world))
spawnState(world);
}
else if (world.status >= 7)
{
if (npc.getNpcId() == TIAT)
{
world.status++;
for(int objId : world.allowed)
{
L2PcInstance pl = L2World.getInstance().getPlayer(objId);
if (pl != null)
pl.showQuestMovie(6);
}
for(L2Npc mob:InstanceManager.getInstance().getInstance(world.instanceId).getNpcs())
mob.deleteMe();
GraciaSeedsManager.getInstance().increaseSoDTiatKilled();
}
else if (npc.getNpcId() == TIAT_GUARD)
{
addMinion(((L2MonsterInstance)npc).getLeader(), TIAT_GUARD);
}
}
}
return "";
}
@Override
public String onTalk (L2Npc npc, L2PcInstance player)
{
int npcId = npc.getNpcId();
QuestState st = player.getQuestState(qn);
if (st == null)
st = newQuestState(player);
if (npcId == ALENOS)
{
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (GraciaSeedsManager.getInstance().getSoDState() == 1 || (world != null && world instanceof SOD1World))
enterInstance(player, "SeedOfDestructionStage1.xml", ENTER_TELEPORT_1);
else if (GraciaSeedsManager.getInstance().getSoDState() == 2)
teleportPlayer(player, ENTER_TELEPORT_2, 0);
}
else if (npcId == TELEPORT)
teleportPlayer(player, CENTER_TELEPORT, player.getInstanceId());
return "";
}
@Override
public String onTrapAction(L2Trap trap, L2Character trigger, TrapAction action)
{
InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(trap.getInstanceId());
if (tmpworld instanceof SOD1World)
{
SOD1World world = (SOD1World) tmpworld;
switch(action)
{
case TRAP_TRIGGERED:
if (trap.getNpcId() == 18771)
for(int npcId : TRAP_18771_NPCS)
addSpawn(npcId, trap.getX(), trap.getY(), trap.getZ(), trap.getHeading(), true, 0, true, world.instanceId);
else
for(int npcId : TRAP_OTHER_NPCS)
addSpawn(npcId, trap.getX(), trap.getY(), trap.getZ(), trap.getHeading(), true, 0, true, world.instanceId);
break;
}
}
return null;
}
public Stage1(int questId, String name, String descr)
{
super(questId, name, descr);
load();
addStartNpc(ALENOS);
addTalkId(ALENOS);
addStartNpc(TELEPORT);
addTalkId(TELEPORT);
addAttackId(OBELISK);
addSpawnId(OBELISK);
addKillId(OBELISK);
addSpawnId(POWERFUL_DEVICE);
addKillId(POWERFUL_DEVICE);
addSpawnId(THRONE_POWERFUL_DEVICE);
addKillId(THRONE_POWERFUL_DEVICE);
addAttackId(TIAT);
addKillId(TIAT);
addKillId(SPAWN_DEVICE);
addSpawnId(TIAT_GUARD);
addKillId(TIAT_GUARD);
addAggroRangeEnterId(TIAT_VIDEO_NPC);
// registering spawn traps which handled in this script
for(int i = 18771; i <= 18774; i++)
addTrapActionId(i);
for(int mobId : _mustKillMobsId)
addKillId(mobId);
}
public static void main(String[] args)
{
// now call the constructor (starts up the)
new Stage1(-1,qn,"instances");
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,7 @@
<html><body>Officer Tepios:<br>
I'm very impressed.<br>
No one has ever broken through this fast to the Hall of Suffering. Extraordinary! In recognition of your achievement, I will give you a <font color="LEVEL">Jeweled Battle Supply</font>.<br>
It is granted only to those who achieve an especially impressive feat in battle.<br>
Your leader may receive it on your behalf.<br>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Officer Tepios:<br>
Unknown Text!<br>
The reward is <font color="LEVEL">Mother-of-Pearl Ornamented Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Officer Tepios:<br>
Unknown Text!<br>
The reward is <font color="LEVEL">Gold-Ornamented Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Officer Tepios:<br>
Unknown Text!<br>
The reward is <font color="LEVEL">Silver-Ornamented Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Officer Tepios:<br>
Unknown Text!<br>
The reward is <font color="LEVEL">Bronze-Ornamented Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Officer Tepios:<br>
Unknown Text!<br>
The reward is <font color="LEVEL">Non-Ornamented Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Officer Tepios:<br>
Unknown Text!<br>
The reward is <font color="LEVEL">Weak-Looking Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Officer Tepios:<br>
Unknown Text!<br>
The reward is <font color="LEVEL">Sad-Looking Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Officer Tepios:<br>
Unknown Text!<br>
The reward is <font color="LEVEL">Poor-Looking Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>
@@ -0,0 +1,6 @@
<html><body>Officer Tepios:<br>
I'm very disappointed.<br>
If I had known your skills were this embarrasingly poor, I would not have assigned you this mission. You're lucky to still be alive! Still, a promise is a promise, so I will give you this <font color="LEVEL">Worthless Battle Supply</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>
@@ -0,0 +1,3 @@
<html><body>Officer Tepios:<br>
I told you that I would give you the reward through your leader. Please bring %ptLeader% here. Then we can proceed.
</body></html>
@@ -0,0 +1,3 @@
<html><body>Officer Tepios:<br>
Didn't we conclude our business? You can rest for a while or use the Scroll of Escape I gave you to leave.
</body></html>
@@ -0,0 +1,634 @@
/*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.SeedOfInfinity;
import java.util.Calendar;
import java.util.Map;
import javolution.util.FastMap;
import com.l2jserver.gameserver.ai.CtrlEvent;
import com.l2jserver.gameserver.cache.HtmCache;
import com.l2jserver.gameserver.datatables.SkillTable;
import com.l2jserver.gameserver.instancemanager.InstanceManager;
import com.l2jserver.gameserver.instancemanager.InstanceManager.InstanceWorld;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Party;
import com.l2jserver.gameserver.model.L2Skill;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.templates.skills.L2SkillType;
import com.l2jserver.gameserver.util.Util;
import com.l2jserver.util.Rnd;
/*
Todo:
- after 15mins mobs are despawned
- bound instance to quests
Contributing authors: Gigiikun, ZakaX, Didldak
Please maintain consistency between the Seed scripts.
*/
public class HallOfSuffering extends Quest
{
private class HSWorld extends InstanceWorld
{
public Map<L2Npc,Boolean> npcList = new FastMap<L2Npc,Boolean>();
public L2Npc klodekus = null;
public L2Npc klanikus = null;
public boolean isBossesAttacked = false;
public long startTime = 0;
public String ptLeaderName = "";
public int rewardItemId = -1;
public String rewardHtm = "";
public boolean isRewarded = false;
public HSWorld()
{
}
}
private static final String qn = "SeedOfInfinity";
private static final int INSTANCEID = 115; // this is the client number
private static final boolean debug = false;
//Items
//NPCs
private static final int MOUTHOFEKIMUS = 32537;
private static final int TEPIOS = 32530;
// teleports
private static final int[] ENTER_TELEPORT = {-187567,205570,-9538};
//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 = 18705;
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
// 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};
//etc
private static final int BOSS_INVUL_TIME = 30000; // in milisex
private static final int BOSS_MINION_SPAWN_TIME = 60000; // in milisex
private static final int BOSS_RESSURECT_TIME = 20000; // in milisex
// Instance reenter time
// default: 24h
private static final int INSTANCEPENALTY = 24;
private boolean checkConditions(L2PcInstance player)
{
if (debug)
return true;
L2Party party = player.getParty();
if (party == null)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.NOT_IN_PARTY_CANT_ENTER));
return false;
}
if (party.getLeader() != player)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ONLY_PARTY_LEADER_CAN_ENTER));
return false;
}
for (L2PcInstance partyMember : party.getPartyMembers())
{
if (partyMember.getLevel() < 75)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_LEVEL_REQUIREMENT_NOT_SUFFICIENT);
sm.addPcName(partyMember);
party.broadcastToPartyMembers(sm);
return false;
}
if (!Util.checkIfInRange(1000, player, partyMember, true))
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_LOCATION_THAT_CANNOT_BE_ENTERED);
sm.addPcName(partyMember);
party.broadcastToPartyMembers(sm);
return false;
}
Long reentertime = InstanceManager.getInstance().getInstanceTime(partyMember.getObjectId(), INSTANCEID);
if (System.currentTimeMillis() < reentertime)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_MAY_NOT_REENTER_YET);
sm.addPcName(partyMember);
party.broadcastToPartyMembers(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 int enterInstance(L2PcInstance player, String template, int[] coords)
{
int instanceId = 0;
//check for existing instances for this player
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
//existing instance
if (world != null)
{
if (!(world instanceof HSWorld))
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ALREADY_ENTERED_ANOTHER_INSTANCE_CANT_ENTER));
return 0;
}
teleportPlayer(player, coords, world.instanceId);
return world.instanceId;
}
//New instance
else
{
if (!checkConditions(player))
return 0;
L2Party party = player.getParty();
instanceId = InstanceManager.getInstance().createDynamicInstance(template);
world = new HSWorld();
world.instanceId = instanceId;
world.templateId = INSTANCEID;
world.status = 0;
((HSWorld)world).startTime = System.currentTimeMillis();
((HSWorld)world).ptLeaderName = player.getName();
InstanceManager.getInstance().addWorld(world);
_log.info("Hall Of Suffering started " + template + " Instance: " + instanceId + " created by player: " + player.getName());
runTumors((HSWorld)world);
// teleport players
if (player.getParty() == null)
{
teleportPlayer(player, coords, instanceId);
world.allowed.add(player.getObjectId());
}
else
{
for (L2PcInstance partyMember : party.getPartyMembers())
{
teleportPlayer(partyMember, coords, instanceId);
world.allowed.add(partyMember.getObjectId());
if (partyMember.getQuestState(qn) == null)
newQuestState(partyMember);
}
}
return instanceId;
}
}
protected boolean checkKillProgress(L2Npc mob, HSWorld 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;
}
_log.warning("");
return new int[][]{};
}
protected void runTumors(HSWorld world)
{
for (int[] mob : getRoomSpawns(world.status))
{
L2Npc npc = addSpawn(mob[0], mob[1], mob[2], mob[3], 0, false,0,false,world.instanceId);
world.npcList.put(npc, false);
}
L2Npc mob = addSpawn(TUMOR_ALIVE, TUMOR_SPAWNS[world.status][0], TUMOR_SPAWNS[world.status][1], TUMOR_SPAWNS[world.status][2], 0, false,0,false,world.instanceId);
mob.disableCoreAI(true);
mob.setIsImmobilized(true);
mob.setCurrentHp(mob.getMaxHp()*0.5);
world.npcList.put(mob, false);
world.status++;
}
protected void runTwins(HSWorld world)
{
world.status++;
world.klodekus = addSpawn(TWIN_SPAWNS[0][0], TWIN_SPAWNS[0][1], TWIN_SPAWNS[0][2], TWIN_SPAWNS[0][3], 0, false,0,false,world.instanceId);
world.klanikus = addSpawn(TWIN_SPAWNS[1][0], TWIN_SPAWNS[1][1], TWIN_SPAWNS[1][2], TWIN_SPAWNS[1][3], 0, false,0,false,world.instanceId);
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);
}
private void calcRewardItemId(HSWorld world)
{
Long finishDiff = System.currentTimeMillis() - world.startTime;
if (finishDiff < 1260000)
{
world.rewardHtm = "32530-00.htm";
world.rewardItemId = 13777;
}
else if (finishDiff < 1380000)
{
world.rewardHtm = "32530-01.htm";
world.rewardItemId = 13778;
}
else if (finishDiff < 1500000)
{
world.rewardHtm = "32530-02.htm";
world.rewardItemId = 13779;
}
else if (finishDiff < 1620000)
{
world.rewardHtm = "32530-03.htm";
world.rewardItemId = 13780;
}
else if (finishDiff < 1740000)
{
world.rewardHtm = "32530-04.htm";
world.rewardItemId = 13781;
}
else if (finishDiff < 1860000)
{
world.rewardHtm = "32530-05.htm";
world.rewardItemId = 13782;
}
else if (finishDiff < 1980000)
{
world.rewardHtm = "32530-06.htm";
world.rewardItemId = 13783;
}
else if (finishDiff < 2100000)
{
world.rewardHtm = "32530-07.htm";
world.rewardItemId = 13784;
}
else if (finishDiff < 2220000)
{
world.rewardHtm = "32530-08.htm";
world.rewardItemId = 13785;
}
else
{
world.rewardHtm = "32530-09.htm";
world.rewardItemId = 13786;
}
}
private String getPtLeaderText(L2PcInstance player, HSWorld world)
{
String htmltext = HtmCache.getInstance().getHtm(player.getHtmlPrefix(),"/data/scripts/instances/SeedOfInfinity/32530-10.htm");
htmltext = htmltext.replaceAll("%ptLeader%", String.valueOf(world.ptLeaderName));
return htmltext;
}
@Override
public String onSkillSee (L2Npc npc, L2PcInstance caster, L2Skill skill, L2Object[] targets, boolean isPet)
{
if (skill.getSkillType() == L2SkillType.BALANCE_LIFE || skill.getSkillType() == L2SkillType.HEAL
|| skill.getSkillType() == L2SkillType.HEAL_PERCENT || skill.getSkillType() == L2SkillType.HEAL_STATIC)
{
int hate = 2 * skill.getAggroPoints();
if (hate < 2)
hate = 1000;
((L2Attackable)npc).addDamageHate(caster,0,hate);
}
return super.onSkillSee(npc, caster, skill, targets, isPet);
}
@Override
public String onAdvEvent (String event, L2Npc npc, L2PcInstance player)
{
InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HSWorld)
{
HSWorld world = (HSWorld) tmpworld;
if (event.equalsIgnoreCase("spawnBossGuards"))
{
if (!world.klanikus.isInCombat() && !world.klodekus.isInCombat())
{
world.isBossesAttacked = false;
return "";
}
L2Npc mob = addSpawn(TWIN_MOBIDS[Rnd.get(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 (Rnd.get(100) < 33)
{
mob = addSpawn(TWIN_MOBIDS[Rnd.get(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"))
{
L2Skill skill = SkillTable.getInstance().getInfo(5824, 1);
L2Npc aliveTwin = (world.klanikus == npc ? world.klodekus : world.klanikus);
npc.doRevive();
npc.doCast(skill);
npc.setCurrentHp(aliveTwin.getCurrentHp());
// get most hated of other boss
L2Character hated = ((L2MonsterInstance)aliveTwin).getMostHated();
if(hated != null) //to prevent revived idling
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 isPet, L2Skill skill)
{
InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HSWorld)
{
if (!((HSWorld)tmpworld).isBossesAttacked)
{
((HSWorld) tmpworld).isBossesAttacked = true;
Calendar reenter = Calendar.getInstance();
reenter.add(Calendar.HOUR, INSTANCEPENALTY);
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.INSTANT_ZONE_S1_RESTRICTED);
sm.addString(InstanceManager.getInstance().getInstanceIdName(tmpworld.templateId));
// set instance reenter time for all allowed players
for (int objectId : tmpworld.allowed)
{
L2PcInstance player = L2World.getInstance().getPlayer(objectId);
if (player != null && player.isOnline())
{
InstanceManager.getInstance().setInstanceTime(objectId, tmpworld.templateId, reenter.getTimeInMillis());
player.sendPacket(sm);
}
}
startQuestTimer("spawnBossGuards", BOSS_MINION_SPAWN_TIME, npc, null);
startQuestTimer("isTwinSeparated", 10000, npc, null);
}
else if (damage >= npc.getCurrentHp())
{
if (((HSWorld)tmpworld).klanikus.isDead())
{
((HSWorld)tmpworld).klanikus.setIsDead(false);
((HSWorld)tmpworld).klanikus.doDie(attacker);
((HSWorld)tmpworld).klodekus.doDie(attacker);
}
else if (((HSWorld)tmpworld).klodekus.isDead())
{
((HSWorld)tmpworld).klodekus.setIsDead(false);
((HSWorld)tmpworld).klodekus.doDie(attacker);
((HSWorld)tmpworld).klanikus.doDie(attacker);
}
else
{
bossSimpleDie(npc);
startQuestTimer("ressurectTwin", BOSS_RESSURECT_TIME, npc, null);
}
}
}
return null;
}
@Override
public String onKill( L2Npc npc, L2PcInstance player, boolean isPet)
{
InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof HSWorld)
{
HSWorld world = (HSWorld) tmpworld;
if (npc.getNpcId() == TUMOR_ALIVE)
addSpawn(TUMOR_DEAD, npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), false, 0, false, npc.getInstanceId());
if (world.status < 5)
{
if (checkKillProgress(npc, world))
runTumors(world);
}
else if (world.status == 5)
{
if (checkKillProgress(npc, world))
runTwins(world);
}
else if (world.status == 6 && (npc.getNpcId() == KLODEKUS || npc.getNpcId() == KLANIKUS))
{
if (world.klanikus.isDead() && world.klodekus.isDead())
{
world.status++;
// instance end
calcRewardItemId(world);
world.klanikus = null;
world.klodekus = null;
this.cancelQuestTimers("ressurectTwin");
this.cancelQuestTimers("spawnBossGuards");
this.cancelQuestTimers("isTwinSeparated");
addSpawn(TEPIOS, TEPIOS_SPAWN[0], TEPIOS_SPAWN[1], TEPIOS_SPAWN[2], 0, false,0,false,world.instanceId);
}
}
}
return "";
}
@Override
public String onFirstTalk (L2Npc npc, L2PcInstance player)
{
if (npc.getNpcId() == TEPIOS)
{
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (((HSWorld)world).rewardItemId == -1)
{
_log.warning("Hall of Suffering: " + player.getName() + "(" + player.getObjectId() + ") is try to cheat!");
return getPtLeaderText(player, (HSWorld)world);
}
else if (((HSWorld)world).isRewarded)
return "32530-11.htm";
else if (player.getParty() != null && player.getParty().getPartyLeaderOID() == player.getObjectId())
return ((HSWorld)world).rewardHtm;
return getPtLeaderText(player, (HSWorld)world);
}
return "";
}
@Override
public String onTalk (L2Npc npc, L2PcInstance player)
{
int npcId = npc.getNpcId();
QuestState st = player.getQuestState(qn);
if (st == null)
st = newQuestState(player);
if (npcId == MOUTHOFEKIMUS)
{
enterInstance(player, "HallOfSuffering.xml", ENTER_TELEPORT);
return "";
}
else if (npcId == TEPIOS)
{
InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (((HSWorld)world).rewardItemId == -1)
{
_log.warning("Hall of Suffering: " + player.getName() + "(" + player.getObjectId() + ") is try to cheat!");
return getPtLeaderText(player, (HSWorld)world);
}
else if (((HSWorld)world).isRewarded)
return "32530-11.htm";
else if (player.getParty() != null && player.getParty().getPartyLeaderOID() == player.getObjectId())
{
((HSWorld)world).isRewarded = true;
for(L2PcInstance pl : player.getParty().getPartyMembers())
{
st = pl.getQuestState(qn);
st.giveItems(736, 1);
st.giveItems(((HSWorld)world).rewardItemId, 1);
}
return "";
}
return getPtLeaderText(player, (HSWorld)world);
}
return "";
}
public HallOfSuffering(int questId, String name, String descr)
{
super(questId, name, descr);
addStartNpc(MOUTHOFEKIMUS);
addTalkId(MOUTHOFEKIMUS);
addStartNpc(TEPIOS);
addFirstTalkId(TEPIOS);
addTalkId(TEPIOS);
addKillId(TUMOR_ALIVE);
addKillId(KLODEKUS);
addKillId(KLANIKUS);
addAttackId(KLODEKUS);
addAttackId(KLANIKUS);
for(int mobId : TUMOR_MOBIDS)
{
addSkillSeeId(mobId);
addKillId(mobId);
}
}
public static void main(String[] args)
{
// now call the constructor (starts up the)
new HallOfSuffering(-1,qn,"instances");
}
}