Classic Interlude branch.

This commit is contained in:
MobiusDevelopment
2019-10-15 21:28:39 +00:00
parent 30b69e38e4
commit 481a1a019c
12853 changed files with 1597401 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai;
import java.util.logging.Logger;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.holders.MinionHolder;
import org.l2jmobius.gameserver.model.quest.Quest;
/**
* Abstract NPC AI class for datapack based AIs.
* @author UnAfraid, Zoey76
*/
public abstract class AbstractNpcAI extends Quest
{
protected final Logger LOGGER = Logger.getLogger(getClass().getName());
public AbstractNpcAI()
{
super(-1);
}
/**
* Simple on first talk event handler.
*/
@Override
public String onFirstTalk(Npc npc, PlayerInstance player)
{
return npc.getId() + ".html";
}
/**
* Registers the following events to the current script:<br>
* <ul>
* <li>ON_ATTACK</li>
* <li>ON_KILL</li>
* <li>ON_SPAWN</li>
* <li>ON_SPELL_FINISHED</li>
* <li>ON_SKILL_SEE</li>
* <li>ON_FACTION_CALL</li>
* <li>ON_AGGR_RANGE_ENTER</li>
* </ul>
* @param mobs
*/
public void registerMobs(int... mobs)
{
addAttackId(mobs);
addKillId(mobs);
addSpawnId(mobs);
addSpellFinishedId(mobs);
addSkillSeeId(mobs);
addAggroRangeEnterId(mobs);
addFactionCallId(mobs);
}
public void spawnMinions(Npc npc, String spawnName)
{
for (MinionHolder is : npc.getParameters().getMinionList(spawnName))
{
addMinion((MonsterInstance) npc, is.getId());
}
}
}

View File

@@ -0,0 +1,103 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.areas.CrumaTower;
import org.l2jmobius.gameserver.model.actor.Attackable;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.skills.Skill;
import ai.AbstractNpcAI;
/**
* Summon Pc AI.<br>
* Summon the player to the NPC on attack.
* @author Zoey76
*/
public class SummonPc extends AbstractNpcAI
{
// NPCs
private static final int PORTA = 20213;
private static final int PERUM = 20221;
// Skill
private static final SkillHolder SUMMON_PC = new SkillHolder(4161, 1);
private SummonPc()
{
addAttackId(PORTA, PERUM);
addSpellFinishedId(PORTA, PERUM);
}
@Override
public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon)
{
final int chance = getRandom(100);
final boolean attacked = npc.getVariables().getBoolean("attacked", false);
if ((npc.calculateDistance3D(attacker) > 300) && !attacked)
{
if (chance < 50)
{
if ((SUMMON_PC.getSkill().getMpConsume() < npc.getCurrentMp()) && (SUMMON_PC.getSkill().getHpConsume() < npc.getCurrentHp()) && !npc.isSkillDisabled(SUMMON_PC.getSkill()))
{
npc.setTarget(attacker);
npc.doCast(SUMMON_PC.getSkill());
}
if ((SUMMON_PC.getSkill().getMpConsume() < npc.getCurrentMp()) && (SUMMON_PC.getSkill().getHpConsume() < npc.getCurrentHp()) && !npc.isSkillDisabled(SUMMON_PC.getSkill()))
{
npc.setTarget(attacker);
npc.doCast(SUMMON_PC.getSkill());
npc.getVariables().set("attacked", true);
}
}
}
else if ((npc.calculateDistance3D(attacker) > 100) && !attacked)
{
final Attackable monster = (Attackable) npc;
if (monster.getMostHated() != null)
{
if (((monster.getMostHated() == attacker) && (chance < 50)) || (chance < 10))
{
if ((SUMMON_PC.getSkill().getMpConsume() < npc.getCurrentMp()) && (SUMMON_PC.getSkill().getHpConsume() < npc.getCurrentHp()) && !npc.isSkillDisabled(SUMMON_PC.getSkill()))
{
npc.setTarget(attacker);
npc.doCast(SUMMON_PC.getSkill());
npc.getVariables().set("attacked", true);
}
}
}
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
{
if ((skill.getId() == SUMMON_PC.getSkillId()) && !npc.isDead() && npc.getVariables().getBoolean("attacked", false))
{
player.teleToLocation(npc);
npc.getVariables().set("attacked", false);
}
return super.onSpellFinished(npc, player, skill);
}
public static void main(String[] args)
{
new SummonPc();
}
}

View File

@@ -0,0 +1,58 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.areas.DragonValley;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Playable;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import ai.AbstractNpcAI;
/**
* Cave Maiden, Keeper AI.
* @author proGenitor
*/
public class CaveMaiden extends AbstractNpcAI
{
// NPCs
private static final int CAVEMAIDEN = 20134;
private static final int CAVEKEEPER = 20246;
private static final int BANSHEE = 20412;
private CaveMaiden()
{
addKillId(CAVEMAIDEN, CAVEKEEPER);
}
@Override
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
{
if (getRandom(100) < 20)
{
final Npc spawnBanshee = addSpawn(BANSHEE, npc, false, 300000);
final Playable attacker = isSummon ? killer.getServitors().values().stream().findFirst().orElse(killer.getPet()) : killer;
addAttackPlayerDesire(spawnBanshee, attacker);
npc.deleteMe();
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new CaveMaiden();
}
}

View File

@@ -0,0 +1,120 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.areas.DungeonOfAbyss;
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.zone.ZoneType;
import ai.AbstractNpcAI;
/**
* @author Mobius
*/
public class DungeonOfAbyssZone extends AbstractNpcAI
{
private static final ZoneType ABYSS_WEST_ZONE_1 = ZoneManager.getInstance().getZoneByName("The West Dungeon of Abyss");
private static final ZoneType ABYSS_WEST_ZONE_2 = ZoneManager.getInstance().getZoneByName("The West Dungeon of Abyss 2nd");
private static final ZoneType ABYSS_EAST_ZONE_3 = ZoneManager.getInstance().getZoneByName("The East Dungeon of Abyss");
private static final ZoneType ABYSS_EAST_ZONE_4 = ZoneManager.getInstance().getZoneByName("The East Dungeon of Abyss 2nd");
private static final ZoneType ABYSS_WEST_ZONE_BOSS_1 = ZoneManager.getInstance().getZoneByName("The West Dungeon of Abyss Boss Room");
private static final ZoneType ABYSS_WEST_ZONE_BOSS_2 = ZoneManager.getInstance().getZoneByName("The West Dungeon of Abyss 2nd Boss Room");
private static final ZoneType ABYSS_EAST_ZONE_BOSS_3 = ZoneManager.getInstance().getZoneByName("The East Dungeon of Abyss Boss Room");
private static final ZoneType ABYSS_EAST_ZONE_BOSS_4 = ZoneManager.getInstance().getZoneByName("The East Dungeon of Abyss 2nd Boss Room");
private static final int EXIT_TIME = 60 * 60 * 1000; // 60 minute
private static final int EXIT_TIME_BOSS_ROOM = 30 * 60 * 1000; // 60 minute
private static final Location EXIT_LOCATION_1 = new Location(-120019, -182575, -6751); // Move to Magrit
private static final Location EXIT_LOCATION_2 = new Location(-119977, -179753, -6751); // Move to Ingrit
private static final Location EXIT_LOCATION_3 = new Location(-109554, -180408, -6753); // Move to Iris
private static final Location EXIT_LOCATION_4 = new Location(-109595, -177560, -6753); // Move to Rosammy
private DungeonOfAbyssZone()
{
addEnterZoneId(ABYSS_WEST_ZONE_1.getId(), ABYSS_WEST_ZONE_2.getId(), ABYSS_EAST_ZONE_3.getId(), ABYSS_EAST_ZONE_4.getId(), ABYSS_WEST_ZONE_BOSS_1.getId(), ABYSS_WEST_ZONE_BOSS_2.getId(), ABYSS_EAST_ZONE_BOSS_3.getId(), ABYSS_EAST_ZONE_BOSS_4.getId());
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (event.startsWith("EXIT_PLAYER") && (player != null))
{
if (event.contains(ABYSS_WEST_ZONE_1.getName()) && ABYSS_WEST_ZONE_1.getPlayersInside().contains(player))
{
player.teleToLocation(EXIT_LOCATION_1);
}
else if (event.contains(ABYSS_WEST_ZONE_2.getName()) && ABYSS_WEST_ZONE_2.getPlayersInside().contains(player))
{
player.teleToLocation(EXIT_LOCATION_2);
}
else if (event.contains(ABYSS_EAST_ZONE_3.getName()) && ABYSS_EAST_ZONE_3.getPlayersInside().contains(player))
{
player.teleToLocation(EXIT_LOCATION_3);
}
else if (event.contains(ABYSS_EAST_ZONE_4.getName()) && ABYSS_EAST_ZONE_4.getPlayersInside().contains(player))
{
player.teleToLocation(EXIT_LOCATION_4);
}
else if (event.contains(ABYSS_WEST_ZONE_BOSS_1.getName()) && ABYSS_WEST_ZONE_BOSS_1.getPlayersInside().contains(player))
{
player.teleToLocation(EXIT_LOCATION_1);
}
else if (event.contains(ABYSS_WEST_ZONE_BOSS_2.getName()) && ABYSS_WEST_ZONE_BOSS_2.getPlayersInside().contains(player))
{
player.teleToLocation(EXIT_LOCATION_2);
}
else if (event.contains(ABYSS_EAST_ZONE_BOSS_3.getName()) && ABYSS_EAST_ZONE_BOSS_3.getPlayersInside().contains(player))
{
player.teleToLocation(EXIT_LOCATION_3);
}
else if (event.contains(ABYSS_EAST_ZONE_BOSS_4.getName()) && ABYSS_EAST_ZONE_BOSS_4.getPlayersInside().contains(player))
{
player.teleToLocation(EXIT_LOCATION_4);
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onEnterZone(Creature creature, ZoneType zone)
{
if (creature.isPlayer())
{
final PlayerInstance player = creature.getActingPlayer();
cancelQuestTimer("EXIT_PLAYER" + ABYSS_WEST_ZONE_1.getName() + player.getObjectId(), null, player);
cancelQuestTimer("EXIT_PLAYER" + ABYSS_WEST_ZONE_2.getName() + player.getObjectId(), null, player);
cancelQuestTimer("EXIT_PLAYER" + ABYSS_EAST_ZONE_3.getName() + player.getObjectId(), null, player);
cancelQuestTimer("EXIT_PLAYER" + ABYSS_EAST_ZONE_4.getName() + player.getObjectId(), null, player);
cancelQuestTimer("EXIT_PLAYER" + ABYSS_WEST_ZONE_BOSS_1.getName() + player.getObjectId(), null, player);
cancelQuestTimer("EXIT_PLAYER" + ABYSS_WEST_ZONE_BOSS_2.getName() + player.getObjectId(), null, player);
cancelQuestTimer("EXIT_PLAYER" + ABYSS_EAST_ZONE_BOSS_3.getName() + player.getObjectId(), null, player);
cancelQuestTimer("EXIT_PLAYER" + ABYSS_EAST_ZONE_BOSS_4.getName() + player.getObjectId(), null, player);
startQuestTimer("EXIT_PLAYER" + zone.getName() + player.getObjectId(), zone.getName().contains("boss") ? EXIT_TIME_BOSS_ROOM : EXIT_TIME, null, player);
}
return super.onEnterZone(creature, zone);
}
public static void main(String[] args)
{
new DungeonOfAbyssZone();
}
}

View File

@@ -0,0 +1,8 @@
<html>body>Magrit:<br>
The Death Eater is the most powerful and dangerous creature in this prison.<br1>
If you have the <font color="LEVEL">Key from the Central Part of the Western Wing of the Dungeon of Abyss</font>, You can get to the Death Eater.<br1>
However, remember: you will be alone with him. No one will come to your rescue. In addition, you will only have <font color="LEVEL">30 minutes</font> to destroy it.<br>
If you decide to retreat or fail and want to try your luck some other time, you will need a new key.<br>
And more: if <font color="LEVEL">the quantity and weight of items in your inventory will exceed 80%</font>, You can not get a reward, so take care of an empty seat before the battle begins.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Magrit 3">Go to the Condemned of Abyss Prison</Button>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Magrit:<br>
An incident occurred in this terrifying prison and put the whole Kingdom of Aden at risk..<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Magrit 1">Go to the West Wing of the Dungeon of Abyss</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Magrit 2">Go to the 2nd entrance to the West Wing of the Dungeon of Abyss</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Chat 1">Go to the Condemned of Abyss Prison</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Magrit 4">Return to Aden</Button>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Ingrit:<br>
The Death Eater is the most powerful and dangerous creature in this prison.<br1>
If you have the <font color="LEVEL">Key from the Central Part of the Western Wing of the Dungeon of Abyss</font>, You can get to the Death Eater.<br1>
However, remember: you will be alone with him. No one will come to your rescue. In addition, you will only have <font color="LEVEL">30 minutes</font> to destroy it.<br>
If you decide to retreat or fail and want to try your luck some other time, you will need a new key.<br>
And more: if <font color="LEVEL">the quantity and weight of items in your inventory will exceed 80%</font>, You can not get a reward, so take care of an empty seat before the battle begins.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Ingrit 3">Go to the Condemned of Abyss Prison</Button>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Ingrit:<br>
An incident occurred in this terrifying prison and put the whole Kingdom of Aden at risk..<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Ingrit 1">Go to the West Wing of the Dungeon of Abyss</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Ingrit 2">Go to the 1nd entrance to the West Wing of the Dungeon of Abyss</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Chat 1">Go to the Condemned of Abyss Prison</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Ingrit 4">Return to Aden</Button>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Iris:<br>
The Death Eater is the most powerful and dangerous creature in this prison.<br1>
If you have the <font color="LEVEL">Key from the Central Part of the Western Wing of the Dungeon of Abyss</font>, You can get to the Death Eater.<br1>
However, remember: you will be alone with him. No one will come to your rescue. In addition, you will only have <font color="LEVEL">30 minutes</font> to destroy it.<br>
If you decide to retreat or fail and want to try your luck some other time, you will need a new key.<br>
And more: if <font color="LEVEL">the quantity and weight of items in your inventory will exceed 80%</font>, You can not get a reward, so take care of an empty seat before the battle begins.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Iris 3">Go to the Condemned of Abyss Prison</Button>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Iris:<br>
An incident occurred in this terrifying prison and put the whole Kingdom of Aden at risk..<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Iris 1">Go to the East Wing of the Dungeon of Abyss</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Iris 2">Go to the 2nd entrance to the East Wing of the Dungeon of Abyss</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Chat 1">Go to the Condemned of Abyss Prison</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Iris 4">Return to Aden</Button>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Rosammy:<br>
The Death Eater is the most powerful and dangerous creature in this prison.<br1>
If you have the <font color="LEVEL">Key from the Central Part of the Western Wing of the Dungeon of Abyss</font>, You can get to the Death Eater.<br1>
However, remember: you will be alone with him. No one will come to your rescue. In addition, you will only have <font color="LEVEL">30 minutes</font> to destroy it.<br>
If you decide to retreat or fail and want to try your luck some other time, you will need a new key.<br>
And more: if <font color="LEVEL">the quantity and weight of items in your inventory will exceed 80%</font>, You can not get a reward, so take care of an empty seat before the battle begins.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Rosammy 3">Go to the Condemned of Abyss Prison</Button>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Rosammy:<br>
An incident occurred in this terrifying prison and put the whole Kingdom of Aden at risk..<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Rosammy 1">Go to the East Wing of the Dungeon of Abyss</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Rosammy 2">Go to the 1nd entrance to the East Wing of the Dungeon of Abyss</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Chat 1">Go to the Condemned of Abyss Prison</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Rosammy 4">Return to Aden</Button>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,109 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.areas.DungeonOfAbyss.SoulTracker;
import java.util.HashMap;
import java.util.Map;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.quest.QuestState;
import ai.AbstractNpcAI;
/**
* @author QuangNguyen
*/
public class Ingrit extends AbstractNpcAI
{
// NPC
private static final int SOUL_TRACKER_INRGIT = 31775;
// Item
private static final int KEY_OF_WEST_WING = 90010;
// Locations
private static final Map<String, Location> LOCATIONS = new HashMap<>();
static
{
LOCATIONS.put("1", new Location(-119533, -179641, -6751)); // Join Room from Ingrit
LOCATIONS.put("2", new Location(-120325, -182444, -6752)); // Move to West Wing 1nd
LOCATIONS.put("3", new Location(-116975, -178699, -6751)); // Go to the Condemned of Abyss Prison
LOCATIONS.put("4", new Location(146945, 26764, -2200)); // Return to Aden
}
private Ingrit()
{
addStartNpc(SOUL_TRACKER_INRGIT);
addTalkId(SOUL_TRACKER_INRGIT);
addFirstTalkId(SOUL_TRACKER_INRGIT);
}
@Override
public String onFirstTalk(Npc npc, PlayerInstance player)
{
return npc.getId() + ".htm";
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (npc.getId() == SOUL_TRACKER_INRGIT)
{
QuestState qs = player.getQuestState("Q00933_ExploringTheWestWingOfTheDungeonOfAbyss");
switch (event)
{
case "1":
{
if ((qs != null) && qs.isStarted())
{
player.teleToLocation(LOCATIONS.get(event), false); // Join Room from Ingrit
}
else
{
return "no_enter.htm";
}
break;
}
case "2":
{
player.teleToLocation(LOCATIONS.get(event), false); // Move to West Wing 1nd
break;
}
case "3":
{
if (!hasQuestItems(player, KEY_OF_WEST_WING))
{
return "no_key.htm";
}
player.teleToLocation(LOCATIONS.get(event), false); // Go to the Condemned of Abyss Prison
break;
}
case "4":
{
player.teleToLocation(LOCATIONS.get(event), false); // Return to Aden
break;
}
}
}
return super.onAdvEvent(event, npc, player);
}
public static void main(String[] args)
{
new Ingrit();
}
}

View File

@@ -0,0 +1,109 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.areas.DungeonOfAbyss.SoulTracker;
import java.util.HashMap;
import java.util.Map;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.quest.QuestState;
import ai.AbstractNpcAI;
/**
* @author QuangNguyen
*/
public class Iris extends AbstractNpcAI
{
// NPC
private static final int SOUL_TRACKER_IRIS = 31776;
// Item
private static final int KEY_OF_EAST_WING = 90011;
// Locations
private static final Map<String, Location> LOCATIONS = new HashMap<>();
static
{
LOCATIONS.put("1", new Location(-110038, -180560, -6754)); // Join Room from Iris
LOCATIONS.put("2", new Location(-109234, -177737, -6751)); // Move to East Wing 2nd
LOCATIONS.put("3", new Location(-112648, -181517, -6751)); // Go to the Condemned of Abyss Prison
LOCATIONS.put("4", new Location(146945, 26764, -2200)); // Return to Aden
}
private Iris()
{
addStartNpc(SOUL_TRACKER_IRIS);
addTalkId(SOUL_TRACKER_IRIS);
addFirstTalkId(SOUL_TRACKER_IRIS);
}
@Override
public String onFirstTalk(Npc npc, PlayerInstance player)
{
return npc.getId() + ".htm";
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (npc.getId() == SOUL_TRACKER_IRIS)
{
QuestState qs = player.getQuestState("Q00935_ExploringTheEastWingOfTheDungeonOfAbyss");
switch (event)
{
case "1":
{
if ((qs != null) && qs.isStarted())
{
player.teleToLocation(LOCATIONS.get(event), false); // Join Room form Iris
}
else
{
return "no_enter.htm";
}
break;
}
case "2":
{
player.teleToLocation(LOCATIONS.get(event), false); // Move to East Wing 2nd
break;
}
case "3":
{
if (!hasQuestItems(player, KEY_OF_EAST_WING))
{
return "no_key.htm";
}
player.teleToLocation(LOCATIONS.get(event), false); // Go to the Condemned of Abyss Prison
break;
}
case "4":
{
player.teleToLocation(LOCATIONS.get(event), false); // Return to Aden
break;
}
}
}
return super.onAdvEvent(event, npc, player);
}
public static void main(String[] args)
{
new Iris();
}
}

View File

@@ -0,0 +1,109 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.areas.DungeonOfAbyss.SoulTracker;
import java.util.HashMap;
import java.util.Map;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.quest.QuestState;
import ai.AbstractNpcAI;
/**
* @author QuangNguyen
*/
public class Magrit extends AbstractNpcAI
{
// NPC
private static final int SOUL_TRACKER_MARGIT = 31774;
// Item
private static final int KEY_OF_WEST_WING = 90010;
// Locations
private static final Map<String, Location> LOCATIONS = new HashMap<>();
static
{
LOCATIONS.put("1", new Location(-119440, -182464, -6752)); // Join Room from Magrit
LOCATIONS.put("2", new Location(-120394, -179651, -6751)); // Move to West Wing 2nd
LOCATIONS.put("3", new Location(-116963, -181492, -6575)); // Go to the Condemned of Abyss Prison
LOCATIONS.put("4", new Location(146945, 26764, -2200)); // Return to Aden
}
private Magrit()
{
addStartNpc(SOUL_TRACKER_MARGIT);
addTalkId(SOUL_TRACKER_MARGIT);
addFirstTalkId(SOUL_TRACKER_MARGIT);
}
@Override
public String onFirstTalk(Npc npc, PlayerInstance player)
{
return npc.getId() + ".htm";
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (npc.getId() == SOUL_TRACKER_MARGIT)
{
QuestState qs = player.getQuestState("Q00933_ExploringTheWestWingOfTheDungeonOfAbyss");
switch (event)
{
case "1":
{
if ((qs != null) && qs.isStarted())
{
player.teleToLocation(LOCATIONS.get(event), false); // Join Room from Magrit
}
else
{
return "no_enter.htm";
}
break;
}
case "2":
{
player.teleToLocation(LOCATIONS.get(event), false); // Move to West Wing 2nd
break;
}
case "3":
{
if (!hasQuestItems(player, KEY_OF_WEST_WING))
{
return "no_key.htm";
}
player.teleToLocation(LOCATIONS.get(event), false); // Go to the Condemned of Abyss Prison
break;
}
case "4":
{
player.teleToLocation(LOCATIONS.get(event), false); // Return to Aden
break;
}
}
}
return super.onAdvEvent(event, npc, player);
}
public static void main(String[] args)
{
new Magrit();
}
}

View File

@@ -0,0 +1,109 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.areas.DungeonOfAbyss.SoulTracker;
import java.util.HashMap;
import java.util.Map;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.quest.QuestState;
import ai.AbstractNpcAI;
/**
* @author QuangNguyen
*/
public class Rosammy extends AbstractNpcAI
{
// NPC
private static final int SOUL_TRACKER_ROSAMMY = 31777;
// Item
private static final int KEY_OF_EAST_WING = 90011;
// Locations
private static final Map<String, Location> LOCATIONS = new HashMap<>();
static
{
LOCATIONS.put("1", new Location(-110067, -177733, -6751)); // Join Room from Rosammy
LOCATIONS.put("2", new Location(-120318, -179626, -6752)); // Move to East Wing 1nd
LOCATIONS.put("3", new Location(-112632, -178671, -6751)); // Go to the Condemned of Abyss Prison
LOCATIONS.put("4", new Location(146945, 26764, -2200)); // Return to Aden
}
private Rosammy()
{
addStartNpc(SOUL_TRACKER_ROSAMMY);
addTalkId(SOUL_TRACKER_ROSAMMY);
addFirstTalkId(SOUL_TRACKER_ROSAMMY);
}
@Override
public String onFirstTalk(Npc npc, PlayerInstance player)
{
return npc.getId() + ".htm";
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (npc.getId() == SOUL_TRACKER_ROSAMMY)
{
QuestState qs = player.getQuestState("Q00935_ExploringTheEastWingOfTheDungeonOfAbyss");
switch (event)
{
case "1":
{
if ((qs != null) && qs.isStarted())
{
player.teleToLocation(LOCATIONS.get(event), false); // Join Room Rosammy
}
else
{
return "no_enter.htm";
}
break;
}
case "2":
{
player.teleToLocation(LOCATIONS.get(event), false); // Move to East Wing 1nd
break;
}
case "3":
{
if (!hasQuestItems(player, KEY_OF_EAST_WING))
{
return "no_key.htm";
}
player.teleToLocation(LOCATIONS.get(event), false); // Go to the Condemned of Abyss Prison
break;
}
case "4":
{
player.teleToLocation(LOCATIONS.get(event), false); // Return to Aden
break;
}
}
}
return super.onAdvEvent(event, npc, player);
}
public static void main(String[] args)
{
new Rosammy();
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Magrit:<br>
You apparently forgot to take the quest, please take the quest.<br>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Magrit:<br>
If you do not have the Key, you can not move to the Condemned of Abyss Prison.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Tores:<br>
It seems to me that you are not strong enough to go on a mission to the Dungeon of Abyss.<br>
(Western Wing of the Dungeon of Abyss for characters 40-44 level.)
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Tores:<br>
It seems to me that you are not strong enough to go on a mission to the Dungeon of Abyss.<br>
(Eastern Wing side of the Dungeon of Abyss for characters 45-49 level.)
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Tores:<br>
Have you heard of the Dungeon of Abyss? Especially evil and dangerous monsters are imprisoned there.<br>
But someone has recently removed the seal from its gates. If we do nothing… No, only a thought of it scares me. I need your help.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Tores 1">Go to the West Wing of the Dungeon of Abyss (Level 40-44)</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Tores 2">Go to the East Wing of the Dungeon of Abyss (Level 45-49)</Button>
</body></html>

View File

@@ -0,0 +1,98 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.areas.DungeonOfAbyss.Tores;
import java.util.HashMap;
import java.util.Map;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import ai.AbstractNpcAI;
/**
* @author QuangNguyen
*/
public class Tores extends AbstractNpcAI
{
// NPC
private static final int TORES = 31778;
// Locations
private static final Map<String, Location> LOCATIONS = new HashMap<>();
static
{
// move from Tores
LOCATIONS.put("1", new Location(-120325, -182444, -6752)); // Move to Magrit
LOCATIONS.put("2", new Location(-109202, -180546, -6751)); // Move to Iris
}
private Tores()
{
addStartNpc(TORES);
addTalkId(TORES);
addFirstTalkId(TORES);
}
@Override
public String onFirstTalk(Npc npc, PlayerInstance player)
{
return "31778.htm";
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
switch (event)
{
case "1":
{
final Location loc = LOCATIONS.get(event);
if ((player.getLevel() > 39) && (player.getLevel() < 45))
{
player.teleToLocation(loc, true);
}
else
{
return "31778-no_level.htm";
}
break;
}
case "2":
{
final Location loc = LOCATIONS.get(event);
if ((player.getLevel() > 44) && (player.getLevel() < 50))
{
player.teleToLocation(loc, true);
}
else
{
return "31778-no_level01.htm";
}
break;
}
}
return super.onAdvEvent(event, npc, player);
}
public static void main(String[] args)
{
new Tores();
}
}

View File

@@ -0,0 +1,5 @@
<html><body>Master Toma:<br>
Who are you?<br>
I don't speak with those I do not know... Just go on!<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,69 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.areas.DwarvenVillage.Toma;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import ai.AbstractNpcAI;
/**
* @author Mobius
*/
public class Toma extends AbstractNpcAI
{
// NPC
private static final int TOMA = 30556;
// Locations
private static final Location[] LOCATIONS =
{
new Location(151680, -174891, -1782),
new Location(154153, -220105, -3402),
new Location(178834, -184336, -355, 41400)
};
// Misc
private static final int TELEPORT_DELAY = 1800000; // 30 minutes
private Toma()
{
addFirstTalkId(TOMA);
onAdvEvent("RESPAWN_TOMA", null, null);
startQuestTimer("RESPAWN_TOMA", TELEPORT_DELAY, null, null, true);
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (event.equals("RESPAWN_TOMA"))
{
addSpawn(TOMA, LOCATIONS[getRandom(LOCATIONS.length)], false, TELEPORT_DELAY);
}
return null;
}
@Override
public String onFirstTalk(Npc npc, PlayerInstance player)
{
return "30556.htm";
}
public static void main(String[] args)
{
new Toma();
}
}

View File

@@ -0,0 +1,57 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.areas.LairOfAntharas;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Playable;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import ai.AbstractNpcAI;
/**
* Pytan, Knorkiks AI.
* @author Quangnguyen
*/
public class Pytan extends AbstractNpcAI
{
// NPCs
private static final int PYTAN = 20761;
private static final int KNORIKS = 20405;
private Pytan()
{
addKillId(PYTAN);
}
@Override
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
{
if (getRandom(100) < 5)
{
final Npc spawnBanshee = addSpawn(KNORIKS, npc, false, 300000);
final Playable attacker = isSummon ? killer.getServitors().values().stream().findFirst().orElse(killer.getPet()) : killer;
addAttackPlayerDesire(spawnBanshee, attacker);
npc.deleteMe();
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new Pytan();
}
}

View File

@@ -0,0 +1,96 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.areas.PlainsOfDion;
import org.l2jmobius.commons.util.CommonUtil;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.geoengine.GeoEngine;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.NpcStringId;
import ai.AbstractNpcAI;
/**
* AI for mobs in Plains of Dion (near Floran Village).
* @author Gladicek
*/
public class PlainsOfDion extends AbstractNpcAI
{
private static final int DELU_LIZARDMEN[] =
{
21104, // Delu Lizardman Supplier
21105, // Delu Lizardman Special Agent
21107, // Delu Lizardman Commander
};
private static final NpcStringId[] MONSTERS_MSG =
{
NpcStringId.S1_HOW_DARE_YOU_INTERRUPT_OUR_FIGHT_HEY_GUYS_HELP,
NpcStringId.S1_HEY_WE_RE_HAVING_A_DUEL_HERE,
NpcStringId.THE_DUEL_IS_OVER_ATTACK,
NpcStringId.FOUL_KILL_THE_COWARD,
NpcStringId.HOW_DARE_YOU_INTERRUPT_A_SACRED_DUEL_YOU_MUST_BE_TAUGHT_A_LESSON
};
private static final NpcStringId[] MONSTERS_ASSIST_MSG =
{
NpcStringId.DIE_YOU_COWARD,
NpcStringId.KILL_THE_COWARD,
NpcStringId.WHAT_ARE_YOU_LOOKING_AT
};
private PlainsOfDion()
{
addAttackId(DELU_LIZARDMEN);
}
@Override
public String onAttack(Npc npc, PlayerInstance player, int damage, boolean isSummon)
{
if (npc.isScriptValue(0))
{
final int i = getRandom(5);
if (i < 2)
{
npc.broadcastSay(ChatType.NPC_GENERAL, MONSTERS_MSG[i], player.getName());
}
else
{
npc.broadcastSay(ChatType.NPC_GENERAL, MONSTERS_MSG[i]);
}
World.getInstance().forEachVisibleObjectInRange(npc, MonsterInstance.class, npc.getTemplate().getClanHelpRange(), obj ->
{
if (CommonUtil.contains(DELU_LIZARDMEN, obj.getId()) && !obj.isAttackingNow() && !obj.isDead() && GeoEngine.getInstance().canSeeTarget(npc, obj))
{
addAttackPlayerDesire(obj, player);
obj.broadcastSay(ChatType.NPC_GENERAL, MONSTERS_ASSIST_MSG[getRandom(3)]);
}
});
npc.setScriptValue(1);
}
return super.onAttack(npc, player, damage, isSummon);
}
public static void main(String[] args)
{
new PlainsOfDion();
}
}

View File

@@ -0,0 +1,62 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.areas.TalkingIsland;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.NpcStringId;
import ai.AbstractNpcAI;
/**
* Roxxy AI.
* @author Mobius
*/
public class Roxxy extends AbstractNpcAI
{
// NPC
private static final int ROXXY = 30006;
private Roxxy()
{
addSpawnId(ROXXY);
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (event.equals("TEXT_SPAM") && (npc != null))
{
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.SPEAK_WITH_ME_ABOUT_TRAVELING_AROUND_ADEN, 1000);
startQuestTimer("TEXT_SPAM", getRandom(10000, 30000), npc, null, false);
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSpawn(Npc npc)
{
startQuestTimer("TEXT_SPAM", 10000, npc, null, false);
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new Roxxy();
}
}

View File

@@ -0,0 +1,20 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Mobius
*/
package ai.areas;

View File

@@ -0,0 +1,8 @@
<html><body>Heart of Warding:<br>
You are overcome by a voice, a voice so powerful you are helpless as it speaks.<br>
<font color="LEVEL">Do not expect Shilen's authority will diminish<br>
while false gods freely roam.<br>
Leave, and<br>
prepare to face the return of Antharas.</font><br>
(Challenging Antharas is not currently available.)
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Heart of Warding:<br>
You are overcome by a voice, a voice so powerful you are helpless as it speaks:<br>
<font color="LEVEL">Do not expect that you might challenge Antharas at your own convenience.<br>
When the time is right, Shilen's authority will judge you.</font><br>
(Currently, other members are challenging Antharas.)
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Heart of Warding:<br>
A voice that can shatter your entire body is resonating in your head:<br>
<font color="LEVEL">Do not dare to face Shilen's authority<br>
without the most determined preparation.</font><br>
(Only those who have the Portal Stone can challenge Antharas.)
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Heart of Warding:<br>
You are overcome by a voice, a voice so powerful you are helpless as it speaks:<br>
<font color="LEVEL">No matter how many gather to follow false gods,<br>
Shilen's authority is too great.</font><br>
(The number of participants are above the allowed number in challenging Antharas.)
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Heart of Warding:<br>
You are overcome by a voice, a voice so powerful you are helpless as it speaks:<br>
<font color="LEVEL">You seek death and defeat by coming here without your leader! You appear before Shilen's authority<br>
and you tempt Shilen's wrath!</font><br>
(The players who belong to an association can only enter through the Association Leader.)
</body></html>

View File

@@ -0,0 +1,12 @@
<html><body>Heart of Warding:<br>
You are overcome by a voice, a voice so powerful you are helpless as it speaks:<br>
<font color="LEVEL">A terrible creature <br>
fell to the earth from above <br>
in order to vent a mother's spite,<br>
cursed and forsaken by her own children.<br>
Dark Pilgrim of the Holy Land,<br>
Do you dare face the Land Dragon Antharas?</font><br>
(A maximum of 200 people can challenge Antharas.)<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Antharas enter">Move to Antharas' Nest</button>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
<html><head><body>Angelic Vortex:<br>
The Angelic Vortex emits a faint light which twinkles out. The vortex becomes inactive. It seems like, in order to go to the place where the Angelic Vortex is leading, you will need some special object.
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Angelic Vortex:<br>
The Angelic Vortex emits a faint light, in the midst of which an image appears. A giant that normally appears as a stone statue has come alive and is fighting with many people. Even angels have joined the fray. It seems that the angels are angry at the humans who have broken the seal of the stone statue.<br>
It appears impossible to cross over to that place right now. You have no choice but to wait until the fight is over.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Baium 31862-04.html">Ask about the stone statue that has come alive.</button>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Angelic Vortex:<br>
The Angelic Vortex emits a faint light, in the midst of which an image appears. A large, open space... but the gigantic, human-like stone statue is no longer there.<br>
It seems that while the statue is not visible, one could cross over to that place.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Baium 31862-04.html">Ask about the stone statue.</button>
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Angelic Vortex:<br>
In ancient times a mighty emperor named Baium became so enamored of his own power that he began to fancy himself a god. He conscripted all of his people to build an awesome tower that reached almost to heaven.<br>
The gods were not amused. They struck him down, cursed him with immortality and imprisoned him in his own tower for eternity! A statue of the foolish emperor stands there to this day.<br>
Occasionally, the old emperor himself is woken up by those who seek his power. Unfortunately, when Baium is disturbed, so are the angels who guard him.<br>
Although the angels are certainly no friend of Baium, they regard Humans with equal disdain.<font color="LEVEL"> Ultimate success against Baium depends upon the defeat of the guardian angels.</font><br>
This is all I can tell you. Good luck!
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Angelic Vortex:<br>
The Angelic Vortex emits a faint light, and in the midst of the light an image appears. In the deepest part of a spacious area, a gigantic stone statue is visible. The statue has a human-like appearance and is in a seated position, as though it was being held by some invisible force against its will.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Baium enter">Go where the Angelic Vortex leads.</button>
</body></html>

View File

@@ -0,0 +1,791 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.bosses.Baium;
import org.l2jmobius.Config;
import org.l2jmobius.commons.util.CommonUtil;
import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.enums.CategoryType;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.MountType;
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.Attackable;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Playable;
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.skills.SkillCaster;
import org.l2jmobius.gameserver.model.variables.NpcVariables;
import org.l2jmobius.gameserver.model.zone.type.NoRestartZone;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.Earthquake;
import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
import ai.AbstractNpcAI;
/**
* Baium AI.
* @author St3eT
*/
public class Baium extends AbstractNpcAI
{
// NPCs
private static final int BAIUM = 29020; // Baium
private static final int BAIUM_STONE = 29025; // Baium
private static final int ANG_VORTEX = 31862; // Angelic Vortex
private static final int ARCHANGEL = 29021; // Archangel
private static final int TELE_CUBE = 31842; // Teleportation Cubic
// Skills
private static final SkillHolder BAIUM_ATTACK = new SkillHolder(4127, 1); // Baium: General Attack
private static final SkillHolder ENERGY_WAVE = new SkillHolder(4128, 1); // Wind Of Force
private static final SkillHolder EARTH_QUAKE = new SkillHolder(4129, 1); // Earthquake
private static final SkillHolder THUNDERBOLT = new SkillHolder(4130, 1); // Striking of Thunderbolt
private static final SkillHolder GROUP_HOLD = new SkillHolder(4131, 1); // Stun
private static final SkillHolder SPEAR_ATTACK = new SkillHolder(4132, 1); // Spear: Pound the Ground
private static final SkillHolder ANGEL_HEAL = new SkillHolder(4133, 1); // Angel Heal
private static final SkillHolder HEAL_OF_BAIUM = new SkillHolder(4135, 1); // Baium Heal
private static final SkillHolder BAIUM_PRESENT = new SkillHolder(4136, 1); // Baium's Gift
private static final SkillHolder ANTI_STRIDER = new SkillHolder(4258, 1); // Hinder Strider
// Items
private static final int FABRIC = 4295; // Blooded Fabric
// Zone
private static final NoRestartZone zone = ZoneManager.getInstance().getZoneById(70051, NoRestartZone.class); // Baium zone
// Status
private static final int ALIVE = 0;
private static final int WAITING = 1;
private static final int IN_FIGHT = 2;
private static final int DEAD = 3;
// Locations
private static final Location BAIUM_GIFT_LOC = new Location(115910, 17337, 10105);
private static final Location BAIUM_LOC = new Location(116033, 17447, 10107, -25348);
private static final Location TELEPORT_CUBIC_LOC = new Location(115017, 15549, 10090);
private static final Location TELEPORT_IN_LOC = new Location(114077, 15882, 10078);
private static final Location[] TELEPORT_OUT_LOC =
{
new Location(108784, 16000, -4928),
new Location(113824, 10448, -5164),
new Location(115488, 22096, -5168),
};
private static final Location[] ARCHANGEL_LOC =
{
new Location(115792, 16608, 10136, 0),
new Location(115168, 17200, 10136, 0),
new Location(115780, 15564, 10136, 13620),
new Location(114880, 16236, 10136, 5400),
new Location(114239, 17168, 10136, -1992)
};
// Misc
private GrandBossInstance _baium = null;
private static long _lastAttack = 0;
private static PlayerInstance _standbyPlayer = null;
private Baium()
{
addFirstTalkId(ANG_VORTEX);
addTalkId(ANG_VORTEX, TELE_CUBE, BAIUM_STONE);
addStartNpc(ANG_VORTEX, TELE_CUBE, BAIUM_STONE);
addAttackId(BAIUM, ARCHANGEL);
addKillId(BAIUM);
addSeeCreatureId(BAIUM);
addSpellFinishedId(BAIUM);
final StatsSet info = GrandBossManager.getInstance().getStatsSet(BAIUM);
switch (getStatus())
{
case WAITING:
{
setStatus(ALIVE);
}
case ALIVE:
{
addSpawn(BAIUM_STONE, BAIUM_LOC, false, 0);
break;
}
case IN_FIGHT:
{
final double curr_hp = info.getDouble("currentHP");
final double curr_mp = info.getDouble("currentMP");
final int loc_x = info.getInt("loc_x");
final int loc_y = info.getInt("loc_y");
final int loc_z = info.getInt("loc_z");
final int heading = info.getInt("heading");
_baium = (GrandBossInstance) addSpawn(BAIUM, loc_x, loc_y, loc_z, heading, false, 0);
_baium.setCurrentHpMp(curr_hp, curr_mp);
_lastAttack = System.currentTimeMillis();
addBoss(_baium);
for (Location loc : ARCHANGEL_LOC)
{
final Npc archangel = addSpawn(ARCHANGEL, loc, false, 0, true);
startQuestTimer("SELECT_TARGET", 5000, archangel, null);
}
startQuestTimer("CHECK_ATTACK", 60000, _baium, null);
break;
}
case DEAD:
{
final long remain = info.getLong("respawn_time") - System.currentTimeMillis();
if (remain > 0)
{
startQuestTimer("CLEAR_STATUS", remain, null, null);
}
else
{
notifyEvent("CLEAR_STATUS", null, null);
}
break;
}
}
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
switch (event)
{
case "31862-04.html":
{
return event;
}
case "enter":
{
String htmltext = null;
if (getStatus() == DEAD)
{
htmltext = "31862-03.html";
}
else if (getStatus() == IN_FIGHT)
{
htmltext = "31862-02.html";
}
else if (!hasQuestItems(player, FABRIC))
{
htmltext = "31862-01.html";
}
else
{
takeItems(player, FABRIC, 1);
player.teleToLocation(TELEPORT_IN_LOC);
}
return htmltext;
}
case "teleportOut":
{
final Location destination = TELEPORT_OUT_LOC[getRandom(TELEPORT_OUT_LOC.length)];
player.teleToLocation(destination.getX() + getRandom(100), destination.getY() + getRandom(100), destination.getZ());
break;
}
case "wakeUp":
{
if (getStatus() == ALIVE)
{
npc.deleteMe();
setStatus(IN_FIGHT);
_baium = (GrandBossInstance) addSpawn(BAIUM, BAIUM_LOC, false, 0);
_baium.disableCoreAI(true);
addBoss(_baium);
_lastAttack = System.currentTimeMillis();
startQuestTimer("WAKEUP_ACTION", 50, _baium, null);
startQuestTimer("MANAGE_EARTHQUAKE", 2000, _baium, player);
startQuestTimer("CHECK_ATTACK", 60000, _baium, null);
}
break;
}
case "WAKEUP_ACTION":
{
if (npc != null)
{
zone.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
}
break;
}
case "MANAGE_EARTHQUAKE":
{
if (npc != null)
{
zone.broadcastPacket(new Earthquake(npc.getX(), npc.getY(), npc.getZ(), 40, 10));
zone.broadcastPacket(new PlaySound("BS02_A"));
startQuestTimer("SOCIAL_ACTION", 8000, npc, player);
}
break;
}
case "SOCIAL_ACTION":
{
if (npc != null)
{
zone.broadcastPacket(new SocialAction(npc.getObjectId(), 3));
startQuestTimer("PLAYER_PORT", 6000, npc, player);
}
break;
}
case "PLAYER_PORT":
{
if (npc != null)
{
if ((player != null) && player.isInsideRadius3D(npc, 16000))
{
player.teleToLocation(BAIUM_GIFT_LOC);
startQuestTimer("PLAYER_KILL", 3000, npc, player);
}
else if ((_standbyPlayer != null) && _standbyPlayer.isInsideRadius3D(npc, 16000))
{
_standbyPlayer.teleToLocation(BAIUM_GIFT_LOC);
startQuestTimer("PLAYER_KILL", 3000, npc, _standbyPlayer);
}
}
break;
}
case "PLAYER_KILL":
{
if ((player != null) && player.isInsideRadius3D(npc, 16000))
{
zone.broadcastPacket(new SocialAction(npc.getObjectId(), 1));
npc.broadcastSay(ChatType.NPC_GENERAL, player.getName() + ", How dare you wake me! Now you shall die!"); // TODO: replace with NpcStringId when are done core support
npc.setTarget(player);
npc.doCast(BAIUM_PRESENT.getSkill());
}
for (PlayerInstance players : zone.getPlayersInside())
{
if (players.isHero())
{
zone.broadcastPacket(new ExShowScreenMessage(NpcStringId.NOT_EVEN_THE_GODS_THEMSELVES_COULD_TOUCH_ME_BUT_YOU_S1_YOU_DARE_CHALLENGE_ME_IGNORANT_MORTAL, 2, 4000, players.getName()));
break;
}
}
startQuestTimer("SPAWN_ARCHANGEL", 8000, npc, null);
break;
}
case "SPAWN_ARCHANGEL":
{
_baium.disableCoreAI(false);
for (Location loc : ARCHANGEL_LOC)
{
final Npc archangel = addSpawn(ARCHANGEL, loc, false, 0, true);
startQuestTimer("SELECT_TARGET", 5000, archangel, null);
}
if ((player != null) && !player.isDead())
{
addAttackPlayerDesire(npc, player);
}
else if ((_standbyPlayer != null) && !_standbyPlayer.isDead())
{
addAttackPlayerDesire(npc, _standbyPlayer);
}
else
{
for (Creature creature : World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 2000))
{
if (zone.isInsideZone(creature) && !creature.isDead())
{
addAttackPlayerDesire(npc, (Playable) creature);
break;
}
}
}
break;
}
case "SELECT_TARGET":
{
if (npc != null)
{
final Attackable mob = (Attackable) npc;
final Creature mostHated = mob.getMostHated();
if ((_baium == null) || _baium.isDead())
{
mob.deleteMe();
break;
}
if ((mostHated != null) && mostHated.isPlayer() && zone.isInsideZone(mostHated))
{
if (mob.getTarget() != mostHated)
{
mob.clearAggroList();
}
addAttackPlayerDesire(mob, (Playable) mostHated);
}
else
{
boolean found = false;
for (Playable creature : World.getInstance().getVisibleObjectsInRange(mob, Playable.class, 1000))
{
if (zone.isInsideZone(creature) && !creature.isDead())
{
if (mob.getTarget() != creature)
{
mob.clearAggroList();
}
addAttackPlayerDesire(mob, creature);
found = true;
break;
}
}
if (!found)
{
if (mob.isInsideRadius3D(_baium, 40))
{
if (mob.getTarget() != _baium)
{
mob.clearAggroList();
}
mob.setRunning();
mob.addDamageHate(_baium, 0, 999);
mob.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, _baium);
}
else
{
mob.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _baium);
}
}
}
startQuestTimer("SELECT_TARGET", 5000, npc, null);
}
break;
}
case "CHECK_ATTACK":
{
if ((npc != null) && ((_lastAttack + 1800000) < System.currentTimeMillis()))
{
notifyEvent("CLEAR_ZONE", null, null);
addSpawn(BAIUM_STONE, BAIUM_LOC, false, 0);
setStatus(ALIVE);
}
else if (npc != null)
{
if (((_lastAttack + 300000) < System.currentTimeMillis()) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.75)))
{
npc.setTarget(npc);
npc.doCast(HEAL_OF_BAIUM.getSkill());
}
startQuestTimer("CHECK_ATTACK", 60000, npc, null);
}
break;
}
case "CLEAR_STATUS":
{
setStatus(ALIVE);
addSpawn(BAIUM_STONE, BAIUM_LOC, false, 0);
break;
}
case "CLEAR_ZONE":
{
for (Creature creature : zone.getCharactersInside())
{
if (creature != null)
{
if (creature.isNpc())
{
creature.deleteMe();
}
else if (creature.isPlayer())
{
notifyEvent("teleportOut", null, (PlayerInstance) creature);
}
}
}
break;
}
case "RESPAWN_BAIUM":
{
if (getStatus() == DEAD)
{
setRespawn(0);
cancelQuestTimer("CLEAR_STATUS", null, null);
notifyEvent("CLEAR_STATUS", null, null);
}
else
{
player.sendMessage(getClass().getSimpleName() + ": You cant respawn Baium while Baium is alive!");
}
break;
}
case "ABORT_FIGHT":
{
if (getStatus() == IN_FIGHT)
{
_baium = null;
notifyEvent("CLEAR_ZONE", null, null);
notifyEvent("CLEAR_STATUS", null, null);
player.sendMessage(getClass().getSimpleName() + ": Aborting fight!");
}
else
{
player.sendMessage(getClass().getSimpleName() + ": You cant abort attack right now!");
}
cancelQuestTimers("CHECK_ATTACK");
cancelQuestTimers("SELECT_TARGET");
break;
}
case "DESPAWN_MINIONS":
{
if (getStatus() == IN_FIGHT)
{
for (Creature creature : zone.getCharactersInside())
{
if ((creature != null) && creature.isNpc() && (creature.getId() == ARCHANGEL))
{
creature.deleteMe();
}
}
if (player != null)
{
player.sendMessage(getClass().getSimpleName() + ": All archangels has been deleted!");
}
}
else if (player != null)
{
player.sendMessage(getClass().getSimpleName() + ": You cant despawn archangels right now!");
}
break;
}
case "MANAGE_SKILLS":
{
if (npc != null)
{
manageSkills(npc);
}
break;
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon, Skill skill)
{
_lastAttack = System.currentTimeMillis();
if (npc.getId() == BAIUM)
{
if ((attacker.getMountType() == MountType.STRIDER) && !attacker.isAffectedBySkill(ANTI_STRIDER.getSkillId()))
{
if (!npc.isSkillDisabled(ANTI_STRIDER.getSkill()))
{
npc.setTarget(attacker);
npc.doCast(ANTI_STRIDER.getSkill());
}
}
if (skill == null)
{
refreshAiParams(attacker, npc, (damage * 1000));
}
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
{
refreshAiParams(attacker, npc, ((damage / 3) * 100));
}
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
{
refreshAiParams(attacker, npc, (damage * 20));
}
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
{
refreshAiParams(attacker, npc, (damage * 10));
}
else
{
refreshAiParams(attacker, npc, ((damage / 3) * 20));
}
manageSkills(npc);
}
else
{
final Attackable mob = (Attackable) npc;
final Creature mostHated = mob.getMostHated();
if ((getRandom(100) < 10) && SkillCaster.checkUseConditions(mob, SPEAR_ATTACK.getSkill()))
{
if ((mostHated != null) && (npc.calculateDistance3D(mostHated) < 1000) && zone.isCharacterInZone(mostHated))
{
mob.setTarget(mostHated);
mob.doCast(SPEAR_ATTACK.getSkill());
}
else if (zone.isCharacterInZone(attacker))
{
mob.setTarget(attacker);
mob.doCast(SPEAR_ATTACK.getSkill());
}
}
if ((getRandom(100) < 5) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.5)) && SkillCaster.checkUseConditions(mob, ANGEL_HEAL.getSkill()))
{
npc.setTarget(npc);
npc.doCast(ANGEL_HEAL.getSkill());
}
}
return super.onAttack(npc, attacker, damage, isSummon, skill);
}
@Override
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
{
if (zone.isCharacterInZone(killer))
{
setStatus(DEAD);
addSpawn(TELE_CUBE, TELEPORT_CUBIC_LOC, false, 900000);
zone.broadcastPacket(new PlaySound("BS01_D"));
final long respawnTime = Config.BAIUM_SPAWN_INTERVAL * 3600000;
setRespawn(respawnTime);
startQuestTimer("CLEAR_STATUS", respawnTime, null, null);
startQuestTimer("CLEAR_ZONE", 900000, null, null);
cancelQuestTimer("CHECK_ATTACK", npc, null);
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onSeeCreature(Npc npc, Creature creature, boolean isSummon)
{
if (!zone.isInsideZone(creature) || (creature.isNpc() && (creature.getId() == BAIUM_STONE)))
{
return super.onSeeCreature(npc, creature, isSummon);
}
if (creature.isPlayer() && !creature.isDead() && (_standbyPlayer == null))
{
_standbyPlayer = (PlayerInstance) creature;
}
if (creature.isInCategory(CategoryType.CLERIC_GROUP))
{
if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
{
refreshAiParams(creature, npc, 10000);
}
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
{
refreshAiParams(creature, npc, 10000, 6000);
}
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
{
refreshAiParams(creature, npc, 10000, 3000);
}
else
{
refreshAiParams(creature, npc, 10000, 2000);
}
}
else
{
refreshAiParams(creature, npc, 10000, 1000);
}
manageSkills(npc);
return super.onSeeCreature(npc, creature, isSummon);
}
@Override
public String onSpellFinished(Npc npc, PlayerInstance player, Skill skill)
{
startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
if (!zone.isCharacterInZone(npc) && (_baium != null))
{
_baium.teleToLocation(BAIUM_LOC);
}
return super.onSpellFinished(npc, player, skill);
}
@Override
public boolean unload(boolean removeFromList)
{
if (_baium != null)
{
_baium.deleteMe();
}
return super.unload(removeFromList);
}
private final void refreshAiParams(Creature attacker, Npc npc, int damage)
{
refreshAiParams(attacker, npc, damage, damage);
}
private final void refreshAiParams(Creature attacker, Npc npc, int damage, int aggro)
{
final int newAggroVal = damage + getRandom(3000);
final int aggroVal = aggro + 1000;
final NpcVariables vars = npc.getVariables();
for (int i = 0; i < 3; i++)
{
if (attacker == vars.getObject("c_quest" + i, Creature.class))
{
if (vars.getInt("i_quest" + i) < aggroVal)
{
vars.set("i_quest" + i, newAggroVal);
}
return;
}
}
final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
vars.set("i_quest" + index, newAggroVal);
vars.set("c_quest" + index, attacker);
}
private int getStatus()
{
return GrandBossManager.getInstance().getBossStatus(BAIUM);
}
private void addBoss(GrandBossInstance grandboss)
{
GrandBossManager.getInstance().addBoss(grandboss);
}
private void setStatus(int status)
{
GrandBossManager.getInstance().setBossStatus(BAIUM, status);
}
private void setRespawn(long respawnTime)
{
GrandBossManager.getInstance().getStatsSet(BAIUM).set("respawn_time", (System.currentTimeMillis() + respawnTime));
}
private void manageSkills(Npc npc)
{
if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
{
return;
}
final NpcVariables vars = npc.getVariables();
for (int i = 0; i < 3; i++)
{
final Creature attacker = vars.getObject("c_quest" + i, Creature.class);
if ((attacker == null) || ((npc.calculateDistance3D(attacker) > 9000) || attacker.isDead()))
{
vars.set("i_quest" + i, 0);
}
}
final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
final Creature creature = vars.getObject("c_quest" + index, Creature.class);
final int i2 = vars.getInt("i_quest" + index);
if ((i2 > 0) && (getRandom(100) < 70))
{
vars.set("i_quest" + index, 500);
}
SkillHolder skillToCast = null;
if ((creature != null) && !creature.isDead())
{
if (npc.getCurrentHp() > (npc.getMaxHp() * 0.75))
{
if (getRandom(100) < 10)
{
skillToCast = ENERGY_WAVE;
}
else if (getRandom(100) < 10)
{
skillToCast = EARTH_QUAKE;
}
else
{
skillToCast = BAIUM_ATTACK;
}
}
else if (npc.getCurrentHp() > (npc.getMaxHp() * 0.5))
{
if (getRandom(100) < 10)
{
skillToCast = GROUP_HOLD;
}
else if (getRandom(100) < 10)
{
skillToCast = ENERGY_WAVE;
}
else if (getRandom(100) < 10)
{
skillToCast = EARTH_QUAKE;
}
else
{
skillToCast = BAIUM_ATTACK;
}
}
else if (npc.getCurrentHp() > (npc.getMaxHp() * 0.25))
{
if (getRandom(100) < 10)
{
skillToCast = THUNDERBOLT;
}
else if (getRandom(100) < 10)
{
skillToCast = GROUP_HOLD;
}
else if (getRandom(100) < 10)
{
skillToCast = ENERGY_WAVE;
}
else if (getRandom(100) < 10)
{
skillToCast = EARTH_QUAKE;
}
else
{
skillToCast = BAIUM_ATTACK;
}
}
else if (getRandom(100) < 10)
{
skillToCast = THUNDERBOLT;
}
else if (getRandom(100) < 10)
{
skillToCast = GROUP_HOLD;
}
else if (getRandom(100) < 10)
{
skillToCast = ENERGY_WAVE;
}
else if (getRandom(100) < 10)
{
skillToCast = EARTH_QUAKE;
}
else
{
skillToCast = BAIUM_ATTACK;
}
}
if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
{
npc.setTarget(creature);
npc.doCast(skillToCast.getSkill());
}
}
public static void main(String[] args)
{
new Baium();
}
}

View File

@@ -0,0 +1,236 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.bosses.Core;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.Config;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.instancemanager.GlobalVariablesManager;
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Attackable;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
import ai.AbstractNpcAI;
/**
* Core AI.
* @author DrLecter, Emperorc, Mobius
*/
public class Core extends AbstractNpcAI
{
// NPCs
private static final int CORE = 29006;
private static final int DEATH_KNIGHT = 29007;
private static final int DOOM_WRAITH = 29008;
private static final int SUSCEPTOR = 29011;
// Spawns
private static final Map<Integer, Location> MINNION_SPAWNS = new HashMap<>();
static
{
MINNION_SPAWNS.put(DEATH_KNIGHT, new Location(17191, 109298, -6488));
MINNION_SPAWNS.put(DEATH_KNIGHT, new Location(17564, 109548, -6488));
MINNION_SPAWNS.put(DEATH_KNIGHT, new Location(17855, 109552, -6488));
MINNION_SPAWNS.put(DEATH_KNIGHT, new Location(18280, 109202, -6488));
MINNION_SPAWNS.put(DEATH_KNIGHT, new Location(18784, 109253, -6488));
MINNION_SPAWNS.put(DEATH_KNIGHT, new Location(18059, 108314, -6488));
MINNION_SPAWNS.put(DEATH_KNIGHT, new Location(17300, 108444, -6488));
MINNION_SPAWNS.put(DEATH_KNIGHT, new Location(17148, 110071, -6648));
MINNION_SPAWNS.put(DEATH_KNIGHT, new Location(18318, 110077, -6648));
MINNION_SPAWNS.put(DEATH_KNIGHT, new Location(17726, 110391, -6648));
MINNION_SPAWNS.put(DOOM_WRAITH, new Location(17113, 110970, -6648));
MINNION_SPAWNS.put(DOOM_WRAITH, new Location(17496, 110880, -6648));
MINNION_SPAWNS.put(DOOM_WRAITH, new Location(18061, 110990, -6648));
MINNION_SPAWNS.put(DOOM_WRAITH, new Location(18384, 110698, -6648));
MINNION_SPAWNS.put(DOOM_WRAITH, new Location(17993, 111458, -6584));
MINNION_SPAWNS.put(SUSCEPTOR, new Location(17297, 111470, -6584));
MINNION_SPAWNS.put(SUSCEPTOR, new Location(17893, 110198, -6648));
MINNION_SPAWNS.put(SUSCEPTOR, new Location(17706, 109423, -6488));
MINNION_SPAWNS.put(SUSCEPTOR, new Location(17849, 109388, -6480));
}
// Misc
private static final byte ALIVE = 0;
private static final byte DEAD = 1;
private static boolean _firstAttacked;
private static final Collection<Attackable> _minions = ConcurrentHashMap.newKeySet();
private Core()
{
registerMobs(CORE, DEATH_KNIGHT, DOOM_WRAITH, SUSCEPTOR);
_firstAttacked = false;
final StatsSet info = GrandBossManager.getInstance().getStatsSet(CORE);
if (GrandBossManager.getInstance().getBossStatus(CORE) == DEAD)
{
// Load the unlock date and time for Core from DB.
final long temp = info.getLong("respawn_time") - System.currentTimeMillis();
// If Core is locked until a certain time, mark it so and start the unlock timer the unlock time has not yet expired.
if (temp > 0)
{
startQuestTimer("core_unlock", temp, null, null);
}
else
{
// The time has already expired while the server was offline. Immediately spawn Core.
final GrandBossInstance core = (GrandBossInstance) addSpawn(CORE, 17726, 108915, -6480, 0, false, 0);
GrandBossManager.getInstance().setBossStatus(CORE, ALIVE);
spawnBoss(core);
}
}
else
{
final boolean test = GlobalVariablesManager.getInstance().getBoolean("Core_Attacked", false);
if (test)
{
_firstAttacked = true;
}
final int loc_x = info.getInt("loc_x");
final int loc_y = info.getInt("loc_y");
final int loc_z = info.getInt("loc_z");
final int heading = info.getInt("heading");
final double hp = info.getDouble("currentHP");
final double mp = info.getDouble("currentMP");
final GrandBossInstance core = (GrandBossInstance) addSpawn(CORE, loc_x, loc_y, loc_z, heading, false, 0);
core.setCurrentHpMp(hp, mp);
spawnBoss(core);
}
}
@Override
public void onSave()
{
GlobalVariablesManager.getInstance().set("Core_Attacked", _firstAttacked);
}
public void spawnBoss(GrandBossInstance npc)
{
GrandBossManager.getInstance().addBoss(npc);
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
// Spawn minions
Attackable mob;
Location spawnLocation;
for (Entry<Integer, Location> spawn : MINNION_SPAWNS.entrySet())
{
spawnLocation = spawn.getValue();
mob = (Attackable) addSpawn(spawn.getKey(), spawnLocation.getX(), spawnLocation.getY(), spawnLocation.getZ(), getRandom(61794), false, 0);
mob.setIsRaidMinion(true);
_minions.add(mob);
}
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (event.equalsIgnoreCase("core_unlock"))
{
final GrandBossInstance core = (GrandBossInstance) addSpawn(CORE, 17726, 108915, -6480, 0, false, 0);
GrandBossManager.getInstance().setBossStatus(CORE, ALIVE);
spawnBoss(core);
}
else if (event.equalsIgnoreCase("spawn_minion"))
{
final Attackable mob = (Attackable) addSpawn(npc.getId(), npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
mob.setIsRaidMinion(true);
_minions.add(mob);
}
else if (event.equalsIgnoreCase("despawn_minions"))
{
_minions.forEach(Attackable::decayMe);
_minions.clear();
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon)
{
if (npc.getId() == CORE)
{
if (_firstAttacked)
{
if (getRandom(100) == 0)
{
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.REMOVING_INTRUDERS);
}
}
else
{
_firstAttacked = true;
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.A_NON_PERMITTED_TARGET_HAS_BEEN_DISCOVERED);
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.INTRUDER_REMOVAL_SYSTEM_INITIATED);
}
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
{
if (npc.getId() == CORE)
{
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.A_FATAL_ERROR_HAS_OCCURRED);
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.SYSTEM_IS_BEING_SHUT_DOWN);
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.EMPTY);
_firstAttacked = false;
GrandBossManager.getInstance().setBossStatus(CORE, DEAD);
// Calculate Min and Max respawn times randomly.
final long respawnTime = (Config.CORE_SPAWN_INTERVAL + getRandom(-Config.CORE_SPAWN_RANDOM, Config.CORE_SPAWN_RANDOM)) * 3600000;
startQuestTimer("core_unlock", respawnTime, null, null);
// Also save the respawn time so that the info is maintained past reboots.
final StatsSet info = GrandBossManager.getInstance().getStatsSet(CORE);
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
GrandBossManager.getInstance().setStatsSet(CORE, info);
startQuestTimer("despawn_minions", 20000, null, null);
cancelQuestTimers("spawn_minion");
}
else if ((GrandBossManager.getInstance().getBossStatus(CORE) == ALIVE) && _minions.contains(npc))
{
_minions.remove(npc);
startQuestTimer("spawn_minion", 60000, npc, null);
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onSpawn(Npc npc)
{
if (npc.getId() == CORE)
{
npc.setIsImmobilized(true);
}
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new Core();
}
}

View File

@@ -0,0 +1,350 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.bosses.Orfen;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.Config;
import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.Spawn;
import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Attackable;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.skills.SkillCaster;
import org.l2jmobius.gameserver.model.zone.ZoneType;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
import ai.AbstractNpcAI;
/**
* Orfen's AI
* @author Emperorc
*/
public class Orfen extends AbstractNpcAI
{
private static final Location[] POS =
{
new Location(43728, 17220, -4342),
new Location(55024, 17368, -5412),
new Location(53504, 21248, -5486),
new Location(53248, 24576, -5262)
};
private static final NpcStringId[] TEXT =
{
NpcStringId.S1_STOP_KIDDING_YOURSELF_ABOUT_YOUR_OWN_POWERLESSNESS,
NpcStringId.S1_I_LL_MAKE_YOU_FEEL_WHAT_TRUE_FEAR_IS,
NpcStringId.YOU_RE_REALLY_STUPID_TO_HAVE_CHALLENGED_ME_S1_GET_READY,
NpcStringId.S1_DO_YOU_THINK_THAT_S_GOING_TO_WORK
};
private static final int ORFEN = 29014;
// private static final int RAIKEL = 29015;
private static final int RAIKEL_LEOS = 29016;
// private static final int RIBA = 29017;
private static final int RIBA_IREN = 29018;
private static boolean _IsTeleported;
private static Set<Attackable> _minions = ConcurrentHashMap.newKeySet();
private static ZoneType ZONE;
private static final byte ALIVE = 0;
private static final byte DEAD = 1;
private static final SkillHolder PARALYSIS = new SkillHolder(4064, 1);
private static final SkillHolder BLOW = new SkillHolder(4067, 4);
private static final SkillHolder ORFEN_HEAL = new SkillHolder(4516, 1);
private Orfen()
{
final int[] mobs =
{
ORFEN,
RAIKEL_LEOS,
RIBA_IREN
};
registerMobs(mobs);
_IsTeleported = false;
ZONE = ZoneManager.getInstance().getZoneById(12013);
final StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN);
final int status = GrandBossManager.getInstance().getBossStatus(ORFEN);
if (status == DEAD)
{
// load the unlock date and time for Orfen from DB
final long temp = info.getLong("respawn_time") - System.currentTimeMillis();
// if Orfen is locked until a certain time, mark it so and start the unlock timer
// the unlock time has not yet expired.
if (temp > 0)
{
startQuestTimer("orfen_unlock", temp, null, null);
}
else
{
// the time has already expired while the server was offline. Immediately spawn Orfen.
final int i = getRandom(10);
Location loc;
if (i < 4)
{
loc = POS[1];
}
else if (i < 7)
{
loc = POS[2];
}
else
{
loc = POS[3];
}
final GrandBossInstance orfen = (GrandBossInstance) addSpawn(ORFEN, loc, false, 0);
GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE);
spawnBoss(orfen);
}
}
else
{
final int loc_x = info.getInt("loc_x");
final int loc_y = info.getInt("loc_y");
final int loc_z = info.getInt("loc_z");
final int heading = info.getInt("heading");
final double hp = info.getDouble("currentHP");
final double mp = info.getDouble("currentMP");
final GrandBossInstance orfen = (GrandBossInstance) addSpawn(ORFEN, loc_x, loc_y, loc_z, heading, false, 0);
orfen.setCurrentHpMp(hp, mp);
spawnBoss(orfen);
}
}
public void setSpawnPoint(Npc npc, int index)
{
((Attackable) npc).clearAggroList();
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
final Spawn spawn = npc.getSpawn();
spawn.setLocation(POS[index]);
npc.teleToLocation(POS[index], false);
}
public void spawnBoss(GrandBossInstance npc)
{
GrandBossManager.getInstance().addBoss(npc);
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
startQuestTimer("check_orfen_pos", 10000, npc, null, true);
// Spawn minions
final int x = npc.getX();
final int y = npc.getY();
Attackable mob;
mob = (Attackable) addSpawn(RAIKEL_LEOS, x + 100, y + 100, npc.getZ(), 0, false, 0);
mob.setIsRaidMinion(true);
_minions.add(mob);
mob = (Attackable) addSpawn(RAIKEL_LEOS, x + 100, y - 100, npc.getZ(), 0, false, 0);
mob.setIsRaidMinion(true);
_minions.add(mob);
mob = (Attackable) addSpawn(RAIKEL_LEOS, x - 100, y + 100, npc.getZ(), 0, false, 0);
mob.setIsRaidMinion(true);
_minions.add(mob);
mob = (Attackable) addSpawn(RAIKEL_LEOS, x - 100, y - 100, npc.getZ(), 0, false, 0);
mob.setIsRaidMinion(true);
_minions.add(mob);
startQuestTimer("check_minion_loc", 10000, npc, null, true);
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (event.equalsIgnoreCase("orfen_unlock"))
{
final int i = getRandom(10);
Location loc;
if (i < 4)
{
loc = POS[1];
}
else if (i < 7)
{
loc = POS[2];
}
else
{
loc = POS[3];
}
final GrandBossInstance orfen = (GrandBossInstance) addSpawn(ORFEN, loc, false, 0);
GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE);
spawnBoss(orfen);
}
else if (event.equalsIgnoreCase("check_orfen_pos"))
{
if ((_IsTeleported && (npc.getCurrentHp() > (npc.getMaxHp() * 0.95))) || (!ZONE.isInsideZone(npc) && !_IsTeleported))
{
setSpawnPoint(npc, getRandom(3) + 1);
_IsTeleported = false;
}
else if (_IsTeleported && !ZONE.isInsideZone(npc))
{
setSpawnPoint(npc, 0);
}
}
else if (event.equalsIgnoreCase("check_minion_loc"))
{
for (Attackable mob : _minions)
{
if (!npc.isInsideRadius2D(mob, 3000))
{
mob.teleToLocation(npc.getLocation());
((Attackable) npc).clearAggroList();
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
}
}
}
else if (event.equalsIgnoreCase("despawn_minions"))
{
for (Attackable mob : _minions)
{
mob.decayMe();
}
_minions.clear();
}
else if (event.equalsIgnoreCase("spawn_minion"))
{
final Attackable mob = (Attackable) addSpawn(RAIKEL_LEOS, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0);
mob.setIsRaidMinion(true);
_minions.add(mob);
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSkillSee(Npc npc, PlayerInstance caster, Skill skill, WorldObject[] targets, boolean isSummon)
{
if (npc.getId() == ORFEN)
{
final Creature originalCaster = isSummon ? caster.getServitors().values().stream().findFirst().orElse(caster.getPet()) : caster;
if ((skill.getEffectPoint() > 0) && (getRandom(5) == 0) && npc.isInsideRadius2D(originalCaster, 1000))
{
npc.broadcastSay(ChatType.NPC_GENERAL, TEXT[getRandom(4)], caster.getName());
originalCaster.teleToLocation(npc.getLocation());
npc.setTarget(originalCaster);
npc.doCast(PARALYSIS.getSkill());
}
}
return super.onSkillSee(npc, caster, skill, targets, isSummon);
}
@Override
public String onFactionCall(Npc npc, Npc caller, PlayerInstance attacker, boolean isSummon)
{
if ((caller == null) || (npc == null) || npc.isCastingNow(SkillCaster::isAnyNormalType))
{
return super.onFactionCall(npc, caller, attacker, isSummon);
}
final int npcId = npc.getId();
final int callerId = caller.getId();
if ((npcId == RAIKEL_LEOS) && (getRandom(20) == 0))
{
npc.setTarget(attacker);
npc.doCast(BLOW.getSkill());
}
else if (npcId == RIBA_IREN)
{
int chance = 1;
if (callerId == ORFEN)
{
chance = 9;
}
if ((callerId != RIBA_IREN) && (caller.getCurrentHp() < (caller.getMaxHp() / 2.0)) && (getRandom(10) < chance))
{
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
npc.setTarget(caller);
npc.doCast(ORFEN_HEAL.getSkill());
}
}
return super.onFactionCall(npc, caller, attacker, isSummon);
}
@Override
public String onAttack(Npc npc, PlayerInstance attacker, int damage, boolean isSummon)
{
final int npcId = npc.getId();
if (npcId == ORFEN)
{
if (!_IsTeleported && ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2)))
{
_IsTeleported = true;
setSpawnPoint(npc, 0);
}
else if (npc.isInsideRadius2D(attacker, 1000) && !npc.isInsideRadius2D(attacker, 300) && (getRandom(10) == 0))
{
npc.broadcastSay(ChatType.NPC_GENERAL, TEXT[getRandom(3)], attacker.getName());
attacker.teleToLocation(npc.getLocation());
npc.setTarget(attacker);
npc.doCast(PARALYSIS.getSkill());
}
}
else if (npcId == RIBA_IREN)
{
if (!npc.isCastingNow(SkillCaster::isAnyNormalType) && ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2.0)))
{
npc.setTarget(attacker);
npc.doCast(ORFEN_HEAL.getSkill());
}
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
{
if (npc.getId() == ORFEN)
{
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
GrandBossManager.getInstance().setBossStatus(ORFEN, DEAD);
// Calculate Min and Max respawn times randomly.
long respawnTime = Config.ORFEN_SPAWN_INTERVAL + getRandom(-Config.ORFEN_SPAWN_RANDOM, Config.ORFEN_SPAWN_RANDOM);
respawnTime *= 3600000;
startQuestTimer("orfen_unlock", respawnTime, null, null);
// also save the respawn time so that the info is maintained past reboots
final StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN);
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
GrandBossManager.getInstance().setStatsSet(ORFEN, info);
cancelQuestTimer("check_minion_loc", npc, null);
cancelQuestTimer("check_orfen_pos", npc, null);
startQuestTimer("despawn_minions", 20000, null, null);
cancelQuestTimers("spawn_minion");
}
else if ((GrandBossManager.getInstance().getBossStatus(ORFEN) == ALIVE) && (npc.getId() == RAIKEL_LEOS))
{
_minions.remove(npc);
startQuestTimer("spawn_minion", 360000, npc, null);
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new Orfen();
}
}

View File

@@ -0,0 +1,409 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.bosses.QueenAnt;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.l2jmobius.Config;
import org.l2jmobius.gameserver.ai.CtrlIntention;
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Attackable;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Playable;
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.skills.CommonSkill;
import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.skills.SkillCaster;
import org.l2jmobius.gameserver.model.zone.ZoneType;
import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
import ai.AbstractNpcAI;
/**
* Queen Ant's AI
* @author Emperorc
*/
public class QueenAnt extends AbstractNpcAI
{
private static final int QUEEN = 29001;
private static final int LARVA = 29002;
private static final int NURSE = 29003;
private static final int GUARD = 29004;
private static final int ROYAL = 29005;
private static final int[] MOBS =
{
QUEEN,
LARVA,
NURSE,
GUARD,
ROYAL
};
private static final Location OUST_LOC_1 = new Location(-19480, 187344, -5600);
private static final Location OUST_LOC_2 = new Location(-17928, 180912, -5520);
private static final Location OUST_LOC_3 = new Location(-23808, 182368, -5600);
private static final int QUEEN_X = -21610;
private static final int QUEEN_Y = 181594;
private static final int QUEEN_Z = -5734;
// QUEEN Status Tracking :
private static final byte ALIVE = 0; // Queen Ant is spawned.
private static final byte DEAD = 1; // Queen Ant has been killed.
private static ZoneType _zone;
private static SkillHolder HEAL1 = new SkillHolder(4020, 1);
private static SkillHolder HEAL2 = new SkillHolder(4024, 1);
MonsterInstance _queen = null;
private MonsterInstance _larva = null;
private final Set<MonsterInstance> _nurses = ConcurrentHashMap.newKeySet();
private QueenAnt()
{
addSpawnId(MOBS);
addKillId(MOBS);
addAggroRangeEnterId(MOBS);
addFactionCallId(NURSE);
_zone = ZoneManager.getInstance().getZoneById(12012);
final StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
final int status = GrandBossManager.getInstance().getBossStatus(QUEEN);
if (status == DEAD)
{
// load the unlock date and time for queen ant from DB
final long temp = info.getLong("respawn_time") - System.currentTimeMillis();
// if queen ant is locked until a certain time, mark it so and start the unlock timer
// the unlock time has not yet expired.
if (temp > 0)
{
startQuestTimer("queen_unlock", temp, null, null);
}
else
{
// the time has already expired while the server was offline. Immediately spawn queen ant.
final GrandBossInstance queen = (GrandBossInstance) addSpawn(QUEEN, QUEEN_X, QUEEN_Y, QUEEN_Z, 0, false, 0);
GrandBossManager.getInstance().setBossStatus(QUEEN, ALIVE);
spawnBoss(queen);
}
}
else
{
int loc_x = info.getInt("loc_x");
int loc_y = info.getInt("loc_y");
int loc_z = info.getInt("loc_z");
final int heading = info.getInt("heading");
final double hp = info.getDouble("currentHP");
final double mp = info.getDouble("currentMP");
if (!_zone.isInsideZone(loc_x, loc_y, loc_z))
{
loc_x = QUEEN_X;
loc_y = QUEEN_Y;
loc_z = QUEEN_Z;
}
final GrandBossInstance queen = (GrandBossInstance) addSpawn(QUEEN, loc_x, loc_y, loc_z, heading, false, 0);
queen.setCurrentHpMp(hp, mp);
spawnBoss(queen);
}
}
private void spawnBoss(GrandBossInstance npc)
{
GrandBossManager.getInstance().addBoss(npc);
if (getRandom(100) < 33)
{
_zone.movePlayersTo(OUST_LOC_1);
}
else if (getRandom(100) < 50)
{
_zone.movePlayersTo(OUST_LOC_2);
}
else
{
_zone.movePlayersTo(OUST_LOC_3);
}
GrandBossManager.getInstance().addBoss(npc);
startQuestTimer("action", 10000, npc, null, true);
startQuestTimer("heal", 1000, null, null, true);
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
_queen = npc;
_larva = (MonsterInstance) addSpawn(LARVA, -21600, 179482, -5846, getRandom(360), false, 0);
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
switch (event)
{
case "heal":
{
boolean notCasting;
final boolean larvaNeedHeal = (_larva != null) && (_larva.getCurrentHp() < _larva.getMaxHp());
final boolean queenNeedHeal = (_queen != null) && (_queen.getCurrentHp() < _queen.getMaxHp());
for (MonsterInstance nurse : _nurses)
{
if ((nurse == null) || nurse.isDead() || nurse.isCastingNow(SkillCaster::isAnyNormalType))
{
continue;
}
notCasting = nurse.getAI().getIntention() != CtrlIntention.AI_INTENTION_CAST;
if (larvaNeedHeal)
{
if ((nurse.getTarget() != _larva) || notCasting)
{
nurse.setTarget(_larva);
nurse.useMagic(getRandomBoolean() ? HEAL1.getSkill() : HEAL2.getSkill());
}
continue;
}
if (queenNeedHeal)
{
if (nurse.getLeader() == _larva)
{
continue;
}
if ((nurse.getTarget() != _queen) || notCasting)
{
nurse.setTarget(_queen);
nurse.useMagic(HEAL1.getSkill());
}
continue;
}
// if nurse not casting - remove target
if (notCasting && (nurse.getTarget() != null))
{
nurse.setTarget(null);
}
}
break;
}
case "action":
{
if ((npc != null) && (getRandom(3) == 0))
{
if (getRandom(2) == 0)
{
npc.broadcastSocialAction(3);
}
else
{
npc.broadcastSocialAction(4);
}
}
break;
}
case "queen_unlock":
{
final GrandBossInstance queen = (GrandBossInstance) addSpawn(QUEEN, QUEEN_X, QUEEN_Y, QUEEN_Z, 0, false, 0);
GrandBossManager.getInstance().setBossStatus(QUEEN, ALIVE);
spawnBoss(queen);
break;
}
case "ANT_QUEEN_TASK":
{
if ((_queen == null) || _queen.isDead())
{
cancelQuestTimers("ANT_QUEEN_TASK");
}
else if (_queen.calculateDistance2D(QUEEN_X, QUEEN_Y, QUEEN_Z) > 2000)
{
_queen.clearAggroList();
_queen.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(QUEEN_X, QUEEN_Y, QUEEN_Z, 0));
}
break;
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSpawn(Npc npc)
{
final MonsterInstance mob = (MonsterInstance) npc;
switch (npc.getId())
{
case LARVA:
{
mob.setIsImmobilized(true);
mob.setUndying(true);
mob.setIsRaidMinion(true);
break;
}
case NURSE:
{
mob.disableCoreAI(true);
mob.setIsRaidMinion(true);
_nurses.add(mob);
break;
}
case ROYAL:
case GUARD:
{
mob.setIsRaidMinion(true);
break;
}
case QUEEN:
{
if (mob.getMinionList().getSpawnedMinions().isEmpty())
{
((MonsterInstance) npc).getMinionList().spawnMinions(npc.getParameters().getMinionList("Privates"));
}
cancelQuestTimer("ANT_QUEEN_TASK", npc, null);
startQuestTimer("ANT_QUEEN_TASK", 5000, npc, null, true);
break;
}
}
return super.onSpawn(npc);
}
@Override
public String onFactionCall(Npc npc, Npc caller, PlayerInstance attacker, boolean isSummon)
{
if ((caller == null) || (npc == null))
{
return super.onFactionCall(npc, caller, attacker, isSummon);
}
if (!npc.isCastingNow(SkillCaster::isAnyNormalType) && (npc.getAI().getIntention() != CtrlIntention.AI_INTENTION_CAST))
{
if (caller.getCurrentHp() < caller.getMaxHp())
{
npc.setTarget(caller);
((Attackable) npc).useMagic(HEAL1.getSkill());
}
}
return null;
}
@Override
public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon)
{
if ((npc == null) || (player.isGM() && player.isInvisible()))
{
return null;
}
final boolean isMage;
final Playable character;
if (isSummon)
{
isMage = false;
character = player.getServitors().values().stream().findFirst().orElse(player.getPet());
}
else
{
isMage = player.isMageClass();
character = player;
}
if (character == null)
{
return null;
}
if (!Config.RAID_DISABLE_CURSE && ((character.getLevel() - npc.getLevel()) > 8))
{
Skill curse = null;
if (isMage)
{
if (!character.hasAbnormalType(CommonSkill.RAID_CURSE.getSkill().getAbnormalType()) && (getRandom(4) == 0))
{
curse = CommonSkill.RAID_CURSE.getSkill();
}
}
else if (!character.hasAbnormalType(CommonSkill.RAID_CURSE2.getSkill().getAbnormalType()) && (getRandom(4) == 0))
{
curse = CommonSkill.RAID_CURSE2.getSkill();
}
if (curse != null)
{
npc.broadcastPacket(new MagicSkillUse(npc, character, curse.getId(), curse.getLevel(), 300, 0));
curse.applyEffects(npc, character);
}
((Attackable) npc).stopHating(character); // for calling again
return null;
}
return super.onAggroRangeEnter(npc, player, isSummon);
}
@Override
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
{
final int npcId = npc.getId();
if (npcId == QUEEN)
{
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
GrandBossManager.getInstance().setBossStatus(QUEEN, DEAD);
// Calculate Min and Max respawn times randomly.
final long respawnTime = (Config.QUEEN_ANT_SPAWN_INTERVAL + getRandom(-Config.QUEEN_ANT_SPAWN_RANDOM, Config.QUEEN_ANT_SPAWN_RANDOM)) * 3600000;
startQuestTimer("queen_unlock", respawnTime, null, null);
cancelQuestTimer("action", npc, null);
cancelQuestTimer("heal", null, null);
// also save the respawn time so that the info is maintained past reboots
final StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
GrandBossManager.getInstance().setStatsSet(QUEEN, info);
_nurses.clear();
_larva.deleteMe();
_larva = null;
_queen = null;
cancelQuestTimers("ANT_QUEEN_TASK");
}
else if ((_queen != null) && !_queen.isAlikeDead())
{
if (npcId == ROYAL)
{
final MonsterInstance mob = (MonsterInstance) npc;
if (mob.getLeader() != null)
{
mob.getLeader().getMinionList().onMinionDie(mob, (280 + getRandom(40)) * 1000);
}
}
else if (npcId == NURSE)
{
final MonsterInstance mob = (MonsterInstance) npc;
_nurses.remove(mob);
if (mob.getLeader() != null)
{
mob.getLeader().getMinionList().onMinionDie(mob, 10000);
}
}
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new QueenAnt();
}
}

View File

@@ -0,0 +1,109 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.bosses.Zaken;
import org.l2jmobius.Config;
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
import org.l2jmobius.gameserver.model.StatsSet;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
import ai.AbstractNpcAI;
/**
* Zaken AI<br>
* TODO: Skill cast?<br>
* TODO: Day/Night spawn? TODO: Boss message broadcast.
* @author Mobius
*/
public class Zaken extends AbstractNpcAI
{
// NPC
private static final int ZAKEN = 29022;
// Location
private static final int ZAKEN_X = 52207;
private static final int ZAKEN_Y = 217230;
private static final int ZAKEN_Z = -3341;
// Misc
private static final byte ALIVE = 0;
private static final byte DEAD = 1;
private Zaken()
{
addKillId(ZAKEN);
final StatsSet info = GrandBossManager.getInstance().getStatsSet(ZAKEN);
final int status = GrandBossManager.getInstance().getBossStatus(ZAKEN);
if (status == DEAD)
{
// load the unlock date and time from DB
final long temp = info.getLong("respawn_time") - System.currentTimeMillis();
if (temp > 0)
{
startQuestTimer("zaken_unlock", temp, null, null);
}
else // the time has already expired while the server was offline
{
spawnBoss();
}
}
else
{
spawnBoss();
}
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
if (event.equals("zaken_unlock"))
{
spawnBoss();
}
return super.onAdvEvent(event, npc, player);
}
private void spawnBoss()
{
final GrandBossInstance zaken = (GrandBossInstance) addSpawn(ZAKEN, ZAKEN_X, ZAKEN_Y, ZAKEN_Z, 0, false, 0);
GrandBossManager.getInstance().setBossStatus(ZAKEN, ALIVE);
GrandBossManager.getInstance().addBoss(zaken);
zaken.broadcastPacket(new PlaySound(1, "BS01_A", 1, zaken.getObjectId(), zaken.getX(), zaken.getY(), zaken.getZ()));
}
@Override
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
{
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
GrandBossManager.getInstance().setBossStatus(ZAKEN, DEAD);
// Calculate Min and Max respawn times randomly.
final long respawnTime = (Config.ZAKEN_SPAWN_INTERVAL + getRandom(-Config.ZAKEN_SPAWN_RANDOM, Config.ZAKEN_SPAWN_RANDOM)) * 3600000;
startQuestTimer("zaken_unlock", respawnTime, null, null);
// also save the respawn time so that the info is maintained past reboots
final StatsSet info = GrandBossManager.getInstance().getStatsSet(ZAKEN);
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
GrandBossManager.getInstance().setStatsSet(ZAKEN, info);
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new Zaken();
}
}

View File

@@ -0,0 +1,20 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Mobius
*/
package ai.bosses;

View File

@@ -0,0 +1,10 @@
<html><body>Arena Director:<br>
Play the game according to the rules! The loser should be silent!<br>
What? Unfair? Then, why don't you hold your tongue and give it another try!<br><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest ArenaManager CPrecovery">CP Recovery: 1,000 Adena</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest ArenaManager HPrecovery">HP Recovery: 1,000 Adena</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest ArenaManager Buff">Buff for Arena: 2,000 Adena</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_DepositP">Private Warehouse: Deposit an item.</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_WithdrawP">Private Warehouse: Withdraw an item.</Button>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,134 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.others.ArenaManager;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.skills.SkillCaster;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.network.SystemMessageId;
import ai.AbstractNpcAI;
/**
* Arena Manager AI.
* @author St3eT
*/
public class ArenaManager extends AbstractNpcAI
{
// NPC
private static final int ARENA_MANAGER = 31226;
// Skills
private static final SkillHolder[] BUFFS =
{
new SkillHolder(6805, 1), // Arena Empower
new SkillHolder(6806, 1), // Arena Acumen
new SkillHolder(6807, 1), // Arena Concentration
new SkillHolder(6808, 1), // Arena Might
new SkillHolder(6804, 1), // Arena Wind Walk
new SkillHolder(6812, 1), // Arena Berserker Spirit
};
private static final SkillHolder CP_RECOVERY = new SkillHolder(4380, 1); // Arena: CP Recovery
private static final SkillHolder HP_RECOVERY = new SkillHolder(6817, 1); // Arena HP Recovery
// Misc
private static final int CP_COST = 1000;
private static final int HP_COST = 1000;
private static final int BUFF_COST = 2000;
private ArenaManager()
{
addStartNpc(ARENA_MANAGER);
addTalkId(ARENA_MANAGER);
addFirstTalkId(ARENA_MANAGER);
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
switch (event)
{
case "CPrecovery":
{
if (player.getAdena() >= CP_COST)
{
takeItems(player, Inventory.ADENA_ID, CP_COST);
startQuestTimer("CPrecovery_delay", 2000, npc, player);
}
else
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
}
break;
}
case "HPrecovery":
{
if (player.getAdena() >= HP_COST)
{
takeItems(player, Inventory.ADENA_ID, HP_COST);
startQuestTimer("HPrecovery_delay", 2000, npc, player);
}
else
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
}
break;
}
case "Buff":
{
if (player.getAdena() >= BUFF_COST)
{
takeItems(player, Inventory.ADENA_ID, BUFF_COST);
for (SkillHolder skill : BUFFS)
{
SkillCaster.triggerCast(npc, player, skill.getSkill());
}
}
else
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
}
break;
}
case "CPrecovery_delay":
{
if ((player != null) && !player.isInsideZone(ZoneId.PVP))
{
npc.setTarget(player);
npc.doCast(CP_RECOVERY.getSkill());
}
break;
}
case "HPrecovery_delay":
{
if ((player != null) && !player.isInsideZone(ZoneId.PVP))
{
npc.setTarget(player);
npc.doCast(HP_RECOVERY.getSkill());
}
break;
}
}
return super.onAdvEvent(event, npc, player);
}
public static void main(String[] args)
{
new ArenaManager();
}
}

View File

@@ -0,0 +1,8 @@
<html><body>Blacksmith:<br>
Hello!<br>
We Dwarves of the Blacksmith Guild have refined our skills in order to create a greater variety of crops for our Lord.<br>
What can I do for you?<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleBlacksmith 35098-02.html">Manufacture a crop</Button>
</center>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>
Sure, no problem! Bring the ingredients needed and I'll create an item for you.<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 350980001">Choose an item</Button>
</center>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Blacksmith:<br>
My goodness! What brings you here?<br>
We Dwarves of the Blacksmith Guild have refined our skills in order to create a greater variety of crops for our Lord.<br>
What can I do for you?<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleBlacksmith 35140-02.html">Manufacture a crop</Button>
</center>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>
Sure, no problem! If you bring me the ingredients I need, I'll get right on it!<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 350980002">Choose an item</Button>
</center>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Blacksmith:<br>
Greetings! Is there anything I can do for you today?<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleBlacksmith 35182-02.html">Manufacture a crop</Button>
</center>
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>
Certainly! If you bring me the ingredients I need I'll make it for you.<br>
What would you like?<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 350980003">View the list</Button>
</center>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Blacksmith:<br>
Greetings!<br>
We Dwarves of the Blacksmith Guild have refined our skills in order to create a greater variety of crops for our Lord.<br>
What can I do for you?<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleBlacksmith 35224-02.html">Manufacture a crop</Button>
</center>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>
Certainly, I'd be glad to make an item for you! Bring me the ingredients I need and I'll make it immediately.<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 350980004">View the list</Button>
</center>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Blacksmith:<br>
My goodness! What brings you here?<br>
We Dwarves of the Blacksmith Guild have refined our skills in order to create a greater variety of crops for our Lord.<br>
What can I do for you?<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleBlacksmith 35272-02.html">Manufacture a crop</Button>
</center>
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>
Sure, just bring the ingredients I need and I'll make it for you right away.<br>
What would you like?<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 350980005">Choose Item</Button>
</center>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Blacksmith:<br>
My goodness! What brings you here?<br>
We Dwarves of the Blacksmith Guild have refined our skills in order to create a greater variety of crops for our Lord.<br>
What can I do for you?<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleBlacksmith 35314-02.html">Manufacture a crop</Button>
</center>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>
Certainly, I'd be glad to make an item for you! Bring me the ingredients I need and I'll make it immediately.<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 350980006">View the list</Button>
</center>
</body></html>

View File

@@ -0,0 +1,9 @@
<html><body>Blacksmith:<br>
What brings you here?<br>
Our Blacksmiths Guild has learned a new technique, so we can use more diverse crops.<br>
Our Dwarven dexterity is truly unequaled!<br>
If you want something made, just give us the order!<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleBlacksmith 35361-02.html">Crop Processing</Button>
</center>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>
If you provide the materials, it won't take anytime! What do you want made?<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 350980007">See the list</Button>
</center>
</body></html>

View File

@@ -0,0 +1,9 @@
<html><body>Blacksmith:<br>
What brings you to this shabby place?<br>
I've learned a new skill from our Blacksmith Guild. Now I can make what you want with various crops, my Lord!<br>
Our Dwarves are truly gifted with their hands. Ha! Oops! Pardon me, my Lord!<br>
If you want me to make something, just say the word!<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleBlacksmith 35507-02.html">Crop Manufacturing</Button>
</center>
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>
Of course! Give me the materials I need and I'll make anything you want at once!<br>
What do you want?<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 350980008">Examine the List</Button>
</center>
</body></html>

View File

@@ -0,0 +1,9 @@
<html><body>Blacksmith:<br>
What brings you to this shabby place?<br>
By the way, I've learned a new skill from our Blacksmith Guild! Now I use a wider variety of crops to make the items you need, my Lord.<br>
Our Dwarves are truly gifted with their hands.. Ha! Oops! Pardon me, my Lord.<br>
If you want me to make something for you, just ask.<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleBlacksmith 35553-02.html">Crop Manufacturing</Button>
</center>
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>
Of course! Bring me the materials I need and I'll make anything you want at once!<br>
What do you want?<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 350980009">Examine the list</Button>
</center>
</body></html>

View File

@@ -0,0 +1,75 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.others.CastleBlacksmith;
import org.l2jmobius.gameserver.model.PlayerCondOverride;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.clan.ClanPrivilege;
import ai.AbstractNpcAI;
/**
* Castle Blacksmith AI.
* @author malyelfik
*/
public class CastleBlacksmith extends AbstractNpcAI
{
// Blacksmith IDs
private static final int[] NPCS =
{
35098, // Blacksmith (Gludio)
35140, // Blacksmith (Dion)
35182, // Blacksmith (Giran)
35224, // Blacksmith (Oren)
35272, // Blacksmith (Aden)
35314, // Blacksmith (Innadril)
35361, // Blacksmith (Goddard)
35507, // Blacksmith (Rune)
35553, // Blacksmith (Schuttgart)
};
private CastleBlacksmith()
{
addStartNpc(NPCS);
addTalkId(NPCS);
addFirstTalkId(NPCS);
}
private boolean hasRights(PlayerInstance player, Npc npc)
{
final boolean isMyLord = player.isClanLeader() ? (player.getClan().getCastleId() == (npc.getCastle() != null ? npc.getCastle().getResidenceId() : -1)) : false;
return player.canOverrideCond(PlayerCondOverride.CASTLE_CONDITIONS) || isMyLord || ((player.getClanId() == npc.getCastle().getOwnerId()) && player.hasClanPrivilege(ClanPrivilege.CS_MANOR_ADMIN));
}
@Override
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
{
return (event.equalsIgnoreCase(npc.getId() + "-02.html") && hasRights(player, npc)) ? event : null;
}
@Override
public String onFirstTalk(Npc npc, PlayerInstance player)
{
return (hasRights(player, npc)) ? npc.getId() + "-01.html" : "no.html";
}
public static void main(String[] args)
{
new CastleBlacksmith();
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Blacksmith:<br>
Leave me alone! I'm very busy!
</body></html>

View File

@@ -0,0 +1,30 @@
<html><body>
<center>
<br><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24180001 24180002">Open the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24180001 24180002">Close the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24180013 24180012">Open the western inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24180013 24180012">Close the western inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24180014 24180015">Open the easten inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24180014 24180015">Close the easten inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24180005 24180004">Open the hall entrance castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24180005 24180004">Close the hall entrance castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24180008 24180007">Open the second level western castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24180008 24180007">Close the second level western castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24180009 24180010">Open the second level easten castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24180009 24180010">Close the second level easten castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24180016">Open the terrace entrance castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24180016">Close the terrace entrance castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24180019">Open the easten sky walk castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24180019">Close the easten sky walk castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24180018">Open the easten outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24180018">Close the easten outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24180021">Open the western sky walk castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24180021">Close the western sky walk castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24180020">Open the western outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24180020">Close the western outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24180001 24180002 24180013 24180012 24180014 24180015 24180005 24180004 24180008 24180007 24180009 24180010 24180016 24180019 24180018 24180021 24180020">Open all gates</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24180001 24180002 24180013 24180012 24180014 24180015 24180005 24180004 24180008 24180007 24180009 24180010 24180016 24180019 24180018 24180021 24180020">Close all gates</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,13 @@
<html><body>
Reinforce castle gates:<br>
Strengthens gates and walls. A good measure against the incursion of enemy troops into the castle.<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 1 24180001 24180002">Reinforce outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 2 24180013 24180012">Reinforce western inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 2 24180014 24180015">Reinforce eastern inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 2 24180005 24180004">Reinforce entrance to inner castle hall</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 3 24180011 24180006">Reinforce outer castle wall</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 3 24180003">Reinforce inner castle wall</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Go back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>&$556;<br><br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13032" msg="811;Front Of Aden Castle">Front Of Aden Castle</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13033" msg="811;Aden Town Square">Aden Town Square</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13034" msg="811;Front of the Narsell Fortress">Front of the Narsell Fortress</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13035" msg="811;Front of the Bayou Fortress">Front of the Bayou Fortress</Button>
</body></html>

View File

@@ -0,0 +1,12 @@
<html><body>&$556;<br><br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13032" msg="811;Front Of Aden Castle">Front Of Aden Castle</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13033" msg="811;Aden Town Square">Aden Town Square</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13034" msg="811;Front of the Narsell Fortress">Front of the Narsell Fortress</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13035" msg="811;Front of the Bayou Fortress">Front of the Bayou Fortress</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13036" msg="811;Enchanted Valley, Northen Region">Enchanted Valley, Northen Region - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13071" msg="811;Blazing Swamp">Blazing Swamp - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13038" msg="811;Forest of Mirrors">Forest of Mirrors - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13039" msg="811;Anghel Waterfall">Anghel Waterfall - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13072" msg="811;The Giant's Cave Upper Layer">The Giant's Cave Upper Layer - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13073" msg="811;The Giant's Cave Lower Layer">The Giant's Cave Lower Layer - 500 Adena</Button>
</body></html>

View File

@@ -0,0 +1,10 @@
<html><body><br>
Activate the trap that is located in the inner part of the island. Then, the trap function produces a magical fire that emanates from the device, slowing movement of those passing above it and setting them afire.<br>
This device has the same effect on allies so it must be carefully deployed... Used correctly there is no greater defense for a castle.<br>
Of course, quality has its price...<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_trap 0">Deploy the device east of the castle</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_trap 1">Deploy the device west of the castle</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Go back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,14 @@
<html><body>
<center>
<br><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 20220001 20220002">Open the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 20220001 20220002">Close the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 20220005 20220006">Open the inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 20220005 20220006">Close the inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 20220008">Open the moring castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 20220008">Close the moring castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 20220001 20220002 20220005 20220006 20220008">Open all gates</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 20220001 20220002 20220005 20220006 20220008">Close all gates</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Go back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,9 @@
<html><body>
Reinforce castle gates:<br>
Strengthens gates and walls. Since it significantly enhances the durability of castle gates and castle walls, it is a good measure against the incursion of enemy troops into the castle. <center><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 1 20220001 20220002">Reinforce outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 2 20220005 20220006">Reinforce inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 3 20220003 20220004">Reinforce castle walls</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.htm">Go back</Button>
</center>
</body> </html>

View File

@@ -0,0 +1,6 @@
<html><body>&$556;<br><br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13008" msg="811;Front Of Dion Castle">Front Of Dion Castle</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13009" msg="811;Dion Town Square">Dion Town Square</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13010" msg="811;Front of the Hive Fortress">Front of the Hive Fortress</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13011" msg="811;Entrance to Floran Village">Entrance to Floran Village</Button>
</body></html>

View File

@@ -0,0 +1,10 @@
<html><body>&$556;<br><br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13008" msg="811;Front Of Dion Castle">Front Of Dion Castle</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13009" msg="811;Dion Town Square">Dion Town Square</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13010" msg="811;Front of the Hive Fortress">Front of the Hive Fortress</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13011" msg="811;Entrance to Floran Village">Entrance to Floran Village</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13012" msg="811;Cruma Marshlands">Cruma Marshlands - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13013" msg="811;Fortress of Resistance">Fortress of Resistance - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13014" msg="811;Plains of Dion">Plains of Dion - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13015" msg="811;Tanor Canyon">Tanor Canyon - 500 Adena</Button>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body><br>
Activate the traps located in the interior of the island. Once activated, the flames do not distinguish friend from foe. Used properly, the trap is a very effective deterrent to invasion. Of course, it costs a fortune!<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_trap 0">Activate the trap near the entrance of the inner castle</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_trap 1">Activate the trap behind the garden in the inner castle</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Back</a>
</center>
</body></html>

View File

@@ -0,0 +1,14 @@
<html><body>
<center>
<br><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 23220001 23220002">Open the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 23220001 23220002">Close the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 23220005 23220006">Open the inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 23220005 23220006">Close the inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 23220008">Open the mooring castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 23220008">Close the mooring castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 23220001 23220002 23220005 23220006 23220008">Open all gates</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 23220001 23220002 23220005 23220006 23220008">Close all gates</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,10 @@
<html><body>
Reinforce castle gates:<br>
Strengthens gates and walls. Since it significantly enhances the durability of castle gates and castle walls, it is a good measure against the incursion of enemy troops into the castle.<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 1 23220001 23220002">Reinforce outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 2 23220005 23220006">Reinforce inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 3 23220003 23220004">Reinforce castle walls</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Go back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>&$556;<br><br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13016" msg="811;Front Of Giran Castle">Front Of Giran Castle</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13017" msg="811;Giran Town Square">Giran Town Square</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13018" msg="811;Front of the Valley Fortress">Front of the Valley Fortress</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13019" msg="811;Giran Harbor">Giran Harbor</Button>
</body></html>

View File

@@ -0,0 +1,10 @@
<html><body>&$556;<br><br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13016" msg="811;Front Of Giran Castle">Front Of Giran Castle</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13017" msg="811;Giran Town Square">Giran Town Square</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13018" msg="811;Front of the Valley Fortress">Front of the Valley Fortress</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13019" msg="811;Giran Harbor">Giran Harbor</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13020" msg="811;Breka's Stronghold">Breka's Stronghold - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13021" msg="811;Devil's Isle">Devil's Isle - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13022" msg="811;Dragon Valley">Dragon Valley - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13023" msg="811;Tanor Canyon">Tanor Canyon - 500 Adena</Button>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body><br>
Activate the traps located in the interior of the island. Once activated, the flames do not distinguish friend from foe. Used properly, the trap is a very effective deterrent to invasion. Of course, it costs a fortune!<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_trap 0">Activate the trap near the entrance of the inner castle</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_trap 1">Activate the trap behind the garden in the inner castle</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Go back</a>
</center>
</body></html>

View File

@@ -0,0 +1,14 @@
<html><body>
<center>
<br><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 19210001 19210002">Open the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 19210001 19210002">Close the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 19210005 19210006">Open the inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 19210005 19210006">Close the inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 19210008">Open the mooring castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 19210008">Close the mooring castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 19210001 19210002 19210005 19210006 19210008">Open all gates</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 19210001 19210002 19210005 19210006 19210008">Close all gates</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,10 @@
<html><body>
Reinforce castle gates:<br>
Strengthens gates and walls. Since it significantly enhances the durability of castle gates and castle walls, it is a good measure against the incursion of enemy troops into the castle.<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 1 19210001 19210002">Reinforce outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 2 19210005 19210006">Reinforce inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 3 19210003 19210004">Reinforce castle walls</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Go back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>&$556;<br><br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13000" msg="811;Front of the Gludio Castle">Front of the Gludio Castle</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13001" msg="811;Gludio Town Square">Gludio Town Square</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13002" msg="811;Front of the Shanty Fortress">Front of the Shanty Fortress</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13003" msg="811;Front of the Southern Fortress">Front of the Southern Fortress</Button>
</body></html>

View File

@@ -0,0 +1,10 @@
<html><body>&$556;<br><br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13000" msg="811;Front of the Gludio Castle">Front of the Gludio Castle</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13001" msg="811;Gludio Town Square">Gludio Town Square</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13002" msg="811;Front of the Shanty Fortress">Front of the Shanty Fortress</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13003" msg="811;Front of the Southern Fortress">Front of the Southern Fortress</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13004" msg="811;Ruins of Agony">Ruins of Agony - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13005" msg="811;Ruins of Despair">Ruins of Despair - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13006" msg="811;The Ant Nest">The Ant Nest - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13007" msg="811;Windawood Manor">Windawood Manor - 500 Adena</Button>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body><br>
Activate the traps located in the interior of the island. Once activated, the flames do not distinguish friend from foe. Used properly, the trap is a very effective deterrent to invasion. Of course, it costs a fortune!<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_trap 0">Activate the trap near the entrance of the inner castle.</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_trap 1">Activate the trap behind the garden in the inner castle.</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,16 @@
<html><body>
<center>
<br><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24160010 24160009">Open the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24160010 24160009">Close the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24160011 24160012">Open the inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24160011 24160012">Close the inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24160013 24160014">Open the inner 2nd floor castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24160013 24160014">Close the inner 2nd floor castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24160015 24160016">Open the mooring castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24160015 24160016">Close the mooring castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 24160010 24160009 24160011 24160012 24160013 24160014 24160015 24160016">Open all gates</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 24160010 24160009 24160011 24160012 24160013 24160014 24160015 24160016">Close all gates</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,10 @@
<html><body>Door Reinforcement:<br>
The doors or walls of the castle are currently being reinforced. This will help defend against enemy attacks.<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 1 24160010 24160009">Outer Door Reinforcement</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 2 24160011 24160012">Inner Door Reinforcement 1F</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 2 24160013 24160014">Inner Door Reinforcement 2F</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 3 24160021 24160022">Wall Reinforcement</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Go back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>&$556;<br><br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13047" msg="811;Front Of Goddard Castle">Front Of Goddard Castle</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13048" msg="811;Goddard Town Square">Goddard Town Square</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13049" msg="811;Front of the Borderland Fortress">Front of the Borderland Fortress</Button>
</body></html>

View File

@@ -0,0 +1,10 @@
<html><body>&$556;<br><br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13047" msg="811;Front Of Goddard Castle">Front Of Goddard Castle</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13048" msg="811;Goddard Town Square">Goddard Town Square</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13049" msg="811;Front of the Borderland Fortress">Front of the Borderland Fortress</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13050" msg="811;Hot Springs">Hot Springs - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13051" msg="811;Varka Silenos Stronghold">Varka Silenos Stronghold - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13052" msg="811;Ketra Orc Outpost">Ketra Orc Outpost - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13053" msg="811;Entrance to the Forge of the Gods">Entrance to the Forge of the Gods - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13054" msg="811;Wall of Argos">Wall of Argos - 500 Adena</Button>
</body></html>

View File

@@ -0,0 +1,10 @@
<html><body><br>
Activates a trap inside the castle. When activated, magic fire shoots from the trap, slowing those crossing it and engulfing them in flames.<br>
These flames will consume friends as well as foes. Used with great care, this is one of the most effective security devices available.<br>
Of course, it's not cheap!<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_trap 0">Activate the trap near the east entrance of the 2nd floor.</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_trap 1">Activate the trap near the west entrance of the 2nd floor.</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,14 @@
<html><body>
<center>
<br><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 23250002 23250001">Open the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 23250002 23250001">Close the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 23250006 23250005">Open the inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 23250006 23250005">Close the inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 23250008">Open the mooring castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 23250008">Close the mooring castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 23250002 23250001 23250006 23250005 23250008">Open all gates</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 23250002 23250001 23250006 23250005 23250008">Close all gates</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,10 @@
<html><body>
Reinforce castle gates:<br>
Strengthens gates and walls. Since it significantly enhances the durability of castle gates and castle walls, it is a good measure against the incursion of enemy troops into the castle.<br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 1 23250002 23250001">Reinforce outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 2 23250006 23250005">Reinforce inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_doors 3 23250003 23250004">Reinforce castle walls</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Go back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>&$556;<br><br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13040" msg="811;Front Of Innadril Castle">Front Of Innadril Castle</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13041" msg="811;Heine Town Square">Heine Town Square</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13042" msg="811;Front of the White Sands Fortress">Front of the White Sands Fortress</Button>
</body></html>

View File

@@ -0,0 +1,9 @@
<html><body>&$556;<br><br>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13040" msg="811;Front Of Innadril Castle">Front Of Innadril Castle</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13041" msg="811;Heine Town Square">Heine Town Square</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13042" msg="811;Front of the White Sands Fortress">Front of the White Sands Fortress</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13043" msg="811;The Center of Alligator Island">The Center of Alligator Island - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13044" msg="811;Field of Silence">Field of Silence - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13045" msg="811;Field of Whispers">Field of Whispers - 500 Adena</Button>
<Button ALIGN=LEFT ICON="TELEPORT" action="bypass -h Quest CastleChamberlain goto 13046" msg="811;Inside the Garden of Eva">Inside the Garden of Eva - 500 Adena</Button>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body><br>
Activate the traps located in the interior of the island. Once activated, the flames do not distinguish friend from foe. Used properly, the trap is a very effective deterrent to invasion. Of course, it costs a fortune!<br><br>
<center>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_trap 0">Activate the trap near the entrance of the inner castle.</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain manage_trap 1">Activate the trap behind the garden in the inner castle.</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Back</Button>
</center>
</body></html>

View File

@@ -0,0 +1,14 @@
<html><body>
<center>
<br><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 22190001 22190002">Open the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 22190001 22190002">Close the outer castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 22190005 22190006">Open the inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 22190005 22190006">Close the inner castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 22190008">Open the mooring castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 22190008">Close the mooring castle gate</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 1 22190001 22190002 22190005 22190006 22190008">Open all gates</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CastleChamberlain operate_door 0 22190001 22190002 22190005 22190006 22190008">Close all gates</Button>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest CastleChamberlain chamberlain-01.html">Back</Button>
</center>
</body></html>

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