Merged with released L2J-Unity files.

This commit is contained in:
mobiusdev
2016-06-12 01:34:09 +00:00
parent e003e87887
commit 635557f5da
18352 changed files with 3245113 additions and 2892959 deletions

View File

@@ -1,323 +1,242 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.enums.InstanceReenterType;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.L2Summon;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Instance;
import com.l2jmobius.gameserver.model.holders.InstanceReenterTimeHolder;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import ai.AbstractNpcAI;
/**
* Abstract class for Instances.
* @author FallenAngel
*/
public abstract class AbstractInstance extends AbstractNpcAI
{
public AbstractInstance(String name, String desc)
{
super(name, desc);
}
public AbstractInstance(String name)
{
super(name, "instances");
}
protected void enterInstance(L2PcInstance player, InstanceWorld instance, String template, int templateId)
{
final InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (world != null)
{
if (world.getTemplateId() == templateId)
{
onEnterInstance(player, world, false);
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
if (inst.isRemoveBuffEnabled())
{
handleRemoveBuffs(player, world);
}
return;
}
player.sendPacket(SystemMessageId.YOU_HAVE_ENTERED_ANOTHER_INSTANT_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON);
return;
}
if (checkConditions(player, templateId))
{
instance.setInstanceId(InstanceManager.getInstance().createDynamicInstance(template));
instance.setTemplateId(templateId);
instance.setStatus(0);
InstanceManager.getInstance().addWorld(instance);
onEnterInstance(player, instance, true);
final Instance inst = InstanceManager.getInstance().getInstance(instance.getInstanceId());
if (inst.getReenterType() == InstanceReenterType.ON_INSTANCE_ENTER)
{
handleReenterTime(instance);
}
if (inst.isRemoveBuffEnabled())
{
handleRemoveBuffs(instance);
}
if (Config.DEBUG_INSTANCES)
{
_log.info("Instance " + inst.getName() + " (" + instance.getTemplateId() + ") has been created by player " + player.getName());
}
}
}
protected void finishInstance(InstanceWorld world)
{
finishInstance(world, Config.INSTANCE_FINISH_TIME);
}
private void finishInstance(InstanceWorld world, int duration)
{
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
if (inst.getReenterType() == InstanceReenterType.ON_INSTANCE_FINISH)
{
handleReenterTime(world);
}
if (duration == 0)
{
InstanceManager.getInstance().destroyInstance(inst.getId());
}
else if (duration > 0)
{
inst.setDuration(duration);
inst.setEmptyDestroyTime(0);
}
}
protected void handleReenterTime(InstanceWorld world)
{
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
final List<InstanceReenterTimeHolder> reenterData = inst.getReenterData();
long time = -1;
for (InstanceReenterTimeHolder data : reenterData)
{
if (data.getTime() > 0)
{
time = System.currentTimeMillis() + data.getTime();
break;
}
final Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.AM_PM, data.getHour() >= 12 ? 1 : 0);
calendar.set(Calendar.HOUR, data.getHour());
calendar.set(Calendar.MINUTE, data.getMinute());
calendar.set(Calendar.SECOND, 0);
if (calendar.getTimeInMillis() <= System.currentTimeMillis())
{
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
if (data.getDay() != null)
{
while (calendar.get(Calendar.DAY_OF_WEEK) != (data.getDay().getValue() + 1))
{
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
}
if (time == -1)
{
time = calendar.getTimeInMillis();
}
else if (calendar.getTimeInMillis() < time)
{
time = calendar.getTimeInMillis();
}
}
if (time > 0)
{
setReenterTime(world, time);
}
}
private void handleRemoveBuffs(InstanceWorld world)
{
for (int objId : world.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objId);
if (player != null)
{
handleRemoveBuffs(player, world);
}
}
}
protected abstract void onEnterInstance(L2PcInstance player, InstanceWorld world, boolean firstEntrance);
protected boolean checkConditions(L2PcInstance player, int templateId)
{
return checkConditions(player);
}
protected boolean checkConditions(L2PcInstance player)
{
return true;
}
/**
* Spawns group of instance NPC's
* @param groupName the name of group from XML definition to spawn
* @param instanceId the instance ID
* @return list of spawned NPC's
*/
protected List<L2Npc> spawnGroup(String groupName, int instanceId)
{
return InstanceManager.getInstance().getInstance(instanceId).spawnGroup(groupName);
}
/**
* Sets reenter time for every player in the instance.
* @param world the instance
* @param time the time in milliseconds
*/
private void setReenterTime(InstanceWorld world, long time)
{
for (int objectId : world.getAllowed())
{
InstanceManager.getInstance().setInstanceTime(objectId, world.getTemplateId(), time);
final L2PcInstance player = L2World.getInstance().getPlayer(objectId);
if ((player != null) && player.isOnline())
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.INSTANT_ZONE_S1_S_ENTRY_HAS_BEEN_RESTRICTED_YOU_CAN_CHECK_THE_NEXT_POSSIBLE_ENTRY_TIME_BY_USING_THE_COMMAND_INSTANCEZONE).addString(InstanceManager.getInstance().getInstance(world.getInstanceId()).getName()));
}
}
if (Config.DEBUG_INSTANCES)
{
_log.info("Time restrictions has been set for player in instance ID: " + world.getInstanceId() + " (" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time) + ")");
}
}
private void handleRemoveBuffs(L2PcInstance player, InstanceWorld world)
{
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
switch (inst.getRemoveBuffType())
{
case ALL:
{
player.stopAllEffectsExceptThoseThatLastThroughDeath();
final L2Summon pet = player.getPet();
if (pet != null)
{
pet.stopAllEffectsExceptThoseThatLastThroughDeath();
}
player.getServitors().values().forEach(L2Summon::stopAllEffectsExceptThoseThatLastThroughDeath);
break;
}
case WHITELIST:
{
for (BuffInfo info : player.getEffectList().getBuffs())
{
if (!inst.getBuffExceptionList().contains(info.getSkill().getId()))
{
info.getEffected().getEffectList().stopSkillEffects(true, info.getSkill());
}
}
for (L2Summon summon : player.getServitors().values())
{
for (BuffInfo info : summon.getEffectList().getBuffs())
{
if (!inst.getBuffExceptionList().contains(info.getSkill().getId()))
{
info.getEffected().getEffectList().stopSkillEffects(true, info.getSkill());
}
}
}
final L2Summon pet = player.getPet();
if (pet != null)
{
for (BuffInfo info : pet.getEffectList().getBuffs())
{
if (!inst.getBuffExceptionList().contains(info.getSkill().getId()))
{
info.getEffected().getEffectList().stopSkillEffects(true, info.getSkill());
}
}
}
break;
}
case BLACKLIST:
{
for (BuffInfo info : player.getEffectList().getBuffs())
{
if (inst.getBuffExceptionList().contains(info.getSkill().getId()))
{
info.getEffected().getEffectList().stopSkillEffects(true, info.getSkill());
}
}
for (L2Summon summon : player.getServitors().values())
{
for (BuffInfo info : summon.getEffectList().getBuffs())
{
if (inst.getBuffExceptionList().contains(info.getSkill().getId()))
{
info.getEffected().getEffectList().stopSkillEffects(true, info.getSkill());
}
}
}
final L2Summon pet = player.getPet();
if (pet != null)
{
for (BuffInfo info : pet.getEffectList().getBuffs())
{
if (inst.getBuffExceptionList().contains(info.getSkill().getId()))
{
info.getEffected().getEffectList().stopSkillEffects(true, info.getSkill());
}
}
}
break;
}
}
}
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances;
import java.util.List;
import com.l2jmobius.gameserver.enums.InstanceReenterType;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.instancezone.InstanceTemplate;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import ai.AbstractNpcAI;
/**
* Abstract class for Instances.
* @author FallenAngel
*/
public abstract class AbstractInstance extends AbstractNpcAI
{
/**
* Get instance world associated with {@code player}.<br>
* @param player player who wants get instance world
* @return instance world if found, otherwise null
*/
public Instance getPlayerInstance(L2PcInstance player)
{
return InstanceManager.getInstance().getPlayerInstance(player, false);
}
/**
* Show an on screen message to each player inside instance.
* @param instance instance where message should be broadcasted
* @param npcStringId the NPC string to display
* @param position the position of the message on the screen
* @param time the duration of the message in milliseconds
* @param params values of parameters to replace in the NPC String (like S1, C1 etc.)
*/
public void showOnScreenMsg(Instance instance, NpcStringId npcStringId, int position, int time, String... params)
{
instance.broadcastPacket(new ExShowScreenMessage(npcStringId, position, time, params));
}
/**
* Show an on screen message to each player inside instance.
* @param instance instance where message should be broadcasted
* @param npcStringId the NPC string to display
* @param position the position of the message on the screen
* @param time the duration of the message in milliseconds
* @param showEffect show visual effect near text
* @param params values of parameters to replace in the NPC String (like S1, C1 etc.)
*/
public void showOnScreenMsg(Instance instance, NpcStringId npcStringId, int position, int time, boolean showEffect, String... params)
{
instance.broadcastPacket(new ExShowScreenMessage(npcStringId, position, time, showEffect, params));
}
/**
* Put player into instance world.<br>
* If instance world doesn't found for player then try to create new one.
* @param player player who wants to enter into instance
* @param npc NPC which allows to enter into instance
* @param templateId template ID of instance where player wants to enter
*/
protected final void enterInstance(L2PcInstance player, L2Npc npc, int templateId)
{
Instance instance = getPlayerInstance(player);
if (instance != null) // Player has already any instance active
{
if (instance.getTemplateId() != templateId)
{
player.sendPacket(SystemMessageId.YOU_HAVE_ENTERED_ANOTHER_INSTANT_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON);
return;
}
onEnter(player, instance, false);
}
else
{
// Get instance template
final InstanceManager manager = InstanceManager.getInstance();
final InstanceTemplate template = manager.getInstanceTemplate(templateId);
if (template == null)
{
_log.warning("Player " + player.getName() + " (" + player.getObjectId() + ") wants to create instance with unknown template id " + templateId + "!");
return;
}
// Get instance enter scope
final List<L2PcInstance> enterGroup = template.getEnterGroup(player);
// When nobody can enter
if (enterGroup == null)
{
_log.warning("Instance " + template.getName() + " (" + templateId + ") has invalid group size limits!");
return;
}
// Validate conditions for group
if (!player.canOverrideCond(PcCondOverride.INSTANCE_CONDITIONS) && (!template.validateConditions(enterGroup, npc, this::showHtmlFile) || !validateConditions(enterGroup, npc, template)))
{
return;
}
// Check if maximum world count limit is exceeded
if ((template.getMaxWorlds() != -1) && (manager.getWorldCount(templateId) >= template.getMaxWorlds()))
{
player.sendPacket(SystemMessageId.THE_NUMBER_OF_INSTANT_ZONES_THAT_CAN_BE_CREATED_HAS_BEEN_EXCEEDED_PLEASE_TRY_AGAIN_LATER);
return;
}
// Check if any player from enter group has active instance
for (L2PcInstance member : enterGroup)
{
if (getPlayerInstance(member) != null)
{
enterGroup.forEach(p -> p.sendPacket(SystemMessageId.YOU_HAVE_ENTERED_ANOTHER_INSTANT_ZONE_THEREFORE_YOU_CANNOT_ENTER_CORRESPONDING_DUNGEON));
return;
}
}
// Create new instance for enter player group
instance = manager.createInstance(template, player);
// Move each player from enter group to instance
for (L2PcInstance member : enterGroup)
{
instance.addAllowed(member);
onEnter(member, instance, true);
}
// Apply condition success effects
template.applyConditionEffects(enterGroup);
// Set re-enter for instances with re-enter on start
if (instance.getReenterType().equals(InstanceReenterType.ON_ENTER))
{
instance.setReenterTime();
}
}
}
/**
* This function is called when player enter into instance trough NPC.
* @param player player who enter
* @param instance instance world where player enter
* @param firstEnter when {@code true} player enter first time, otherwise player entered multiple times
*/
protected void onEnter(L2PcInstance player, Instance instance, boolean firstEnter)
{
teleportPlayerIn(player, instance);
}
/**
* This method is used to teleport player into instance by start NPC.<br>
* When you override whole method, XML teleport data won't be applied.
* @param player player which should be teleported
* @param instance instance where player should be teleported
*/
protected void teleportPlayerIn(L2PcInstance player, Instance instance)
{
final Location loc = instance.getEnterLocation();
if (loc != null)
{
player.teleToLocation(loc, instance);
}
else
{
_log.warning("Missing start location for instance instance.getName() (" + instance.getId() + ")");
}
}
/**
* This method is used to teleport player from instance world by NPC.
* @param player player which should be ejected
* @param instance instance from player should be removed
*/
protected void teleportPlayerOut(L2PcInstance player, Instance instance)
{
instance.ejectPlayer(player);
}
/**
* Sets instance to finish state. <br>
* See {@link Instance#finishInstance()} for more details.
* @param player player used for determine current instance world
*/
protected void finishInstance(L2PcInstance player)
{
final Instance inst = player.getInstanceWorld();
if (inst != null)
{
inst.finishInstance();
}
}
/**
* Sets instance to finish state.<br>
* See {@link Instance#finishInstance(int)} for more details.
* @param player player used for determine current instance world
* @param delay finish delay in minutes
*/
protected void finishInstance(L2PcInstance player, int delay)
{
final Instance inst = player.getInstanceWorld();
if (inst != null)
{
inst.finishInstance(delay);
}
}
/**
* This method is supposed to be used for validation of additional conditions that are too much specific to instance world (to avoid useless core conditions).<br>
* These conditions are validated after conditions defined in XML template.
* @param group group of players which wants to enter (first player inside list is player who make enter request)
* @param npc NPC used for enter
* @param template template of instance world which should be created
* @return {@code true} when conditions are valid, otherwise {@code false}
*/
protected boolean validateConditions(List<L2PcInstance> group, L2Npc npc, InstanceTemplate template)
{
return true;
}
}

View File

@@ -0,0 +1,337 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.BaylorWarzone;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Attackable;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureDeath;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureSee;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.skills.Skill;
import instances.AbstractInstance;
/**
* Baylor Warzone instance zone.
* @author St3eT
*/
public final class BaylorWarzone extends AbstractInstance
{
// NPCs
private static final int BAYLOR = 29213;
private static final int PRISON_GUARD = 29104;
private static final int ENTRANCE_PORTAL = 33523;
private static final int INVISIBLE_NPC_1 = 29106;
private static final int INVISIBLE_NPC_2 = 29108;
private static final int INVISIBLE_NPC_3 = 29109;
// Skills
private static final SkillHolder INVIS_NPC_SOCIAL_SKILL = new SkillHolder(5401, 1);
private static final SkillHolder BAYLOR_SOCIAL_SKILL = new SkillHolder(5402, 1);
// Locations
private static final Location BATTLE_PORT = new Location(153567, 143319, -12736);
// Misc
private static final int TEMPLATE_ID = 166;
public BaylorWarzone()
{
addStartNpc(ENTRANCE_PORTAL);
addTalkId(ENTRANCE_PORTAL);
addInstanceCreatedId(TEMPLATE_ID);
addSpawnId(INVISIBLE_NPC_1);
addSpellFinishedId(INVISIBLE_NPC_1);
setCreatureSeeId(this::onCreatureSee, INVISIBLE_NPC_1);
setCreatureKillId(this::onBossKill, BAYLOR);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("enterInstance"))
{
enterInstance(player, npc, TEMPLATE_ID);
}
return super.onAdvEvent(event, npc, player);
}
@Override
public void onTimerEvent(String event, StatsSet params, L2Npc npc, L2PcInstance player)
{
final Instance world = npc.getInstanceWorld();
if (isBylorInstance(world))
{
switch (event)
{
case "START_SCENE_01":
{
specialCamera(world, npc, 2300, 0, 90, 2000, 3000, 2500, 0, 180, 1, 0, 1);
playSound(world, "BS06_A");
getTimers().addTimer("START_SCENE_02", 2000, npc, null);
break;
}
case "START_SCENE_02":
{
specialCamera(world, npc, 10, 180, 0, 17000, 3000, 30000, 0, 20, 1, 0, 0);
getTimers().addTimer("START_SCENE_03", 17000, npc, null);
break;
}
case "START_SCENE_03":
{
specialCamera(world, npc, 15, 15, 0, 6000, 3000, 9000, 0, 10, 1, 0, 0);
getTimers().addTimer("START_SCENE_04", 6000, npc, null);
break;
}
case "START_SCENE_04":
{
specialCamera(world, npc, 5, 200, 0, 6000, 3000, 9000, 0, 10, 1, 0, 0);
getTimers().addTimer("START_SCENE_05", 6000, npc, null);
break;
}
case "START_SCENE_05":
{
specialCamera(world, npc, 5, 70, 0, 4000, 3000, 9000, 0, 10, 1, 0, 0);
getTimers().addTimer("START_SCENE_06", 4000, npc, null);
break;
}
case "START_SCENE_06":
{
specialCamera(world, npc, 200, 60, 0, 1000, 3000, 4000, 0, 6, 1, 0, 0);
getTimers().addTimer("START_SCENE_07", 1000, npc, null);
break;
}
case "START_SCENE_07":
{
specialCamera(world, npc, 500, 260, 0, 8000, 3000, 9000, 0, 10, 1, 0, 0);
getTimers().addTimer("SPAWN_GUARD_1", 100, e -> world.spawnGroup("PRISON_GUARD_GROUP_1"));
getTimers().addTimer("SPAWN_GUARD_2", 2100, e -> world.spawnGroup("PRISON_GUARD_GROUP_2"));
getTimers().addTimer("SPAWN_GUARD_3", 4100, e -> world.spawnGroup("PRISON_GUARD_GROUP_3"));
getTimers().addTimer("SPAWN_GUARD_4", 6100, e -> world.spawnGroup("PRISON_GUARD_GROUP_4"));
getTimers().addTimer("START_SCENE_08", 8000, npc, null);
break;
}
case "START_SCENE_08":
{
specialCamera(world, npc, 850, 260, 70, 2000, 3000, 5000, 0, 0, 1, 0, 0);
getTimers().addTimer("START_SCENE_09", 2000, npc, null);
break;
}
case "START_SCENE_09":
{
specialCamera(world, npc, 0, 260, 70, 1800, 3000, 2000, 0, 0, 1, 0, 0);
getTimers().addTimer("START_SCENE_10", 1800, npc, null);
getTimers().addTimer("START_SCENE_12", 1000, npc, null);
break;
}
case "START_SCENE_10":
{
specialCamera(world, npc, 200, 20, 0, 100, 3000, 5000, 160, 15, 1, 0, 0);
getTimers().addTimer("START_SCENE_11", 2000, npc, null);
break;
}
case "START_SCENE_11":
{
specialCamera(world, npc, 100, 20, 0, 4000, 3000, 7000, 160, 10, 1, 0, 0);
getTimers().addTimer("START_SCENE_14", 6500, npc, null);
break;
}
case "START_SCENE_12":
{
int count = 0;
for (L2Npc baylor : world.spawnGroup("BAYLOR"))
{
baylor.getVariables().set("is_after_you", count);
baylor.disableCoreAI(true);
baylor.setRandomAnimation(false);
baylor.setRandomWalking(false);
((L2Attackable) baylor).setCanReturnToSpawnPoint(false);
count++;
}
getTimers().addTimer("START_SCENE_13", 300, npc, null);
break;
}
case "START_SCENE_13":
{
world.getAliveNpcs(BAYLOR).forEach(baylor ->
{
getTimers().addTimer("BAYLOR_SOCIAL_SKILL", (baylor.getVariables().getInt("is_after_you") == 0 ? 14 : 16) * 1000, baylor, null);
broadcastSocialAction(baylor, 1);
});
break;
}
case "START_SCENE_14":
{
world.getAliveNpcs(INVISIBLE_NPC_3).forEach(invisNpc ->
{
specialCamera(world, invisNpc, 45, 237, 0, 0, 3000, 5000, 0, 27, 1, 0, 1);
getTimers().addTimer("START_SCENE_15", 1500, invisNpc, null);
});
world.getAliveNpcs(PRISON_GUARD).forEach(guard ->
{
final int random = getRandom(100);
if (random >= 20)
{
broadcastSocialAction(guard, 2);
}
else if (random >= 40)
{
getTimers().addTimer("SOCIAL_ACTION", 250, e -> broadcastSocialAction(guard, 2));
}
else if (random >= 60)
{
getTimers().addTimer("SOCIAL_ACTION", 500, e -> broadcastSocialAction(guard, 2));
}
else if (random >= 80)
{
getTimers().addTimer("SOCIAL_ACTION", 700, e -> broadcastSocialAction(guard, 2));
}
else
{
getTimers().addTimer("SOCIAL_ACTION", 800, e -> broadcastSocialAction(guard, 2));
}
});
break;
}
case "START_SCENE_15":
{
world.getAliveNpcs(INVISIBLE_NPC_3).forEach(invisNpc ->
{
specialCamera(world, invisNpc, 500, 212, 0, 1500, 3000, 3000, 357, 15, 1, 0, 1);
getTimers().addTimer("START_SCENE_16", 1500, invisNpc, null);
});
getTimers().addTimer("NPC_DESPAWN", 3000, e -> npc.deleteMe());
break;
}
case "START_SCENE_16":
{
specialCamera(world, npc, 500, 212, 0, 1000, 3000, 3000, 357, 40, 1, 0, 0);
getTimers().addTimer("START_SCENE_17", 1000, npc, null);
break;
}
case "START_SCENE_17":
{
specialCamera(world, npc, 900, 212, 0, 1000, 3000, 3000, 357, 10, 1, 0, 0);
getTimers().addTimer("START_SCENE_18", 2000, npc, null);
break;
}
case "START_SCENE_18":
{
specialCamera(world, npc, 500, 212, 0, 3000, 3000, 15000, 357, 20, 1, 0, 0);
getTimers().addTimer("START_SCENE_19", 7000, npc, null);
break;
}
case "START_SCENE_19":
{
specialCamera(world, npc, 700, 212, 30, 1000, 7000, 2500, 357, 0, 1, 0, 0);
break;
}
case "BAYLOR_SOCIAL_SKILL":
{
npc.doCast(BAYLOR_SOCIAL_SKILL.getSkill());
npc.disableCoreAI(false);
world.getAliveNpcs(INVISIBLE_NPC_1).forEach(invisNpc -> getTimers().addTimer("INVIS_NPC_SOCIAL_SKILL", 1300, invisNpc, null));
break;
}
case "INVIS_NPC_SOCIAL_SKILL":
{
npc.doCast(INVIS_NPC_SOCIAL_SKILL.getSkill());
break;
}
}
}
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
final Instance world = npc.getInstanceWorld();
if (isBylorInstance(world))
{
world.getAliveNpcs(INVISIBLE_NPC_1, INVISIBLE_NPC_2, INVISIBLE_NPC_3).forEach(L2Npc::deleteMe);
world.getAliveNpcs(PRISON_GUARD).forEach(guard -> guard.doDie(null));
npc.deleteMe();
}
return super.onSpellFinished(npc, player, skill);
}
@Override
public void onInstanceCreated(Instance instance, L2PcInstance player)
{
getTimers().addTimer("BATTLE_PORT", 3000, e ->
{
instance.getPlayers().forEach(p -> p.teleToLocation(BATTLE_PORT));
instance.getDoors().forEach(L2DoorInstance::closeMe);
});
}
public void onBossKill(OnCreatureDeath event)
{
final L2Npc npc = (L2Npc) event.getTarget();
final Instance world = npc.getInstanceWorld();
if (isBylorInstance(world))
{
if (world.getAliveNpcs(BAYLOR).isEmpty())
{
world.finishInstance();
}
else
{
world.setReenterTime();
}
}
}
public void onCreatureSee(OnCreatureSee event)
{
final L2Character creature = event.getSeen();
final L2Npc npc = (L2Npc) event.getSeer();
final Instance world = npc.getInstanceWorld();
if (isBylorInstance(world) && creature.isPlayer() && npc.isScriptValue(0))
{
npc.setScriptValue(1);
getTimers().addTimer("START_SCENE_01", 5000, npc, null);
}
}
@Override
public String onSpawn(L2Npc npc)
{
if (npc.getId() == INVISIBLE_NPC_1)
{
npc.initSeenCreatures();
}
return super.onSpawn(npc);
}
private boolean isBylorInstance(Instance instance)
{
return (instance != null) && (instance.getTemplateId() == TEMPLATE_ID);
}
public static void main(String[] args)
{
new BaylorWarzone();
}
}

View File

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

View File

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

View File

@@ -1,501 +1,351 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.CavernOfThePirateCaptain;
import java.util.ArrayList;
import java.util.List;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.L2Party;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Attackable;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import instances.AbstractInstance;
/**
* Cavern Of The Pirate Captain (Day Dream) instance Zone.
* @author St3eT
*/
public final class CavernOfThePirateCaptain extends AbstractInstance
{
class CavernOfThePirateCaptainWorld extends InstanceWorld
{
final List<L2PcInstance> playersInside = new ArrayList<>();
L2Attackable _zaken;
long storeTime = 0;
boolean _is83;
int _zakenRoom;
int _blueFounded;
}
// NPCs
private static final int PATHFINDER = 32713; // Pathfinder Worker
private static final int ZAKEN_60 = 29176; // Zaken
private static final int ZAKEN_83 = 29181; // Zaken
private static final int CANDLE = 32705; // Zaken's Candle
private static final int DOLL_BLADER_60 = 29023; // Doll Blader
private static final int DOLL_BLADER_83 = 29182; // Doll Blader
private static final int VALE_MASTER_60 = 29024; // Veil Master
private static final int VALE_MASTER_83 = 29183; // Veil Master
private static final int PIRATES_ZOMBIE_60 = 29027; // Pirate Zombie
private static final int PIRATES_ZOMBIE_83 = 29185; // Pirate Zombie
private static final int PIRATES_ZOMBIE_CAPTAIN_60 = 29026; // Pirate Zombie Captain
private static final int PIRATES_ZOMBIE_CAPTAIN_83 = 29184; // Pirate Zombie Captain
// Items
private static final int VORPAL_RING = 15763; // Sealed Vorpal Ring
private static final int VORPAL_EARRING = 15764; // Sealed Vorpal Earring
// Locations
private static final Location[] ENTER_LOC =
{
new Location(52684, 219989, -3496),
new Location(52669, 219120, -3224),
new Location(52672, 219439, -3312),
};
private static final Location[] CANDLE_LOC =
{
// Floor 1
new Location(53313, 220133, -3498),
new Location(53313, 218079, -3498),
new Location(54240, 221045, -3498),
new Location(54325, 219095, -3498),
new Location(54240, 217155, -3498),
new Location(55257, 220028, -3498),
new Location(55257, 218172, -3498),
new Location(56280, 221045, -3498),
new Location(56195, 219095, -3498),
new Location(56280, 217155, -3498),
new Location(57215, 220133, -3498),
new Location(57215, 218079, -3498),
// Floor 2
new Location(53313, 220133, -3226),
new Location(53313, 218079, -3226),
new Location(54240, 221045, -3226),
new Location(54325, 219095, -3226),
new Location(54240, 217155, -3226),
new Location(55257, 220028, -3226),
new Location(55257, 218172, -3226),
new Location(56280, 221045, -3226),
new Location(56195, 219095, -3226),
new Location(56280, 217155, -3226),
new Location(57215, 220133, -3226),
new Location(57215, 218079, -3226),
// Floor 3
new Location(53313, 220133, -2954),
new Location(53313, 218079, -2954),
new Location(54240, 221045, -2954),
new Location(54325, 219095, -2954),
new Location(54240, 217155, -2954),
new Location(55257, 220028, -2954),
new Location(55257, 218172, -2954),
new Location(56280, 221045, -2954),
new Location(56195, 219095, -2954),
new Location(56280, 217155, -2954),
new Location(57215, 220133, -2954),
new Location(57215, 218079, -2954),
};
// Misc
private static final int MIN_LV_60 = 55;
private static final int MIN_LV_83 = 78;
private static final int PLAYERS_60_MIN = 9;
private static final int PLAYERS_60_MAX = 27;
private static final int PLAYERS_83_MIN = 9;
private static final int PLAYERS_83_MAX = 27;
private static final int TEMPLATE_ID_60 = 133;
private static final int TEMPLATE_ID_83 = 135;
//@formatter:off
private static final int[][] ROOM_DATA =
{
// Floor 1
{54240, 220133, -3498, 1, 3, 4, 6},
{54240, 218073, -3498, 2, 5, 4, 7},
{55265, 219095, -3498, 4, 9, 6, 7},
{56289, 220133, -3498, 8, 11, 6, 9},
{56289, 218073, -3498, 10, 12, 7, 9},
// Floor 2
{54240, 220133, -3226, 13, 15, 16, 18},
{54240, 218073, -3226, 14, 17, 16, 19},
{55265, 219095, -3226, 21, 16, 19, 18},
{56289, 220133, -3226, 20, 23, 21, 18},
{56289, 218073, -3226, 22, 24, 19, 21},
// Floor 3
{54240, 220133, -2954, 25, 27, 28, 30},
{54240, 218073, -2954, 26, 29, 28, 31},
{55265, 219095, -2954, 33, 28, 31, 30},
{56289, 220133, -2954, 32, 35, 30, 33},
{56289, 218073, -2954, 34, 36, 31, 33}
};
//@formatter:on
public CavernOfThePirateCaptain()
{
super(CavernOfThePirateCaptain.class.getSimpleName());
addStartNpc(PATHFINDER);
addTalkId(PATHFINDER);
addKillId(ZAKEN_60, ZAKEN_83);
addFirstTalkId(CANDLE);
}
@Override
public void onEnterInstance(L2PcInstance player, InstanceWorld world, boolean firstEntrance)
{
if (firstEntrance)
{
final CavernOfThePirateCaptainWorld curworld = (CavernOfThePirateCaptainWorld) world;
curworld._is83 = curworld.getTemplateId() == TEMPLATE_ID_83;
curworld.storeTime = System.currentTimeMillis();
if (!player.isInParty())
{
managePlayerEnter(player, curworld);
}
else if (player.getParty().isInCommandChannel())
{
for (L2PcInstance players : player.getParty().getCommandChannel().getMembers())
{
managePlayerEnter(players, curworld);
}
}
else
{
for (L2PcInstance players : player.getParty().getMembers())
{
managePlayerEnter(players, curworld);
}
}
manageNpcSpawn(curworld);
}
else
{
teleportPlayer(player, ENTER_LOC[getRandom(ENTER_LOC.length)], world.getInstanceId(), false);
}
}
private void managePlayerEnter(L2PcInstance player, CavernOfThePirateCaptainWorld world)
{
world.playersInside.add(player);
world.addAllowed(player.getObjectId());
teleportPlayer(player, ENTER_LOC[getRandom(ENTER_LOC.length)], world.getInstanceId(), false);
}
@Override
protected boolean checkConditions(L2PcInstance player, int templateId)
{
if (player.canOverrideCond(PcCondOverride.INSTANCE_CONDITIONS))
{
return true;
}
if (!player.isInParty())
{
broadcastSystemMessage(player, null, SystemMessageId.YOU_ARE_NOT_CURRENTLY_IN_A_PARTY_SO_YOU_CANNOT_ENTER, false);
return false;
}
final boolean is83 = templateId == TEMPLATE_ID_83;
final L2Party party = player.getParty();
final boolean isInCC = party.isInCommandChannel();
final List<L2PcInstance> members = isInCC ? party.getCommandChannel().getMembers() : party.getMembers();
final boolean isPartyLeader = isInCC ? party.getCommandChannel().isLeader(player) : party.isLeader(player);
if (!isPartyLeader)
{
broadcastSystemMessage(player, null, SystemMessageId.ONLY_A_PARTY_LEADER_CAN_MAKE_THE_REQUEST_TO_ENTER, false);
return false;
}
if ((members.size() < (is83 ? PLAYERS_83_MIN : PLAYERS_60_MIN)) || (members.size() > (is83 ? PLAYERS_83_MAX : PLAYERS_60_MAX)))
{
broadcastSystemMessage(player, null, SystemMessageId.YOU_CANNOT_ENTER_DUE_TO_THE_PARTY_HAVING_EXCEEDED_THE_LIMIT, false);
return false;
}
for (L2PcInstance groupMembers : members)
{
if (groupMembers.getLevel() < (is83 ? MIN_LV_83 : MIN_LV_60))
{
broadcastSystemMessage(player, groupMembers, SystemMessageId.C1_S_LEVEL_DOES_NOT_CORRESPOND_TO_THE_REQUIREMENTS_FOR_ENTRY, true);
return false;
}
if (!player.isInsideRadius(groupMembers, 1000, true, true))
{
broadcastSystemMessage(player, groupMembers, SystemMessageId.C1_IS_IN_A_LOCATION_WHICH_CANNOT_BE_ENTERED_THEREFORE_IT_CANNOT_BE_PROCESSED, true);
return false;
}
if (System.currentTimeMillis() < InstanceManager.getInstance().getInstanceTime(groupMembers.getObjectId(), is83 ? TEMPLATE_ID_83 : TEMPLATE_ID_60))
{
broadcastSystemMessage(player, groupMembers, SystemMessageId.C1_MAY_NOT_RE_ENTER_YET, true);
return false;
}
}
return true;
}
private void broadcastSystemMessage(L2PcInstance player, L2PcInstance member, SystemMessageId msgId, boolean toGroup)
{
final SystemMessage sm = SystemMessage.getSystemMessage(msgId);
if (toGroup)
{
sm.addPcName(member);
if (player.getParty().isInCommandChannel())
{
player.getParty().getCommandChannel().broadcastPacket(sm);
}
else
{
player.getParty().broadcastPacket(sm);
}
}
else
{
player.broadcastPacket(sm);
}
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("enter60"))
{
enterInstance(player, new CavernOfThePirateCaptainWorld(), "CavernOfThePirateCaptainWorldDay60.xml", TEMPLATE_ID_60);
}
else if (event.equals("enter83"))
{
enterInstance(player, new CavernOfThePirateCaptainWorld(), "CavernOfThePirateCaptainWorldDay83.xml", TEMPLATE_ID_83);
}
else
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof CavernOfThePirateCaptainWorld)
{
final CavernOfThePirateCaptainWorld world = (CavernOfThePirateCaptainWorld) tmpworld;
switch (event)
{
case "BURN_BLUE":
{
if (npc.getDisplayEffect() == 0)
{
npc.setDisplayEffect(1); // Burning
startQuestTimer("BURN_BLUE2", 3000, npc, player);
if (world._blueFounded == 4)
{
startQuestTimer("SHOW_ZAKEN", 5000, npc, player);
}
}
break;
}
case "BURN_BLUE2":
{
if (npc.getDisplayEffect() == 1) // Burning
{
npc.setDisplayEffect(3); // Blue glow
}
break;
}
case "BURN_RED":
{
if (npc.getDisplayEffect() == 0)
{
npc.setDisplayEffect(1); // Burning
startQuestTimer("BURN_RED2", 3000, npc, player);
}
break;
}
case "BURN_RED2":
{
if (npc.getDisplayEffect() == 1) // Burning
{
final int room = getRoomByCandle(npc);
npc.setDisplayEffect(2); // Red glow
manageScreenMsg(world, NpcStringId.THE_CANDLES_CAN_LEAD_YOU_TO_ZAKEN_DESTROY_HIM);
spawnNpc(world._is83 ? DOLL_BLADER_83 : DOLL_BLADER_60, room, player, world);
spawnNpc(world._is83 ? VALE_MASTER_83 : VALE_MASTER_60, room, player, world);
spawnNpc(world._is83 ? PIRATES_ZOMBIE_83 : PIRATES_ZOMBIE_60, room, player, world);
spawnNpc(world._is83 ? PIRATES_ZOMBIE_CAPTAIN_83 : PIRATES_ZOMBIE_CAPTAIN_60, room, player, world);
}
break;
}
case "SHOW_ZAKEN":
{
if (world._is83)
{
manageScreenMsg(world, NpcStringId.WHO_DARES_AWAKEN_THE_MIGHTY_ZAKEN);
}
world._zaken.setInvisible(false);
world._zaken.setIsParalyzed(false);
spawnNpc(world._is83 ? DOLL_BLADER_83 : DOLL_BLADER_60, world._zakenRoom, player, world);
spawnNpc(world._is83 ? PIRATES_ZOMBIE_83 : PIRATES_ZOMBIE_60, world._zakenRoom, player, world);
spawnNpc(world._is83 ? PIRATES_ZOMBIE_CAPTAIN_83 : PIRATES_ZOMBIE_CAPTAIN_60, world._zakenRoom, player, world);
break;
}
}
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof CavernOfThePirateCaptainWorld)
{
final CavernOfThePirateCaptainWorld world = (CavernOfThePirateCaptainWorld) tmpworld;
if (npc.getId() == ZAKEN_83)
{
for (L2PcInstance playersInside : world.playersInside)
{
if ((playersInside != null) && (playersInside.getInstanceId() == world.getInstanceId()) && playersInside.isInsideRadius(npc, 1500, true, true))
{
final long time = System.currentTimeMillis() - world.storeTime;
if (time <= 300000) // 5 minutes
{
if (getRandomBoolean())
{
giveItems(playersInside, VORPAL_RING, 1);
}
}
else if (time <= 600000) // 10 minutes
{
if (getRandom(100) < 30)
{
giveItems(playersInside, VORPAL_EARRING, 1);
}
}
else if ((time <= 900000) && (getRandom(100) < 25)) // 15 minutes
{
giveItems(playersInside, VORPAL_RING, 1);
}
}
}
}
finishInstance(world);
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof CavernOfThePirateCaptainWorld)
{
final CavernOfThePirateCaptainWorld world = (CavernOfThePirateCaptainWorld) tmpworld;
final boolean isBlue = npc.getVariables().getInt("isBlue", 0) == 1;
if (npc.isScriptValue(0))
{
if (isBlue)
{
world._blueFounded++;
startQuestTimer("BURN_BLUE", 500, npc, player);
}
else
{
startQuestTimer("BURN_RED", 500, npc, player);
}
npc.setScriptValue(1);
}
}
return null;
}
private int getRoomByCandle(L2Npc npc)
{
final int candleId = npc.getVariables().getInt("candleId", 0);
for (int i = 0; i < 15; i++)
{
if ((ROOM_DATA[i][3] == candleId) || (ROOM_DATA[i][4] == candleId))
{
return i + 1;
}
}
if ((candleId == 6) || (candleId == 7))
{
return 3;
}
else if ((candleId == 18) || (candleId == 19))
{
return 8;
}
else if ((candleId == 30) || (candleId == 31))
{
return 13;
}
return 0;
}
private void manageScreenMsg(CavernOfThePirateCaptainWorld world, NpcStringId stringId)
{
for (L2PcInstance players : world.playersInside)
{
if ((players != null) && (players.getInstanceId() == world.getInstanceId()))
{
showOnScreenMsg(players, stringId, 5, 6000);
}
}
}
private L2Attackable spawnNpc(int npcId, int roomId, L2PcInstance player, CavernOfThePirateCaptainWorld world)
{
if ((player != null) && (npcId != ZAKEN_60) && (npcId != ZAKEN_83))
{
final L2Attackable mob = (L2Attackable) addSpawn(npcId, ROOM_DATA[roomId - 1][0] + getRandom(350), ROOM_DATA[roomId - 1][1] + getRandom(350), ROOM_DATA[roomId - 1][2], 0, false, 0, false, world.getInstanceId());
addAttackDesire(mob, player);
return mob;
}
return (L2Attackable) addSpawn(npcId, ROOM_DATA[roomId - 1][0], ROOM_DATA[roomId - 1][1], ROOM_DATA[roomId - 1][2], 0, false, 0, false, world.getInstanceId());
}
private void manageNpcSpawn(CavernOfThePirateCaptainWorld world)
{
final List<L2Npc> candles = new ArrayList<>();
world._zakenRoom = getRandom(1, 15);
for (int i = 0; i < 36; i++)
{
final L2Npc candle = addSpawn(CANDLE, CANDLE_LOC[i], false, 0, false, world.getInstanceId());
candle.getVariables().set("candleId", i + 1);
candles.add(candle);
}
for (int i = 3; i < 7; i++)
{
candles.get(ROOM_DATA[world._zakenRoom - 1][i] - 1).getVariables().set("isBlue", 1);
}
world._zaken = spawnNpc(world._is83 ? ZAKEN_83 : ZAKEN_60, world._zakenRoom, null, world);
world._zaken.setInvisible(true);
world._zaken.setIsParalyzed(true);
}
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.CavernOfThePirateCaptain;
import java.util.ArrayList;
import java.util.List;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import instances.AbstractInstance;
/**
* Cavern Of The Pirate Captain (Day Dream) instance Zone.
* @author St3eT
*/
public final class CavernOfThePirateCaptain extends AbstractInstance
{
// NPCs
private static final int PATHFINDER = 32713; // Pathfinder Worker
private static final int ZAKEN_60 = 29176; // Zaken
private static final int ZAKEN_83 = 29181; // Zaken
private static final int CANDLE = 32705; // Zaken's Candle
// Items
private static final int VORPAL_RING = 15763; // Sealed Vorpal Ring
private static final int VORPAL_EARRING = 15764; // Sealed Vorpal Earring
// Reward - Zaken lvl 83 @formatter:off
private static final int[][] VORPAL_JEWELS =
{
// Time, jewel id, chance
{300000, VORPAL_RING, 50}, // 5 minutes
{600000, VORPAL_EARRING, 30}, // 10 minutes
{900000, VORPAL_RING, 25}, // 15 minutes
};
// Locations @formatter:on
private static final Location[] CANDLE_LOC =
{
// Floor 1
new Location(53313, 220133, -3498),
new Location(53313, 218079, -3498),
new Location(54240, 221045, -3498),
new Location(54325, 219095, -3498),
new Location(54240, 217155, -3498),
new Location(55257, 220028, -3498),
new Location(55257, 218172, -3498),
new Location(56280, 221045, -3498),
new Location(56195, 219095, -3498),
new Location(56280, 217155, -3498),
new Location(57215, 220133, -3498),
new Location(57215, 218079, -3498),
// Floor 2
new Location(53313, 220133, -3226),
new Location(53313, 218079, -3226),
new Location(54240, 221045, -3226),
new Location(54325, 219095, -3226),
new Location(54240, 217155, -3226),
new Location(55257, 220028, -3226),
new Location(55257, 218172, -3226),
new Location(56280, 221045, -3226),
new Location(56195, 219095, -3226),
new Location(56280, 217155, -3226),
new Location(57215, 220133, -3226),
new Location(57215, 218079, -3226),
// Floor 3
new Location(53313, 220133, -2954),
new Location(53313, 218079, -2954),
new Location(54240, 221045, -2954),
new Location(54325, 219095, -2954),
new Location(54240, 217155, -2954),
new Location(55257, 220028, -2954),
new Location(55257, 218172, -2954),
new Location(56280, 221045, -2954),
new Location(56195, 219095, -2954),
new Location(56280, 217155, -2954),
new Location(57215, 220133, -2954),
new Location(57215, 218079, -2954),
};
// Misc
private static final int TEMPLATE_ID_60 = 133;
private static final int TEMPLATE_ID_83 = 135;
//@formatter:off
private static final int[][] ROOM_DATA =
{
// Floor 1
{54240, 220133, -3498, 1, 3, 4, 6},
{54240, 218073, -3498, 2, 5, 4, 7},
{55265, 219095, -3498, 4, 9, 6, 7},
{56289, 220133, -3498, 8, 11, 6, 9},
{56289, 218073, -3498, 10, 12, 7, 9},
// Floor 2
{54240, 220133, -3226, 13, 15, 16, 18},
{54240, 218073, -3226, 14, 17, 16, 19},
{55265, 219095, -3226, 21, 16, 19, 18},
{56289, 220133, -3226, 20, 23, 21, 18},
{56289, 218073, -3226, 22, 24, 19, 21},
// Floor 3
{54240, 220133, -2954, 25, 27, 28, 30},
{54240, 218073, -2954, 26, 29, 28, 31},
{55265, 219095, -2954, 33, 28, 31, 30},
{56289, 220133, -2954, 32, 35, 30, 33},
{56289, 218073, -2954, 34, 36, 31, 33}
};
//@formatter:on
public CavernOfThePirateCaptain()
{
addStartNpc(PATHFINDER);
addTalkId(PATHFINDER);
addKillId(ZAKEN_60, ZAKEN_83);
addFirstTalkId(CANDLE);
addInstanceCreatedId(TEMPLATE_ID_60, TEMPLATE_ID_83);
addInstanceEnterId(TEMPLATE_ID_60, TEMPLATE_ID_83);
addInstanceLeaveId(TEMPLATE_ID_60, TEMPLATE_ID_83);
}
@Override
public void onInstanceCreated(Instance instance, L2PcInstance player)
{
final List<L2Npc> candles = new ArrayList<>();
final int zakenRoom = getRandom(1, 15);
for (int i = 0; i < 36; i++)
{
final L2Npc candle = addSpawn(CANDLE, CANDLE_LOC[i], false, 0, false, instance.getId());
candle.getVariables().set("candleId", i + 1);
candles.add(candle);
}
for (int i = 3; i < 7; i++)
{
candles.get(ROOM_DATA[zakenRoom - 1][i] - 1).getVariables().set("isBlue", 1);
}
final L2Npc zaken = spawnNpc(instance.getTemplateParameters().getInt("Zaken"), zakenRoom, null, instance);
zaken.setInvisible(true);
zaken.setBlockActions(true);
instance.setParameter("zakenRoom", zakenRoom);
instance.setParameter("zaken", zaken);
}
@Override
public void onInstanceEnter(L2PcInstance player, Instance instance)
{
final int startTime = (int) (instance.getElapsedTime() / 1000);
final int endTime = (int) (instance.getRemainingTime() / 1000);
player.sendPacket(new ExSendUIEvent(player, false, true, startTime, endTime, NpcStringId.ELAPSED_TIME));
}
@Override
public void onInstanceLeave(L2PcInstance player, Instance instance)
{
player.sendPacket(new ExSendUIEvent(player, true, true, 0, 0, NpcStringId.ELAPSED_TIME));
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("enter60"))
{
enterInstance(player, npc, TEMPLATE_ID_60);
}
else if (event.equals("enter83"))
{
enterInstance(player, npc, TEMPLATE_ID_83);
}
else
{
final Instance world = npc.getInstanceWorld();
if (world != null)
{
final StatsSet templParams = world.getTemplateParameters();
final StatsSet params = world.getParameters();
switch (event)
{
case "BURN_BLUE":
{
if (npc.hasDisplayEffect(0))
{
npc.setDisplayEffect(1); // Burning
startQuestTimer("BURN_BLUE2", 3000, npc, player);
if (params.getInt("blueFounded") == 4)
{
startQuestTimer("SHOW_ZAKEN", 5000, npc, player);
}
}
break;
}
case "BURN_BLUE2":
{
if (npc.hasDisplayEffect(1)) // Burning
{
npc.setDisplayEffect(3); // Blue glow
}
break;
}
case "BURN_RED":
{
if (npc.hasDisplayEffect(0))
{
npc.setDisplayEffect(1); // Burning
startQuestTimer("BURN_RED2", 3000, npc, player);
}
break;
}
case "BURN_RED2":
{
if (npc.hasDisplayEffect(1)) // Burning
{
final int room = getRoomByCandle(npc);
npc.setDisplayEffect(2); // Red glow
showOnScreenMsg(world, NpcStringId.THE_CANDLES_CAN_LEAD_YOU_TO_ZAKEN_DESTROY_HIM, ExShowScreenMessage.MIDDLE_CENTER, 6000);
spawnNpc(templParams.getInt("DollBlader"), room, player, world);
spawnNpc(templParams.getInt("ValeMaster"), room, player, world);
spawnNpc(templParams.getInt("PiratesZombie"), room, player, world);
spawnNpc(templParams.getInt("PiratesZombieCaptain"), room, player, world);
}
break;
}
case "SHOW_ZAKEN":
{
if (world.getTemplateId() == ZAKEN_83)
{
showOnScreenMsg(world, NpcStringId.WHO_DARES_AWAKEN_THE_MIGHTY_ZAKEN, ExShowScreenMessage.MIDDLE_CENTER, 6000);
}
final int zakenRoom = params.getInt("zakenRoom");
final L2Npc zaken = params.getObject("zaken", L2Npc.class);
zaken.setInvisible(false);
zaken.setBlockActions(false);
spawnNpc(templParams.getInt("DollBlader"), zakenRoom, player, world);
spawnNpc(templParams.getInt("PiratesZombie"), zakenRoom, player, world);
spawnNpc(templParams.getInt("PiratesZombieCaptain"), zakenRoom, player, world);
break;
}
}
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
final Instance world = npc.getInstanceWorld();
if (world != null)
{
if (npc.getId() == ZAKEN_83)
{
final long time = world.getElapsedTime();
for (L2PcInstance playersInside : world.getPlayersInsideRadius(npc, 1500))
{
for (int[] reward : VORPAL_JEWELS)
{
if (time <= reward[0])
{
if (getRandom(100) < reward[2])
{
giveItems(playersInside, reward[1], 1);
}
break;
}
}
}
}
world.finishInstance();
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
final Instance world = npc.getInstanceWorld();
if ((world != null) && npc.isScriptValue(0))
{
npc.setScriptValue(1);
if (npc.getVariables().getInt("isBlue", 0) == 1)
{
final int blueCandles = world.getParameters().getInt("blueFounded", 0);
world.setParameter("blueFounded", blueCandles + 1);
startQuestTimer("BURN_BLUE", 500, npc, player);
}
else
{
startQuestTimer("BURN_RED", 500, npc, player);
}
}
return null;
}
private int getRoomByCandle(L2Npc npc)
{
final int candleId = npc.getVariables().getInt("candleId", 0);
for (int i = 0; i < 15; i++)
{
if ((ROOM_DATA[i][3] == candleId) || (ROOM_DATA[i][4] == candleId))
{
return i + 1;
}
}
if ((candleId == 6) || (candleId == 7))
{
return 3;
}
else if ((candleId == 18) || (candleId == 19))
{
return 8;
}
else if ((candleId == 30) || (candleId == 31))
{
return 13;
}
return 0;
}
private L2Npc spawnNpc(int npcId, int roomId, L2PcInstance player, Instance world)
{
if ((player != null) && (npcId != ZAKEN_60) && (npcId != ZAKEN_83))
{
final L2Npc mob = addSpawn(npcId, ROOM_DATA[roomId - 1][0] + getRandom(350), ROOM_DATA[roomId - 1][1] + getRandom(350), ROOM_DATA[roomId - 1][2], 0, false, 0, false, world.getId());
addAttackPlayerDesire(mob, player);
return mob;
}
return addSpawn(npcId, ROOM_DATA[roomId - 1][0], ROOM_DATA[roomId - 1][1], ROOM_DATA[roomId - 1][2], 0, false, 0, false, world.getId());
}
public static void main(String[] args)
{
new CavernOfThePirateCaptain();
}
}

View File

@@ -1,621 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.ChambersOfDelusion;
import java.util.Calendar;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2Party;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Instance;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.util.Util;
import instances.AbstractInstance;
/**
* Chambers of Delusion superclass.
* @author GKR
*/
abstract class Chamber extends AbstractInstance
{
private class CDWorld extends InstanceWorld
{
int currentRoom;
final L2Party partyInside;
final ScheduledFuture<?> _banishTask;
private ScheduledFuture<?> _roomChangeTask;
CDWorld(L2Party party)
{
currentRoom = 0;
partyInside = party;
_banishTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new BanishTask(), 60000, 60000);
}
L2Party getPartyInside()
{
return partyInside;
}
void scheduleRoomChange(boolean bossRoom)
{
final Instance inst = InstanceManager.getInstance().getInstance(getInstanceId());
final long nextInterval = bossRoom ? 60000L : (ROOM_CHANGE_INTERVAL + getRandom(ROOM_CHANGE_RANDOM_TIME)) * 1000L;
// Schedule next room change only if remaining time is enough
if ((inst.getInstanceEndTime() - System.currentTimeMillis()) > nextInterval)
{
_roomChangeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ChangeRoomTask(), nextInterval - 5000);
}
}
void stopBanishTask()
{
_banishTask.cancel(true);
}
void stopRoomChangeTask()
{
_roomChangeTask.cancel(true);
}
class BanishTask implements Runnable
{
@Override
public void run()
{
final Instance inst = InstanceManager.getInstance().getInstance(getInstanceId());
if ((inst == null) || ((inst.getInstanceEndTime() - System.currentTimeMillis()) < 60000))
{
_banishTask.cancel(false);
}
else
{
for (int objId : inst.getPlayers())
{
final L2PcInstance pl = L2World.getInstance().getPlayer(objId);
if ((pl != null) && pl.isOnline() && ((partyInside == null) || !pl.isInParty() || (partyInside != pl.getParty())))
{
exitInstance(pl);
}
}
}
}
}
class ChangeRoomTask implements Runnable
{
@Override
public void run()
{
try
{
earthQuake(CDWorld.this);
Thread.sleep(5000);
changeRoom(CDWorld.this);
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + " ChangeRoomTask exception : " + e.getMessage(), e);
}
}
}
}
// Items
private static final int ENRIA = 4042;
private static final int ASOFE = 4043;
private static final int THONS = 4044;
private static final int LEONARD = 9628;
private static final int DELUSION_MARK = 15311;
// NPCs
private final int ENTRANCE_GATEKEEPER;
private final int ROOM_GATEKEEPER_FIRST;
private final int ROOM_GATEKEEPER_LAST;
private final int AENKINEL;
private final int BOX;
// Skills
private static final SkillHolder SUCCESS_SKILL = new SkillHolder(5758, 1);
private static final SkillHolder FAIL_SKILL = new SkillHolder(5376, 4);
private static final int ROOM_CHANGE_INTERVAL = 480; // 8 min
private static final int ROOM_CHANGE_RANDOM_TIME = 120; // 2 min
// Instance restart time
private static final int RESET_HOUR = 6;
private static final int RESET_MIN = 30;
// Following values vary between scripts
private final int INSTANCEID;
private final String INSTANCE_TEMPLATE;
protected Location[] ROOM_ENTER_POINTS;
// Misc
private static final String RETURN = Chamber.class.getSimpleName() + "_return";
protected Chamber(String name, String descr, int instanceId, String instanceTemplateName, int entranceGKId, int roomGKFirstId, int roomGKLastId, int aenkinelId, int boxId)
{
super(name, descr);
INSTANCEID = instanceId;
INSTANCE_TEMPLATE = instanceTemplateName;
ENTRANCE_GATEKEEPER = entranceGKId;
ROOM_GATEKEEPER_FIRST = roomGKFirstId;
ROOM_GATEKEEPER_LAST = roomGKLastId;
AENKINEL = aenkinelId;
BOX = boxId;
addStartNpc(ENTRANCE_GATEKEEPER);
addTalkId(ENTRANCE_GATEKEEPER);
for (int i = ROOM_GATEKEEPER_FIRST; i <= ROOM_GATEKEEPER_LAST; i++)
{
addStartNpc(i);
addTalkId(i);
}
addKillId(AENKINEL);
addAttackId(BOX);
addSpellFinishedId(BOX);
addEventReceivedId(BOX);
}
private boolean isBigChamber()
{
return (INSTANCEID == 131) || (INSTANCEID == 132);
}
private boolean isBossRoom(CDWorld world)
{
return world.currentRoom == (ROOM_ENTER_POINTS.length - 1);
}
@Override
protected boolean checkConditions(L2PcInstance player)
{
final L2Party party = player.getParty();
if (party == null)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_NOT_CURRENTLY_IN_A_PARTY_SO_YOU_CANNOT_ENTER));
return false;
}
if (party.getLeader() != player)
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ONLY_A_PARTY_LEADER_CAN_MAKE_THE_REQUEST_TO_ENTER));
return false;
}
for (L2PcInstance partyMember : party.getMembers())
{
if (partyMember.getLevel() < 80)
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_S_LEVEL_DOES_NOT_CORRESPOND_TO_THE_REQUIREMENTS_FOR_ENTRY);
sm.addPcName(partyMember);
party.broadcastPacket(sm);
return false;
}
if (!Util.checkIfInRange(1000, player, partyMember, true))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_A_LOCATION_WHICH_CANNOT_BE_ENTERED_THEREFORE_IT_CANNOT_BE_PROCESSED);
sm.addPcName(partyMember);
party.broadcastPacket(sm);
return false;
}
if (isBigChamber() && (System.currentTimeMillis() < InstanceManager.getInstance().getInstanceTime(partyMember.getObjectId(), INSTANCEID)))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_MAY_NOT_RE_ENTER_YET);
sm.addPcName(partyMember);
party.broadcastPacket(sm);
return false;
}
}
return true;
}
private void markRestriction(InstanceWorld world)
{
if (world instanceof CDWorld)
{
final Calendar reenter = Calendar.getInstance();
final Calendar now = Calendar.getInstance();
reenter.set(Calendar.MINUTE, RESET_MIN);
reenter.set(Calendar.HOUR_OF_DAY, RESET_HOUR);
if (reenter.before(now))
{
reenter.add(Calendar.DAY_OF_WEEK, 1);
}
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.INSTANT_ZONE_S1_S_ENTRY_HAS_BEEN_RESTRICTED_YOU_CAN_CHECK_THE_NEXT_POSSIBLE_ENTRY_TIME_BY_USING_THE_COMMAND_INSTANCEZONE);
sm.addString(InstanceManager.getInstance().getInstanceIdName(world.getTemplateId()));
// set instance reenter time for all allowed players
for (int objectId : world.getAllowed())
{
final L2PcInstance player = L2World.getInstance().getPlayer(objectId);
if ((player != null) && player.isOnline())
{
InstanceManager.getInstance().setInstanceTime(objectId, world.getTemplateId(), reenter.getTimeInMillis());
player.sendPacket(sm);
}
}
}
}
void changeRoom(CDWorld world)
{
final L2Party party = world.getPartyInside();
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
if ((party == null) || (inst == null))
{
return;
}
int newRoom = world.currentRoom;
// Do nothing, if there are raid room of Square or Tower Chamber
if (isBigChamber() && isBossRoom(world))
{
return;
}
// Teleport to raid room 10 min or lesser before instance end time for Tower and Square Chambers
else if (isBigChamber() && ((inst.getInstanceEndTime() - System.currentTimeMillis()) < 600000))
{
newRoom = ROOM_ENTER_POINTS.length - 1;
}
// 10% chance for teleport to raid room if not here already for Northern, Southern, Western and Eastern Chambers
else if (!isBigChamber() && !isBossRoom(world) && (getRandom(100) < 10))
{
newRoom = ROOM_ENTER_POINTS.length - 1;
}
else
{
while (newRoom == world.currentRoom) // otherwise teleport to another room, except current
{
newRoom = getRandom(ROOM_ENTER_POINTS.length - 1);
}
}
for (L2PcInstance partyMember : party.getMembers())
{
if (world.getInstanceId() == partyMember.getInstanceId())
{
partyMember.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
teleportPlayer(partyMember, ROOM_ENTER_POINTS[newRoom], world.getInstanceId());
}
}
world.currentRoom = newRoom;
// Do not schedule room change for Square and Tower Chambers, if raid room is reached
if (isBigChamber() && isBossRoom(world))
{
inst.setDuration((int) ((inst.getInstanceEndTime() - System.currentTimeMillis()) + 1200000)); // Add 20 min to instance time if raid room is reached
for (L2Npc npc : inst.getNpcs())
{
if (npc.getId() == ROOM_GATEKEEPER_LAST)
{
npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), NpcStringId.MINUTES_ARE_ADDED_TO_THE_REMAINING_TIME_IN_THE_INSTANT_ZONE));
}
}
}
else
{
world.scheduleRoomChange(false);
}
}
private void enter(CDWorld world)
{
final L2Party party = world.getPartyInside();
if (party == null)
{
return;
}
for (L2PcInstance partyMember : party.getMembers())
{
if (hasQuestItems(partyMember, DELUSION_MARK))
{
takeItems(partyMember, DELUSION_MARK, -1);
}
if (party.isLeader(partyMember))
{
giveItems(partyMember, DELUSION_MARK, 1);
}
// Save location for teleport back into main hall
partyMember.getVariables().set(RETURN, Integer.toString(partyMember.getX()) + ";" + Integer.toString(partyMember.getY()) + ";" + Integer.toString(partyMember.getZ()));
partyMember.setInstanceId(world.getInstanceId());
world.addAllowed(partyMember.getObjectId());
}
changeRoom(world);
}
void earthQuake(CDWorld world)
{
final L2Party party = world.getPartyInside();
if (party == null)
{
return;
}
for (L2PcInstance partyMember : party.getMembers())
{
if (world.getInstanceId() == partyMember.getInstanceId())
{
partyMember.sendPacket(new Earthquake(partyMember.getX(), partyMember.getY(), partyMember.getZ(), 20, 10));
}
}
}
@Override
public void onEnterInstance(L2PcInstance player, InstanceWorld world, boolean firstEntrance)
{
if (firstEntrance)
{
enter((CDWorld) world);
}
else
{
teleportPlayer(player, ROOM_ENTER_POINTS[((CDWorld) world).currentRoom], world.getInstanceId());
}
}
void exitInstance(L2PcInstance player)
{
if ((player == null) || !player.isOnline() || (player.getInstanceId() == 0))
{
return;
}
final Instance inst = InstanceManager.getInstance().getInstance(player.getInstanceId());
final Location ret = inst.getExitLoc();
final String return_point = player.getVariables().getString(RETURN, null);
if (return_point != null)
{
final String[] coords = return_point.split(";");
if (coords.length == 3)
{
try
{
ret.setLocation(new Location(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(coords[2])));
}
catch (Exception e)
{
}
}
}
teleportPlayer(player, ret, 0);
final InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
if (world != null)
{
world.removeAllowed(player.getObjectId());
}
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = "";
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if ((player != null) && (tmpworld != null) && (tmpworld instanceof CDWorld) && (npc.getId() >= ROOM_GATEKEEPER_FIRST) && (npc.getId() <= ROOM_GATEKEEPER_LAST))
{
final CDWorld world = (CDWorld) tmpworld;
// Change room from dialog
if (event.equals("next_room"))
{
if (player.getParty() == null)
{
htmltext = getHtm(player.getHtmlPrefix(), "scripts/instances/ChambersOfDelusion/no_party.html");
}
else if (player.getParty().getLeaderObjectId() != player.getObjectId())
{
htmltext = getHtm(player.getHtmlPrefix(), "scripts/instances/ChambersOfDelusion/no_leader.html");
}
else if (hasQuestItems(player, DELUSION_MARK))
{
takeItems(player, DELUSION_MARK, 1);
world.stopRoomChangeTask();
changeRoom(world);
}
else
{
htmltext = getHtm(player.getHtmlPrefix(), "scripts/instances/ChambersOfDelusion/no_item.html");
}
}
else if (event.equals("go_out"))
{
if (player.getParty() == null)
{
htmltext = getHtm(player.getHtmlPrefix(), "scripts/instances/ChambersOfDelusion/no_party.html");
}
else if (player.getParty().getLeaderObjectId() != player.getObjectId())
{
htmltext = getHtm(player.getHtmlPrefix(), "scripts/instances/ChambersOfDelusion/no_leader.html");
}
else
{
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
world.stopRoomChangeTask();
world.stopBanishTask();
for (L2PcInstance partyMember : player.getParty().getMembers())
{
exitInstance(partyMember);
}
inst.setEmptyDestroyTime(0);
}
}
else if (event.equals("look_party") && (player.getParty() != null) && (player.getParty() == world.getPartyInside()))
{
teleportPlayer(player, ROOM_ENTER_POINTS[world.currentRoom], world.getInstanceId(), false);
}
}
return htmltext;
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isPet, Skill skill)
{
if (!npc.isBusy() && (npc.getCurrentHp() < (npc.getMaxHp() / 10)))
{
npc.setBusy(true);
if (getRandom(100) < 25) // 25% chance to reward
{
if (getRandom(100) < 33)
{
npc.dropItem(attacker, ENRIA, (int) (3 * Config.RATE_QUEST_DROP));
}
if (getRandom(100) < 50)
{
npc.dropItem(attacker, THONS, (int) (4 * Config.RATE_QUEST_DROP));
}
if (getRandom(100) < 50)
{
npc.dropItem(attacker, ASOFE, (int) (4 * Config.RATE_QUEST_DROP));
}
if (getRandom(100) < 16)
{
npc.dropItem(attacker, LEONARD, (int) (2 * Config.RATE_QUEST_DROP));
}
npc.broadcastEvent("SCE_LUCKY", 2000, null);
npc.doCast(SUCCESS_SKILL.getSkill());
}
else
{
npc.broadcastEvent("SCE_DREAM_FIRE_IN_THE_HOLE", 2000, null);
}
}
return super.onAttack(npc, attacker, damage, isPet, skill);
}
@Override
public String onEventReceived(String eventName, L2Npc sender, L2Npc receiver, L2Object reference)
{
switch (eventName)
{
case "SCE_LUCKY":
{
receiver.setBusy(true);
receiver.doCast(SUCCESS_SKILL.getSkill());
break;
}
case "SCE_DREAM_FIRE_IN_THE_HOLE":
{
receiver.setBusy(true);
receiver.doCast(FAIL_SKILL.getSkill());
break;
}
}
return null;
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isPet)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getPlayerWorld(player);
if (tmpworld instanceof CDWorld)
{
final CDWorld world = (CDWorld) tmpworld;
final Instance inst = InstanceManager.getInstance().getInstance(world.getInstanceId());
if (isBigChamber())
{
markRestriction(world); // Set reenter restriction
if ((inst.getInstanceEndTime() - System.currentTimeMillis()) > 300000)
{
inst.setDuration(300000); // Finish instance in 5 minutes
}
}
else
{
world.stopRoomChangeTask();
world.scheduleRoomChange(true);
}
inst.spawnGroup("boxes");
}
return super.onKill(npc, player, isPet);
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
if ((npc.getId() == BOX) && ((skill.getId() == 5376) || (skill.getId() == 5758)) && !npc.isDead())
{
npc.doDie(player);
}
return super.onSpellFinished(npc, player, skill);
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
final int npcId = npc.getId();
QuestState qs = getQuestState(player, false);
if (qs == null)
{
qs = newQuestState(player);
}
if ((npcId == ENTRANCE_GATEKEEPER) && checkConditions(player))
{
enterInstance(player, new CDWorld(player.getParty()), INSTANCE_TEMPLATE, INSTANCEID);
}
return "";
}
}

View File

@@ -0,0 +1,449 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.ChambersOfDelusion;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.stream.IntStream;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.CommonUtil;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
import instances.AbstractInstance;
/**
* Chambers of Delusion.
* @author GKR
*/
public final class ChamberOfDelusion extends AbstractInstance
{
// NPCs
private static final Map<Integer, Integer> ENTRANCE_GATEKEEPER = new HashMap<>();
private static final int[] ROOM_GATEKEEPERS = IntStream.range(32664, 32702).toArray();
private static final int[] AENKINEL =
{
25690, // East
25691, // West
25692, // South
25693, // North
25694, // Square
25695, // Tower
};
private static final int[] BOX =
{
18838, // East, West, South, North
18820, // Square
18823, // Tower
};
// Items
private static final int ENRIA = 4042;
private static final int ASOFE = 4043;
private static final int THONS = 4044;
private static final int LEONARD = 9628;
private static final int DELUSION_MARK = 15311;
// Skills
private static final SkillHolder SUCCESS_SKILL = new SkillHolder(5758, 1);
private static final SkillHolder FAIL_SKILL = new SkillHolder(5376, 4);
// Timers
private static final int ROOM_CHANGE_INTERVAL = 480; // 8 min
private static final int ROOM_CHANGE_RANDOM_TIME = 120; // 2 min
static
{
ENTRANCE_GATEKEEPER.put(32658, 127); // East
ENTRANCE_GATEKEEPER.put(32659, 128); // West
ENTRANCE_GATEKEEPER.put(32660, 129); // South
ENTRANCE_GATEKEEPER.put(32661, 130); // North
ENTRANCE_GATEKEEPER.put(32662, 131); // Square
ENTRANCE_GATEKEEPER.put(32663, 132); // Tower
}
public ChamberOfDelusion()
{
addStartNpc(ENTRANCE_GATEKEEPER.keySet());
addStartNpc(ROOM_GATEKEEPERS);
addTalkId(ENTRANCE_GATEKEEPER.keySet());
addTalkId(ROOM_GATEKEEPERS);
addKillId(AENKINEL);
addAttackId(BOX);
addSpellFinishedId(BOX);
addEventReceivedId(BOX);
addInstanceCreatedId(ENTRANCE_GATEKEEPER.values());
addInstanceDestroyId(ENTRANCE_GATEKEEPER.values());
}
@Override
public void onInstanceCreated(Instance instance, L2PcInstance player)
{
// Choose start room
changeRoom(instance);
// Start banish task
final ScheduledFuture<?> banishTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(() ->
{
if (instance.getRemainingTime() < 60000)
{
final ScheduledFuture<?> task = instance.getParameters().getObject("banishTask", ScheduledFuture.class);
task.cancel(false);
}
else
{
for (int objId : instance.getAllowed())
{
final L2PcInstance pl = L2World.getInstance().getPlayer(objId);
if ((pl != null) && pl.isOnline() && !pl.isInParty())
{
instance.finishInstance(0);
break;
}
}
}
}, 60000, 60000);
instance.setParameter("banishTask", banishTask);
}
@Override
public void onInstanceDestroy(Instance instance)
{
// Stop room change task
stopRoomChangeTask(instance);
// Stop banish task
final ScheduledFuture<?> banish = instance.getParameters().getObject("banishTask", ScheduledFuture.class);
if (banish != null)
{
banish.cancel(true);
instance.setParameter("banishTask", null);
}
}
@Override
protected void onEnter(L2PcInstance player, Instance instance, boolean firstEnter)
{
// Teleport player to instance
super.onEnter(player, instance, firstEnter);
// Take items
if (firstEnter)
{
if (hasQuestItems(player, DELUSION_MARK))
{
takeItems(player, DELUSION_MARK, -1);
}
if (player.getParty().isLeader(player))
{
giveItems(player, DELUSION_MARK, 1);
}
}
}
@Override
protected void teleportPlayerIn(L2PcInstance player, Instance instance)
{
final int room = instance.getParameters().getInt("currentRoom");
final Location loc = instance.getEnterLocations().get(room);
player.teleToLocation(loc, instance);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = null;
final Instance world = npc.getInstanceWorld();
if ((player != null) && (world != null) && CommonUtil.contains(ROOM_GATEKEEPERS, npc.getId()))
{
switch (event)
{
case "next_room":
{
if (player.isInParty())
{
htmltext = "no_party.html";
}
else if (player.getParty().isLeader(player))
{
htmltext = "no_leader.html";
}
else if (!hasQuestItems(player, DELUSION_MARK))
{
htmltext = "no_item.html";
}
else
{
takeItems(player, DELUSION_MARK, 1);
stopRoomChangeTask(world);
changeRoom(world);
}
break;
}
case "go_out":
{
if (player.isInParty())
{
htmltext = "no_party.html";
}
else if (player.getParty().isLeader(player))
{
htmltext = "no_leader.html";
}
else
{
world.finishInstance(0);
}
break;
}
case "look_party":
{
if (player.isInParty() && world.isAllowed(player))
{
teleportPlayerIn(player, world);
}
break;
}
}
}
return htmltext;
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
final int npcId = npc.getId();
if (ENTRANCE_GATEKEEPER.containsKey(npcId))
{
enterInstance(player, npc, ENTRANCE_GATEKEEPER.get(npcId));
}
return null;
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
if (!npc.isDead() && CommonUtil.contains(BOX, npc.getId()) && ((skill.getId() == FAIL_SKILL.getSkillId()) || (skill.getId() == SUCCESS_SKILL.getSkillId())))
{
npc.doDie(player);
}
return super.onSpellFinished(npc, player, skill);
}
@Override
public String onEventReceived(String eventName, L2Npc sender, L2Npc receiver, L2Object reference)
{
switch (eventName)
{
case "SCE_LUCKY":
receiver.setBusy(true);
receiver.doCast(SUCCESS_SKILL.getSkill());
break;
case "SCE_DREAM_FIRE_IN_THE_HOLE":
receiver.setBusy(true);
receiver.doCast(FAIL_SKILL.getSkill());
break;
}
return null;
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isPet, Skill skill)
{
if (!npc.isBusy() && (npc.getCurrentHp() < (npc.getMaxHp() / 10)))
{
npc.setBusy(true);
if (getRandom(100) < 25) // 25% chance to reward
{
if (getRandom(100) < 33)
{
npc.dropItem(attacker, ENRIA, (int) (3 * Config.RATE_QUEST_DROP));
}
if (getRandom(100) < 50)
{
npc.dropItem(attacker, THONS, (int) (4 * Config.RATE_QUEST_DROP));
}
if (getRandom(100) < 50)
{
npc.dropItem(attacker, ASOFE, (int) (4 * Config.RATE_QUEST_DROP));
}
if (getRandom(100) < 16)
{
npc.dropItem(attacker, LEONARD, (int) (2 * Config.RATE_QUEST_DROP));
}
npc.broadcastEvent("SCE_LUCKY", 2000, null);
npc.doCast(SUCCESS_SKILL.getSkill());
}
else
{
npc.broadcastEvent("SCE_DREAM_FIRE_IN_THE_HOLE", 2000, null);
}
}
return super.onAttack(npc, attacker, damage, isPet, skill);
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isPet)
{
final Instance world = player.getInstanceWorld();
if (world != null)
{
if (isBigChamber(world))
{
world.setReenterTime();
if (world.getRemainingTime() > (Config.INSTANCE_FINISH_TIME * 60000))
{
world.finishInstance();
}
}
else
{
stopRoomChangeTask(world);
scheduleRoomChange(world, true);
}
world.spawnGroup("boxes");
}
return super.onKill(npc, player, isPet);
}
private boolean isBigChamber(Instance world)
{
return world.getTemplateParameters().getBoolean("isBigRoom");
}
private boolean isBossRoom(Instance world, int room)
{
return room == (world.getEnterLocations().size() - 1);
}
protected void changeRoom(Instance world)
{
final StatsSet params = world.getParameters();
final List<Location> locations = world.getEnterLocations();
int newRoom = params.getInt("currentRoom", 0);
if (isBigChamber(world))
{
// Do nothing, if there are raid room of Sqare or Tower Chamber
if (isBossRoom(world, newRoom))
{
return;
}
// Teleport to raid room 10 min or lesser before instance end time for Tower and Square Chambers
else if (world.getRemainingTime() < 600000)
{
newRoom = locations.size() - 1;
}
}
// 10% chance for teleport to raid room if not here already for Northern, Southern, Western and Eastern Chambers
else if (!isBossRoom(world, newRoom) && (getRandom(100) < 10))
{
newRoom = locations.size() - 1;
}
else
{
// otherwise teleport to another room, except current
while (newRoom == params.getInt("currentRoom", 0))
{
newRoom = getRandom(locations.size() - 1);
}
}
world.setParameter("currentRoom", newRoom);
// Teleport players into new room
world.getPlayers().forEach(p -> teleportPlayerIn(p, world));
// Do not schedule room change for Square and Tower Chambers, if raid room is reached
if (isBigChamber(world) && isBossRoom(world, newRoom))
{
// Add 20 min to instance time if raid room is reached
world.setDuration((int) (TimeUnit.MILLISECONDS.toMinutes(world.getRemainingTime() + 1200000)));
// Broadcast instance duration change (NPC message)
final int raidGatekeeper = world.getTemplateParameters().getInt("raidGatekeeper");
final L2Npc gatekeeper = world.getNpc(raidGatekeeper);
if (gatekeeper != null)
{
gatekeeper.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.MINUTES_ARE_ADDED_TO_THE_REMAINING_TIME_IN_THE_INSTANT_ZONE);
}
}
else
{
scheduleRoomChange(world, false);
}
}
protected void scheduleRoomChange(Instance world, boolean bossRoom)
{
// Schedule next room change only if remaining time is enough
final long nextInterval = (bossRoom) ? 60000L : (ROOM_CHANGE_INTERVAL + getRandom(ROOM_CHANGE_RANDOM_TIME)) * 1000L;
if (world.getRemainingTime() > nextInterval)
{
final ScheduledFuture<?> roomChangeTask = ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
try
{
// Send earthquake packet
for (L2PcInstance player : world.getPlayers())
{
player.sendPacket(new Earthquake(player, 20, 10));
}
// Wait for a while
Thread.sleep(5000);
// Change room
changeRoom(world);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error occured in room change task: ", e);
}
}, nextInterval - 5000);
world.setParameter("roomChangeTask", roomChangeTask);
}
}
protected void stopRoomChangeTask(Instance world)
{
final ScheduledFuture<?> task = world.getParameters().getObject("roomChangeTask", ScheduledFuture.class);
if (task != null)
{
task.cancel(true);
world.setParameter("roomChangeTask", null);
}
}
public static void main(String[] args)
{
new ChamberOfDelusion();
}
}

View File

@@ -1,51 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.ChambersOfDelusion;
import com.l2jmobius.gameserver.model.Location;
/**
* Chamber of Delusion East.
* @author GKR
*/
public final class ChamberOfDelusionEast extends Chamber
{
// NPCs
private static final int ENTRANCE_GATEKEEPER = 32658;
private static final int ROOM_GATEKEEPER_FIRST = 32664;
private static final int ROOM_GATEKEEPER_LAST = 32668;
private static final int AENKINEL = 25690;
private static final int BOX = 18838;
// Misc
private static final Location[] ENTER_POINTS = new Location[]
{
new Location(-122368, -218972, -6720),
new Location(-122352, -218044, -6720),
new Location(-122368, -220220, -6720),
new Location(-121440, -218444, -6720),
new Location(-121424, -220124, -6720), // Raid room
};
private static final int INSTANCEID = 127;
private static final String INSTANCE_TEMPLATE = "ChamberOfDelusionEast.xml";
public ChamberOfDelusionEast()
{
super(ChamberOfDelusionEast.class.getSimpleName(), "instances", INSTANCEID, INSTANCE_TEMPLATE, ENTRANCE_GATEKEEPER, ROOM_GATEKEEPER_FIRST, ROOM_GATEKEEPER_LAST, AENKINEL, BOX);
ROOM_ENTER_POINTS = ENTER_POINTS;
}
}

View File

@@ -1,51 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.ChambersOfDelusion;
import com.l2jmobius.gameserver.model.Location;
/**
* Chamber of Delusion North.
* @author GKR
*/
public final class ChamberOfDelusionNorth extends Chamber
{
// NPC's
private static final int ENTRANCE_GATEKEEPER = 32661;
private static final int ROOM_GATEKEEPER_FIRST = 32679;
private static final int ROOM_GATEKEEPER_LAST = 32683;
private static final int AENKINEL = 25693;
private static final int BOX = 18838;
// Misc
private static final Location[] ENTER_POINTS = new Location[]
{
new Location(-108976, -207772, -6720),
new Location(-108976, -206972, -6720),
new Location(-108960, -209164, -6720),
new Location(-108048, -207340, -6720),
new Location(-108048, -209020, -6720), // Raid room
};
private static final int INSTANCEID = 130; // this is the client number
private static final String INSTANCE_TEMPLATE = "ChamberOfDelusionNorth.xml";
public ChamberOfDelusionNorth()
{
super(ChamberOfDelusionNorth.class.getSimpleName(), "instances", INSTANCEID, INSTANCE_TEMPLATE, ENTRANCE_GATEKEEPER, ROOM_GATEKEEPER_FIRST, ROOM_GATEKEEPER_LAST, AENKINEL, BOX);
ROOM_ENTER_POINTS = ENTER_POINTS;
}
}

View File

@@ -1,51 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.ChambersOfDelusion;
import com.l2jmobius.gameserver.model.Location;
/**
* Chamber of Delusion South.
* @author GKR
*/
public final class ChamberOfDelusionSouth extends Chamber
{
// NPC's
private static final int ENTRANCE_GATEKEEPER = 32660;
private static final int ROOM_GATEKEEPER_FIRST = 32674;
private static final int ROOM_GATEKEEPER_LAST = 32678;
private static final int AENKINEL = 25692;
private static final int BOX = 18838;
// Misc
private static final Location[] ENTER_POINTS = new Location[]
{
new Location(-122368, -207820, -6720),
new Location(-122368, -206940, -6720),
new Location(-122368, -209116, -6720),
new Location(-121456, -207356, -6720),
new Location(-121440, -209004, -6720), // Raid room
};
private static final int INSTANCEID = 129; // this is the client number
private static final String INSTANCE_TEMPLATE = "ChamberOfDelusionSouth.xml";
public ChamberOfDelusionSouth()
{
super(ChamberOfDelusionSouth.class.getSimpleName(), "instances", INSTANCEID, INSTANCE_TEMPLATE, ENTRANCE_GATEKEEPER, ROOM_GATEKEEPER_FIRST, ROOM_GATEKEEPER_LAST, AENKINEL, BOX);
ROOM_ENTER_POINTS = ENTER_POINTS;
}
}

View File

@@ -1,55 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.ChambersOfDelusion;
import com.l2jmobius.gameserver.model.Location;
/**
* Chamber of Delusion Square.
* @author GKR
*/
public final class ChamberOfDelusionSquare extends Chamber
{
// NPC's
private static final int ENTRANCE_GATEKEEPER = 32662;
private static final int ROOM_GATEKEEPER_FIRST = 32684;
private static final int ROOM_GATEKEEPER_LAST = 32692;
private static final int AENKINEL = 25694;
private static final int BOX = 18820;
// Misc
private static final Location[] ENTER_POINTS = new Location[]
{
new Location(-122368, -153388, -6688),
new Location(-122368, -152524, -6688),
new Location(-120480, -155116, -6688),
new Location(-120480, -154236, -6688),
new Location(-121440, -151212, -6688),
new Location(-120464, -152908, -6688),
new Location(-122368, -154700, -6688),
new Location(-121440, -152908, -6688),
new Location(-121440, -154572, -6688), // Raid room
};
private static final int INSTANCEID = 131;
private static final String INSTANCE_TEMPLATE = "ChamberOfDelusionSquare.xml";
public ChamberOfDelusionSquare()
{
super(ChamberOfDelusionSquare.class.getSimpleName(), "instances", INSTANCEID, INSTANCE_TEMPLATE, ENTRANCE_GATEKEEPER, ROOM_GATEKEEPER_FIRST, ROOM_GATEKEEPER_LAST, AENKINEL, BOX);
ROOM_ENTER_POINTS = ENTER_POINTS;
}
}

View File

@@ -1,55 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.ChambersOfDelusion;
import com.l2jmobius.gameserver.model.Location;
/**
* Chamber of Delusion Tower.
* @author GKR
*/
public final class ChamberOfDelusionTower extends Chamber
{
// NPC's
private static final int ENTRANCE_GATEKEEPER = 32663;
private static final int ROOM_GATEKEEPER_FIRST = 32693;
private static final int ROOM_GATEKEEPER_LAST = 32701;
private static final int AENKINEL = 25695;
private static final int BOX = 18823;
// Misc
private static final Location[] ENTER_POINTS = new Location[]
{
new Location(-108976, -153372, -6688),
new Location(-108960, -152524, -6688),
new Location(-107088, -155052, -6688),
new Location(-107104, -154236, -6688),
new Location(-108048, -151244, -6688),
new Location(-107088, -152956, -6688),
new Location(-108992, -154604, -6688),
new Location(-108032, -152892, -6688),
new Location(-108048, -154572, -6688), // Raid room
};
private static final int INSTANCEID = 132; // this is the client number
private static final String INSTANCE_TEMPLATE = "ChamberOfDelusionTower.xml";
public ChamberOfDelusionTower()
{
super(ChamberOfDelusionTower.class.getSimpleName(), "instances", INSTANCEID, INSTANCE_TEMPLATE, ENTRANCE_GATEKEEPER, ROOM_GATEKEEPER_FIRST, ROOM_GATEKEEPER_LAST, AENKINEL, BOX);
ROOM_ENTER_POINTS = ENTER_POINTS;
}
}

View File

@@ -1,51 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.ChambersOfDelusion;
import com.l2jmobius.gameserver.model.Location;
/**
* Chamber of Delusion West.
* @author GKR
*/
public final class ChamberOfDelusionWest extends Chamber
{
// NPC's
private static final int ENTRANCE_GATEKEEPER = 32659;
private static final int ROOM_GATEKEEPER_FIRST = 32669;
private static final int ROOM_GATEKEEPER_LAST = 32673;
private static final int AENKINEL = 25691;
private static final int BOX = 18838;
// Misc
private static final Location[] ENTER_POINTS = new Location[]
{
new Location(-108960, -218892, -6720),
new Location(-108976, -218028, -6720),
new Location(-108960, -220204, -6720),
new Location(-108032, -218428, -6720),
new Location(-108032, -220140, -6720), // Raid room
};
private static final int INSTANCEID = 128; // this is the client number
private static final String INSTANCE_TEMPLATE = "ChamberOfDelusionWest.xml";
public ChamberOfDelusionWest()
{
super(ChamberOfDelusionWest.class.getSimpleName(), "instances", INSTANCEID, INSTANCE_TEMPLATE, ENTRANCE_GATEKEEPER, ROOM_GATEKEEPER_FIRST, ROOM_GATEKEEPER_LAST, AENKINEL, BOX);
ROOM_ENTER_POINTS = ENTER_POINTS;
}
}

View File

@@ -1,7 +0,0 @@
<html><body>Oracle Guide:<br>
Brilliant five-colored light shines forth from an aquamarine sphere. You hear a loud, dear voice:<br>
Welcome, you who have accomplished the test of the Oracle. Your contributions have led to the downfall of the Demon Balor.<br>
I am the last child of the Oracle, whose mission it is to escort you safely to the place where Parme is being kept. She is still under an evil influence, but the object you carry has the power to heal her.<br>
If you are ready to meet the priests of the Water Dragon, give me your hand.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CrystalCaverns TeleportParme">Go to meet Parme.</Button>
</body></html>

View File

@@ -1,4 +0,0 @@
<html><body>Oracle Guide:<br>
Baylor is dead!<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CrystalCaverns TeleportOut">Let me out!</Button>
</body></html>

View File

@@ -1,4 +0,0 @@
<html><body>[You feel a chill and hear a voice...]<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CrystalCaverns CoralGarden">Run Coral Garden.</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest CrystalCaverns EmeraldSteam">Run Emerald Square/Steam Corridor</Button>
</body></html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +0,0 @@
<html><body>Oracle Guide:<br>
I can't speak with you, while bleeding.
</body></html>

View File

@@ -1,472 +1,438 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.DisciplesNecropolisPast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
import com.l2jmobius.gameserver.util.Util;
import instances.AbstractInstance;
import quests.Q00196_SevenSignsSealOfTheEmperor.Q00196_SevenSignsSealOfTheEmperor;
/**
* Disciple's Necropolis Past instance zone.
* @author Adry_85
*/
public final class DisciplesNecropolisPast extends AbstractInstance
{
// NPCs
private static final int SEAL_DEVICE = 27384;
private static final int PROMISE_OF_MAMMON = 32585;
private static final int SHUNAIMAN = 32586;
private static final int LEON = 32587;
private static final int DISCIPLES_GATEKEEPER = 32657;
private static final int LILITH = 32715;
private static final int LILITHS_STEWARD = 32716;
private static final int LILITHS_ELITE = 32717;
private static final int ANAKIM = 32718;
private static final int ANAKIMS_GUARDIAN = 32719;
private static final int ANAKIMS_GUARD = 32720;
private static final int ANAKIMS_EXECUTOR = 32721;
private static final int LILIM_BUTCHER = 27371;
private static final int LILIM_MAGUS = 27372;
private static final int LILIM_KNIGHT_ERRANT = 27373;
private static final int SHILENS_EVIL_THOUGHTS1 = 27374;
private static final int SHILENS_EVIL_THOUGHTS2 = 27375;
private static final int LILIM_KNIGHT = 27376;
private static final int LILIM_SLAYER = 27377;
private static final int LILIM_GREAT_MAGUS = 27378;
private static final int LILIM_GUARD_KNIGHT = 27379;
// Items
private static final int SACRED_SWORD_OF_EINHASAD = 15310;
private static final int SEAL_OF_BINDING = 13846;
// Skills
private static final SkillHolder SEAL_ISOLATION = new SkillHolder(5980, 3);
private static final Map<Integer, SkillHolder> SKILLS = new HashMap<>();
static
{
SKILLS.put(32715, new SkillHolder(6187, 1)); // Presentation - Lilith Battle
SKILLS.put(32716, new SkillHolder(6188, 1)); // Presentation - Lilith's Steward Battle1
SKILLS.put(32717, new SkillHolder(6190, 1)); // Presentation - Lilith's Bodyguards Battle1
SKILLS.put(32718, new SkillHolder(6191, 1)); // Presentation - Anakim Battle
SKILLS.put(32719, new SkillHolder(6192, 1)); // Presentation - Anakim's Guardian Battle1
SKILLS.put(32720, new SkillHolder(6194, 1)); // Presentation - Anakim's Guard Battle
SKILLS.put(32721, new SkillHolder(6195, 1)); // Presentation - Anakim's Executor Battle
}
// Locations
private static final Location ENTER = new Location(-89554, 216078, -7488, 0, 0);
private static final Location EXIT = new Location(171895, -17501, -4903, 0, 0);
// NpcStringId
private static final NpcStringId[] LILITH_SHOUT =
{
NpcStringId.HOW_DARE_YOU_TRY_TO_CONTEND_AGAINST_ME_IN_STRENGTH_RIDICULOUS,
NpcStringId.ANAKIM_IN_THE_NAME_OF_GREAT_SHILEN_I_WILL_CUT_YOUR_THROAT,
NpcStringId.YOU_CANNOT_BE_THE_MATCH_OF_LILITH_I_LL_TEACH_YOU_A_LESSON
};
// Misc
private static final int TEMPLATE_ID = 112;
private static final int DOOR_1 = 17240102;
private static final int DOOR_2 = 17240104;
private static final int DOOR_3 = 17240106;
private static final int DOOR_4 = 17240108;
private static final int DOOR_5 = 17240110;
private static final int DISCIPLES_NECROPOLIS_DOOR = 17240111;
private static final Map<Integer, Location> LILITH_SPAWN = new HashMap<>();
private static final Map<Integer, Location> ANAKIM_SPAWN = new HashMap<>();
static
{
LILITH_SPAWN.put(LILITH, new Location(-83175, 217021, -7504, 49151));
LILITH_SPAWN.put(LILITHS_STEWARD, new Location(-83327, 216938, -7492, 50768));
LILITH_SPAWN.put(LILITHS_ELITE, new Location(-83003, 216909, -7492, 4827));
ANAKIM_SPAWN.put(ANAKIM, new Location(-83179, 216479, -7504, 16384));
ANAKIM_SPAWN.put(ANAKIMS_GUARDIAN, new Location(-83321, 216507, -7492, 16166));
ANAKIM_SPAWN.put(ANAKIMS_GUARD, new Location(-83086, 216519, -7495, 15910));
ANAKIM_SPAWN.put(ANAKIMS_EXECUTOR, new Location(-83031, 216604, -7492, 17071));
}
class DNPWorld extends InstanceWorld
{
final List<L2Npc> anakimGroup = new ArrayList<>();
final List<L2Npc> lilithGroup = new ArrayList<>();
int countKill = 0;
}
public DisciplesNecropolisPast()
{
super(DisciplesNecropolisPast.class.getSimpleName());
addAttackId(SEAL_DEVICE);
addFirstTalkId(SHUNAIMAN, LEON, DISCIPLES_GATEKEEPER);
addKillId(LILIM_BUTCHER, LILIM_MAGUS, LILIM_KNIGHT_ERRANT, LILIM_KNIGHT, SHILENS_EVIL_THOUGHTS1, SHILENS_EVIL_THOUGHTS2, LILIM_SLAYER, LILIM_GREAT_MAGUS, LILIM_GUARD_KNIGHT);
addAggroRangeEnterId(LILIM_BUTCHER, LILIM_MAGUS, LILIM_KNIGHT_ERRANT, LILIM_KNIGHT, SHILENS_EVIL_THOUGHTS1, SHILENS_EVIL_THOUGHTS2, LILIM_SLAYER, LILIM_GREAT_MAGUS, LILIM_GUARD_KNIGHT);
addSpawnId(SEAL_DEVICE);
addStartNpc(PROMISE_OF_MAMMON);
addTalkId(PROMISE_OF_MAMMON, SHUNAIMAN, LEON, DISCIPLES_GATEKEEPER);
}
private void spawnNPC(DNPWorld world)
{
for (Map.Entry<Integer, Location> entry : LILITH_SPAWN.entrySet())
{
final L2Npc npc = addSpawn(entry.getKey(), entry.getValue(), false, 0, false, world.getInstanceId());
world.lilithGroup.add(npc);
}
for (Map.Entry<Integer, Location> entry : ANAKIM_SPAWN.entrySet())
{
final L2Npc enpc = addSpawn(entry.getKey(), entry.getValue(), false, 0, false, world.getInstanceId());
world.anakimGroup.add(enpc);
}
}
private synchronized void checkDoors(L2Npc npc, DNPWorld world)
{
world.countKill++;
switch (world.countKill)
{
case 4:
{
openDoor(DOOR_1, world.getInstanceId());
break;
}
case 10:
{
openDoor(DOOR_2, world.getInstanceId());
break;
}
case 18:
{
openDoor(DOOR_3, world.getInstanceId());
break;
}
case 28:
{
openDoor(DOOR_4, world.getInstanceId());
break;
}
case 40:
{
openDoor(DOOR_5, world.getInstanceId());
break;
}
}
}
@Override
public void onEnterInstance(L2PcInstance player, InstanceWorld world, boolean firstEntrance)
{
if (firstEntrance)
{
spawnNPC((DNPWorld) world);
world.addAllowed(player.getObjectId());
}
teleportPlayer(player, ENTER, world.getInstanceId());
}
private void makeCast(L2Npc npc, List<L2Npc> targets)
{
npc.setTarget(targets.get(getRandom(targets.size())));
if (SKILLS.containsKey(npc.getId()))
{
npc.doCast(SKILLS.get(npc.getId()).getSkill());
}
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getPlayerWorld(player);
if (tmpworld instanceof DNPWorld)
{
final DNPWorld world = (DNPWorld) tmpworld;
switch (event)
{
case "FINISH":
{
if (getQuestItemsCount(player, SEAL_OF_BINDING) >= 4)
{
player.showQuestMovie(13);
startQuestTimer("TELEPORT", 27000, null, player);
}
break;
}
case "TELEPORT":
{
player.teleToLocation(ENTER, 0);
break;
}
case "FIGHT":
{
for (L2Npc caster : world.anakimGroup)
{
if ((caster != null) && !caster.isCastingNow())
{
makeCast(caster, world.lilithGroup);
}
if ((caster != null) && (caster.getId() == ANAKIM))
{
if (caster.isScriptValue(0))
{
caster.broadcastPacket(new NpcSay(caster.getObjectId(), ChatType.NPC_SHOUT, caster.getId(), NpcStringId.YOU_SUCH_A_FOOL_THE_VICTORY_OVER_THIS_WAR_BELONGS_TO_SHILEN));
caster.setScriptValue(1);
}
else if (getRandom(100) < 10)
{
caster.broadcastPacket(new NpcSay(caster.getObjectId(), ChatType.NPC_SHOUT, caster.getId(), LILITH_SHOUT[getRandom(3)]));
}
}
}
for (L2Npc caster : world.lilithGroup)
{
if ((caster != null) && !caster.isCastingNow())
{
makeCast(caster, world.anakimGroup);
}
if ((caster != null) && (caster.getId() == 32715))
{
if (caster.isScriptValue(0))
{
caster.broadcastPacket(new NpcSay(caster.getObjectId(), ChatType.NPC_SHOUT, caster.getId(), NpcStringId.FOR_THE_ETERNITY_OF_EINHASAD));
if (Util.checkIfInRange(2000, caster, player, true))
{
player.sendPacket(new NpcSay(caster.getObjectId(), ChatType.NPC_WHISPER, caster.getId(), NpcStringId.MY_POWER_S_WEAKENING_HURRY_AND_TURN_ON_THE_SEALING_DEVICE));
}
caster.setScriptValue(1);
}
else if (getRandom(100) < 10)
{
switch (getRandom(3))
{
case 0:
{
caster.broadcastPacket(new NpcSay(caster.getObjectId(), ChatType.NPC_SHOUT, caster.getId(), NpcStringId.DEAR_SHILLIEN_S_OFFSPRINGS_YOU_ARE_NOT_CAPABLE_OF_CONFRONTING_US));
if (Util.checkIfInRange(2000, caster, player, true))
{
player.sendPacket(new NpcSay(caster.getObjectId(), ChatType.NPC_WHISPER, caster.getId(), NpcStringId.ALL_4_SEALING_DEVICES_MUST_BE_TURNED_ON));
}
break;
}
case 1:
{
caster.broadcastPacket(new NpcSay(caster.getObjectId(), ChatType.NPC_SHOUT, caster.getId(), NpcStringId.I_LL_SHOW_YOU_THE_REAL_POWER_OF_EINHASAD));
if (Util.checkIfInRange(2000, caster, player, true))
{
player.sendPacket(new NpcSay(caster.getObjectId(), ChatType.NPC_WHISPER, caster.getId(), NpcStringId.LILITH_ATTACK_IS_GETTING_STRONGER_GO_AHEAD_AND_TURN_IT_ON));
}
break;
}
case 2:
{
caster.broadcastPacket(new NpcSay(caster.getObjectId(), ChatType.NPC_SHOUT, caster.getId(), NpcStringId.DEAR_MILITARY_FORCE_OF_LIGHT_GO_DESTROY_THE_OFFSPRINGS_OF_SHILLIEN));
if (Util.checkIfInRange(2000, caster, player, true))
{
player.sendPacket(new NpcSay(caster.getObjectId(), ChatType.NPC_WHISPER, caster.getId(), NpcStringId.DEAR_S1_GIVE_ME_MORE_STRENGTH).addStringParameter(player.getName()));
}
break;
}
}
}
}
startQuestTimer("FIGHT", 1000, null, player);
}
break;
}
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
switch (npc.getId())
{
case LILIM_BUTCHER:
case LILIM_GUARD_KNIGHT:
{
if (npc.isScriptValue(0))
{
npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), NpcStringId.THIS_PLACE_ONCE_BELONGED_TO_LORD_SHILEN));
npc.setScriptValue(1);
}
break;
}
case LILIM_MAGUS:
case LILIM_GREAT_MAGUS:
{
if (npc.isScriptValue(0))
{
npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), NpcStringId.WHO_DARES_ENTER_THIS_PLACE));
npc.setScriptValue(1);
}
break;
}
case LILIM_KNIGHT_ERRANT:
case LILIM_KNIGHT:
{
if (npc.isScriptValue(0))
{
npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), NpcStringId.THOSE_WHO_ARE_AFRAID_SHOULD_GET_AWAY_AND_THOSE_WHO_ARE_BRAVE_SHOULD_FIGHT));
npc.setScriptValue(1);
}
break;
}
case LILIM_SLAYER:
{
if (npc.isScriptValue(0))
{
npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), NpcStringId.LEAVE_NOW));
npc.setScriptValue(1);
}
break;
}
}
return super.onAggroRangeEnter(npc, player, isSummon);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getPlayerWorld(player);
if (tmpworld instanceof DNPWorld)
{
if (npc.isScriptValue(0) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.1)))
{
giveItems(player, SEAL_OF_BINDING, 1);
player.sendPacket(SystemMessageId.THE_SEALING_DEVICE_GLITTERS_AND_MOVES_ACTIVATION_COMPLETE_NORMALLY);
npc.setScriptValue(1);
startQuestTimer("FINISH", 1000, npc, player);
cancelQuestTimer("FIGHT", npc, player);
}
if (getRandom(100) < 50)
{
npc.doCast(SEAL_ISOLATION.getSkill());
}
}
return super.onAttack(npc, player, damage, isSummon);
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
return npc.getId() + ".htm";
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getPlayerWorld(player);
if (tmpworld instanceof DNPWorld)
{
checkDoors(npc, (DNPWorld) tmpworld);
}
switch (npc.getId())
{
case LILIM_MAGUS:
case LILIM_GREAT_MAGUS:
{
npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), NpcStringId.LORD_SHILEN_SOME_DAY_YOU_WILL_ACCOMPLISH_THIS_MISSION));
break;
}
case LILIM_KNIGHT_ERRANT:
case LILIM_KNIGHT:
case LILIM_GUARD_KNIGHT:
{
npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), NpcStringId.WHY_ARE_YOU_GETTING_IN_OUR_WAY));
break;
}
case LILIM_SLAYER:
{
npc.broadcastPacket(new NpcSay(npc.getObjectId(), ChatType.NPC_GENERAL, npc.getId(), NpcStringId.FOR_SHILEN));
break;
}
}
return super.onKill(npc, player, isSummon);
}
@Override
public final String onSpawn(L2Npc npc)
{
npc.setIsMortal(false);
return super.onSpawn(npc);
}
@Override
public String onTalk(L2Npc npc, L2PcInstance talker)
{
final QuestState qs = talker.getQuestState(Q00196_SevenSignsSealOfTheEmperor.class.getSimpleName());
String htmltext = getNoQuestMsg(talker);
if (qs == null)
{
return htmltext;
}
switch (npc.getId())
{
case PROMISE_OF_MAMMON:
{
if (qs.isCond(3) || qs.isCond(4))
{
enterInstance(talker, new DNPWorld(), "DisciplesNecropolisPast.xml", TEMPLATE_ID);
return "";
}
break;
}
case LEON:
{
if (qs.getCond() >= 3)
{
takeItems(talker, SACRED_SWORD_OF_EINHASAD, -1);
final InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(talker);
world.removeAllowed(talker.getObjectId());
talker.teleToLocation(EXIT, 0);
htmltext = "32587-01.html";
}
break;
}
case DISCIPLES_GATEKEEPER:
{
if (qs.getCond() >= 3)
{
final InstanceWorld tmpworld = InstanceManager.getInstance().getWorld(npc.getInstanceId());
if (tmpworld instanceof DNPWorld)
{
final DNPWorld world = (DNPWorld) tmpworld;
openDoor(DISCIPLES_NECROPOLIS_DOOR, world.getInstanceId());
talker.showQuestMovie(12);
startQuestTimer("FIGHT", 1000, null, talker);
}
}
break;
}
}
return htmltext;
}
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.DisciplesNecropolisPast;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.enums.Movie;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.model.skills.SkillCaster;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
import com.l2jmobius.gameserver.util.Util;
import instances.AbstractInstance;
import quests.Q00196_SevenSignsSealOfTheEmperor.Q00196_SevenSignsSealOfTheEmperor;
/**
* Disciple's Necropolis Past instance zone.
* @author Adry_85
*/
public final class DisciplesNecropolisPast extends AbstractInstance
{
// NPCs
private static final int SEAL_DEVICE = 27384;
private static final int PROMISE_OF_MAMMON = 32585;
private static final int SHUNAIMAN = 32586;
private static final int LEON = 32587;
private static final int DISCIPLES_GATEKEEPER = 32657;
// Monsters
private static final int LILITH = 32715;
private static final int ANAKIM = 32718;
private static final int LILIM_BUTCHER = 27371;
private static final int LILIM_MAGUS = 27372;
private static final int LILIM_KNIGHT_ERRANT = 27373;
private static final int SHILENS_EVIL_THOUGHTS1 = 27374;
private static final int SHILENS_EVIL_THOUGHTS2 = 27375;
private static final int LILIM_KNIGHT = 27376;
private static final int LILIM_SLAYER = 27377;
private static final int LILIM_GREAT_MAGUS = 27378;
private static final int LILIM_GUARD_KNIGHT = 27379;
private static final int[] ANAKIM_GROUP =
{
ANAKIM,
32719,
32720,
32721
};
private static final int[] LILITH_GROUP =
{
LILITH,
32716,
32717
};
// Items
private static final int SACRED_SWORD_OF_EINHASAD = 15310;
private static final int SEAL_OF_BINDING = 13846;
// Skills
private static final SkillHolder SEAL_ISOLATION = new SkillHolder(5980, 3);
private static final Map<Integer, SkillHolder> SKILLS = new HashMap<>();
static
{
SKILLS.put(32715, new SkillHolder(6187, 1)); // Presentation - Lilith Battle
SKILLS.put(32716, new SkillHolder(6188, 1)); // Presentation - Lilith's Steward Battle1
SKILLS.put(32717, new SkillHolder(6190, 1)); // Presentation - Lilith's Bodyguards Battle1
SKILLS.put(32718, new SkillHolder(6191, 1)); // Presentation - Anakim Battle
SKILLS.put(32719, new SkillHolder(6192, 1)); // Presentation - Anakim's Guardian Battle1
SKILLS.put(32720, new SkillHolder(6194, 1)); // Presentation - Anakim's Guard Battle
SKILLS.put(32721, new SkillHolder(6195, 1)); // Presentation - Anakim's Executor Battle
}
// Locations
private static final Location ENTER = new Location(-89554, 216078, -7488);
// NpcStringId
private static final NpcStringId[] LILITH_SHOUT =
{
NpcStringId.HOW_DARE_YOU_TRY_TO_CONTEND_AGAINST_ME_IN_STRENGTH_RIDICULOUS,
NpcStringId.ANAKIM_IN_THE_NAME_OF_GREAT_SHILEN_I_WILL_CUT_YOUR_THROAT,
NpcStringId.YOU_CANNOT_BE_THE_MATCH_OF_LILITH_I_LL_TEACH_YOU_A_LESSON
};
// Misc
private static final int TEMPLATE_ID = 112;
private static final int DOOR_1 = 17240102;
private static final int DOOR_2 = 17240104;
private static final int DOOR_3 = 17240106;
private static final int DOOR_4 = 17240108;
private static final int DOOR_5 = 17240110;
private static final int DISCIPLES_NECROPOLIS_DOOR = 17240111;
public DisciplesNecropolisPast()
{
addAttackId(SEAL_DEVICE);
addFirstTalkId(SHUNAIMAN, LEON, DISCIPLES_GATEKEEPER);
addKillId(LILIM_BUTCHER, LILIM_MAGUS, LILIM_KNIGHT_ERRANT, LILIM_KNIGHT, SHILENS_EVIL_THOUGHTS1, SHILENS_EVIL_THOUGHTS2, LILIM_SLAYER, LILIM_GREAT_MAGUS, LILIM_GUARD_KNIGHT);
addAggroRangeEnterId(LILIM_BUTCHER, LILIM_MAGUS, LILIM_KNIGHT_ERRANT, LILIM_KNIGHT, SHILENS_EVIL_THOUGHTS1, SHILENS_EVIL_THOUGHTS2, LILIM_SLAYER, LILIM_GREAT_MAGUS, LILIM_GUARD_KNIGHT);
addSpawnId(SEAL_DEVICE);
addStartNpc(PROMISE_OF_MAMMON);
addTalkId(PROMISE_OF_MAMMON, SHUNAIMAN, LEON, DISCIPLES_GATEKEEPER);
}
private void checkDoors(L2Npc npc, Instance world, int count)
{
switch (count)
{
case 4:
world.openCloseDoor(DOOR_1, true);
break;
case 10:
world.openCloseDoor(DOOR_2, true);
break;
case 18:
world.openCloseDoor(DOOR_3, true);
break;
case 28:
world.openCloseDoor(DOOR_4, true);
break;
case 40:
world.openCloseDoor(DOOR_5, true);
break;
}
}
private void makeCast(L2Npc npc, List<L2Npc> targets)
{
npc.setTarget(targets.get(getRandom(targets.size())));
if (SKILLS.containsKey(npc.getId()))
{
npc.doCast(SKILLS.get(npc.getId()).getSkill());
}
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final Instance world = player.getInstanceWorld();
if (world != null)
{
switch (event)
{
case "FINISH":
{
if (getQuestItemsCount(player, SEAL_OF_BINDING) >= 4)
{
playMovie(player, Movie.SSQ_SEALING_EMPEROR_2ND);
startQuestTimer("TELEPORT", 27000, null, player);
}
break;
}
case "TELEPORT":
{
player.teleToLocation(ENTER);
break;
}
case "FIGHT":
{
final List<L2Npc> anakimGroup = world.getNpcs(ANAKIM_GROUP);
final List<L2Npc> lilithGroup = world.getNpcs(LILITH_GROUP);
for (L2Npc caster : anakimGroup)
{
if ((caster != null) && !caster.isCastingNow(SkillCaster::isAnyNormalType))
{
makeCast(caster, lilithGroup);
}
if ((caster != null) && (caster.getId() == ANAKIM))
{
if (caster.isScriptValue(0))
{
caster.broadcastSay(ChatType.NPC_SHOUT, NpcStringId.YOU_SUCH_A_FOOL_THE_VICTORY_OVER_THIS_WAR_BELONGS_TO_SHILEN);
caster.setScriptValue(1);
}
else if (getRandom(100) < 10)
{
caster.broadcastSay(ChatType.NPC_SHOUT, LILITH_SHOUT[getRandom(3)]);
}
}
}
for (L2Npc caster : lilithGroup)
{
if ((caster != null) && !caster.isCastingNow(SkillCaster::isAnyNormalType))
{
makeCast(caster, anakimGroup);
}
if ((caster != null) && (caster.getId() == LILITH))
{
if (caster.isScriptValue(0))
{
caster.broadcastSay(ChatType.NPC_SHOUT, NpcStringId.FOR_THE_ETERNITY_OF_EINHASAD);
if (Util.checkIfInRange(2000, caster, player, true))
{
player.sendPacket(new NpcSay(caster, ChatType.NPC_WHISPER, NpcStringId.MY_POWER_S_WEAKENING_HURRY_AND_TURN_ON_THE_SEALING_DEVICE));
}
caster.setScriptValue(1);
}
else if (getRandom(100) < 10)
{
switch (getRandom(3))
{
case 0:
{
caster.broadcastSay(ChatType.NPC_SHOUT, NpcStringId.DEAR_SHILLIEN_S_OFFSPRINGS_YOU_ARE_NOT_CAPABLE_OF_CONFRONTING_US);
if (Util.checkIfInRange(2000, caster, player, true))
{
player.sendPacket(new NpcSay(caster, ChatType.NPC_WHISPER, NpcStringId.ALL_4_SEALING_DEVICES_MUST_BE_TURNED_ON));
}
break;
}
case 1:
{
caster.broadcastSay(ChatType.NPC_SHOUT, NpcStringId.I_LL_SHOW_YOU_THE_REAL_POWER_OF_EINHASAD);
if (Util.checkIfInRange(2000, caster, player, true))
{
player.sendPacket(new NpcSay(caster, ChatType.NPC_WHISPER, NpcStringId.LILITH_ATTACK_IS_GETTING_STRONGER_GO_AHEAD_AND_TURN_IT_ON));
}
break;
}
case 2:
{
caster.broadcastSay(ChatType.NPC_SHOUT, NpcStringId.DEAR_MILITARY_FORCE_OF_LIGHT_GO_DESTROY_THE_OFFSPRINGS_OF_SHILLIEN);
if (Util.checkIfInRange(2000, caster, player, true))
{
player.sendPacket(new NpcSay(caster, ChatType.NPC_WHISPER, NpcStringId.DEAR_S1_GIVE_ME_MORE_STRENGTH).addStringParameter(player.getName()));
}
break;
}
}
}
}
startQuestTimer("FIGHT", 1000, null, player);
}
break;
}
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
switch (npc.getId())
{
case LILIM_BUTCHER:
case LILIM_GUARD_KNIGHT:
{
if (npc.isScriptValue(0))
{
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.THIS_PLACE_ONCE_BELONGED_TO_LORD_SHILEN);
npc.setScriptValue(1);
}
break;
}
case LILIM_MAGUS:
case LILIM_GREAT_MAGUS:
{
if (npc.isScriptValue(0))
{
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.WHO_DARES_ENTER_THIS_PLACE);
npc.setScriptValue(1);
}
break;
}
case LILIM_KNIGHT_ERRANT:
case LILIM_KNIGHT:
{
if (npc.isScriptValue(0))
{
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.THOSE_WHO_ARE_AFRAID_SHOULD_GET_AWAY_AND_THOSE_WHO_ARE_BRAVE_SHOULD_FIGHT);
npc.setScriptValue(1);
}
break;
}
case LILIM_SLAYER:
{
if (npc.isScriptValue(0))
{
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.LEAVE_NOW);
npc.setScriptValue(1);
}
break;
}
}
return super.onAggroRangeEnter(npc, player, isSummon);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon)
{
final Instance world = player.getInstanceWorld();
if (world != null)
{
if (npc.isScriptValue(0))
{
if (npc.getCurrentHp() < (npc.getMaxHp() * 0.1))
{
giveItems(player, SEAL_OF_BINDING, 1);
player.sendPacket(SystemMessageId.THE_SEALING_DEVICE_GLITTERS_AND_MOVES_ACTIVATION_COMPLETE_NORMALLY);
npc.setScriptValue(1);
startQuestTimer("FINISH", 1000, npc, player);
cancelQuestTimer("FIGHT", npc, player);
}
}
if (getRandom(100) < 50)
{
npc.doCast(SEAL_ISOLATION.getSkill());
}
}
return super.onAttack(npc, player, damage, isSummon);
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
return npc.getId() + ".htm";
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final Instance world = player.getInstanceWorld();
if (world != null)
{
synchronized (world)
{
final int count = world.getParameters().getInt("countKill", 0) + 1;
world.setParameter("countKill", count);
checkDoors(npc, world, count);
}
}
switch (npc.getId())
{
case LILIM_MAGUS:
case LILIM_GREAT_MAGUS:
{
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.LORD_SHILEN_SOME_DAY_YOU_WILL_ACCOMPLISH_THIS_MISSION);
break;
}
case LILIM_KNIGHT_ERRANT:
case LILIM_KNIGHT:
case LILIM_GUARD_KNIGHT:
{
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.WHY_ARE_YOU_GETTING_IN_OUR_WAY);
break;
}
case LILIM_SLAYER:
{
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.FOR_SHILEN);
break;
}
}
return super.onKill(npc, player, isSummon);
}
@Override
public String onSpawn(L2Npc npc)
{
npc.setUndying(true);
return super.onSpawn(npc);
}
@Override
public String onTalk(L2Npc npc, L2PcInstance talker)
{
final QuestState qs = talker.getQuestState(Q00196_SevenSignsSealOfTheEmperor.class.getSimpleName());
String htmltext = getNoQuestMsg(talker);
if (qs == null)
{
return htmltext;
}
switch (npc.getId())
{
case PROMISE_OF_MAMMON:
{
if (qs.isCond(3) || qs.isCond(4))
{
enterInstance(talker, npc, TEMPLATE_ID);
return "";
}
break;
}
case LEON:
{
if (qs.getCond() >= 3)
{
takeItems(talker, SACRED_SWORD_OF_EINHASAD, -1);
finishInstance(talker, 0);
htmltext = "32587-01.html";
}
break;
}
case DISCIPLES_GATEKEEPER:
{
if (qs.getCond() >= 3)
{
final Instance world = npc.getInstanceWorld();
if (world != null)
{
world.openCloseDoor(DISCIPLES_NECROPOLIS_DOOR, true);
playMovie(talker, Movie.SSQ_SEALING_EMPEROR_1ST);
startQuestTimer("FIGHT", 1000, null, talker);
}
}
break;
}
}
return htmltext;
}
public static void main(String[] args)
{
new DisciplesNecropolisPast();
}
}

View File

@@ -1,100 +1,78 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.ElcadiasTent;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.quest.QuestState;
import instances.AbstractInstance;
import quests.Q10292_SevenSignsGirlOfDoubt.Q10292_SevenSignsGirlOfDoubt;
import quests.Q10293_SevenSignsForbiddenBookOfTheElmoreAdenKingdom.Q10293_SevenSignsForbiddenBookOfTheElmoreAdenKingdom;
import quests.Q10294_SevenSignsToTheMonasteryOfSilence.Q10294_SevenSignsToTheMonasteryOfSilence;
import quests.Q10296_SevenSignsPowerOfTheSeal.Q10296_SevenSignsPowerOfTheSeal;
/**
* Elcadia's Tent instance zone.
* @author Adry_85
*/
public final class ElcadiasTent extends AbstractInstance
{
// NPCs
private static final int ELCADIA = 32784;
private static final int GRUFF_LOOKING_MAN = 32862;
// Locations
private static final Location START_LOC = new Location(89706, -238074, -9632, 0, 0);
private static final Location EXIT_LOC = new Location(43316, -87986, -2832, 0, 0);
// Misc
private static final int TEMPLATE_ID = 158;
class ETWorld extends InstanceWorld
{
}
public ElcadiasTent()
{
super(ElcadiasTent.class.getSimpleName());
addFirstTalkId(GRUFF_LOOKING_MAN, ELCADIA);
addStartNpc(GRUFF_LOOKING_MAN, ELCADIA);
addTalkId(GRUFF_LOOKING_MAN, ELCADIA);
}
@Override
public String onTalk(L2Npc npc, L2PcInstance talker)
{
if (npc.getId() == GRUFF_LOOKING_MAN)
{
final QuestState GirlOfDoubt = talker.getQuestState(Q10292_SevenSignsGirlOfDoubt.class.getSimpleName());
final QuestState ForbiddenBook = talker.getQuestState(Q10293_SevenSignsForbiddenBookOfTheElmoreAdenKingdom.class.getSimpleName());
final QuestState Monastery = talker.getQuestState(Q10294_SevenSignsToTheMonasteryOfSilence.class.getSimpleName());
final QuestState PowerOfSeal = talker.getQuestState(Q10296_SevenSignsPowerOfTheSeal.class.getSimpleName());
if (((GirlOfDoubt != null) && GirlOfDoubt.isStarted()) //
|| ((GirlOfDoubt != null) && GirlOfDoubt.isCompleted() && (ForbiddenBook == null)) //
|| ((ForbiddenBook != null) && ForbiddenBook.isStarted()) //
|| ((ForbiddenBook != null) && ForbiddenBook.isCompleted() && (Monastery == null)) //
|| ((PowerOfSeal != null) && PowerOfSeal.isStarted()))
{
enterInstance(talker, new ETWorld(), "ElcadiasTent.xml", TEMPLATE_ID);
}
else
{
return "32862-01.html";
}
}
else
{
final InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(talker);
world.removeAllowed(talker.getObjectId());
talker.setInstanceId(0);
talker.teleToLocation(EXIT_LOC);
}
return super.onTalk(npc, talker);
}
@Override
public void onEnterInstance(L2PcInstance player, InstanceWorld world, boolean firstEntrance)
{
if (firstEntrance)
{
world.addAllowed(player.getObjectId());
}
teleportPlayer(player, START_LOC, world.getInstanceId(), false);
}
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.ElcadiasTent;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.quest.QuestState;
import instances.AbstractInstance;
import quests.Q10292_SevenSignsGirlOfDoubt.Q10292_SevenSignsGirlOfDoubt;
import quests.Q10293_SevenSignsForbiddenBookOfTheElmoreAdenKingdom.Q10293_SevenSignsForbiddenBookOfTheElmoreAdenKingdom;
import quests.Q10294_SevenSignsToTheMonasteryOfSilence.Q10294_SevenSignsToTheMonasteryOfSilence;
/**
* Elcadia's Tent instance zone.
* @author Adry_85
*/
public final class ElcadiasTent extends AbstractInstance
{
// NPCs
private static final int ELCADIA = 32784;
private static final int GRUFF_LOOKING_MAN = 32862;
// Misc
private static final int TEMPLATE_ID = 158;
public ElcadiasTent()
{
addFirstTalkId(GRUFF_LOOKING_MAN, ELCADIA);
addStartNpc(GRUFF_LOOKING_MAN, ELCADIA);
addTalkId(GRUFF_LOOKING_MAN, ELCADIA);
}
@Override
public String onTalk(L2Npc npc, L2PcInstance talker)
{
if (npc.getId() == GRUFF_LOOKING_MAN)
{
final QuestState GirlOfDoubt = talker.getQuestState(Q10292_SevenSignsGirlOfDoubt.class.getSimpleName());
final QuestState ForbiddenBook = talker.getQuestState(Q10293_SevenSignsForbiddenBookOfTheElmoreAdenKingdom.class.getSimpleName());
final QuestState Monastery = talker.getQuestState(Q10294_SevenSignsToTheMonasteryOfSilence.class.getSimpleName());
if (((GirlOfDoubt != null) && GirlOfDoubt.isStarted()) //
|| ((GirlOfDoubt != null) && GirlOfDoubt.isCompleted() && (ForbiddenBook == null)) //
|| ((ForbiddenBook != null) && ForbiddenBook.isStarted()) //
|| ((ForbiddenBook != null) && ForbiddenBook.isCompleted() && (Monastery == null)))
{
enterInstance(talker, npc, TEMPLATE_ID);
}
else
{
return "32862-01.html";
}
}
else
{
finishInstance(talker, 0);
}
return super.onTalk(npc, talker);
}
public static void main(String[] args)
{
new ElcadiasTent();
}
}

View File

@@ -0,0 +1,4 @@
<html><body>Priest Cerenas:<br>
You are learning, adventurer. I will pray for your illumination.<br>
(You have already completed this quest.)
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Priest Cerenas:<br>
No, no, this will not do. You have not proven yourself worthy. (You must have started the "Soul Testing" quest to enter.)
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Eva's Avatar:<br>
The Goddess of Destruction has finally resurrected! The energy of water continues to be contaminated....<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EvasHiddenSpace exitInstance">Back</Button>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,92 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.EvasHiddenSpace;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.quest.QuestState;
import instances.AbstractInstance;
import quests.Q10369_NoblesseSoulTesting.Q10369_NoblesseSoulTesting;
/**
* Eva's Hidden Space instance zone.
* @author Gladicek, St3eT
*/
public final class EvasHiddenSpace extends AbstractInstance
{
// NPCs
private static final int CERENAS = 31281;
private static final int EVAS_AVATAR = 33686;
// Misc
private static final int TEMPLATE_ID = 217;
public EvasHiddenSpace()
{
addStartNpc(CERENAS);
addTalkId(CERENAS, EVAS_AVATAR);
addFirstTalkId(EVAS_AVATAR);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = null;
final QuestState qs = player.getQuestState(Q10369_NoblesseSoulTesting.class.getSimpleName());
if (event.equals("enterInstance"))
{
if ((qs != null) && qs.isStarted())
{
enterInstance(player, npc, TEMPLATE_ID);
if (qs.isCond(14))
{
qs.setCond(15);
}
else if (qs.isCond(17))
{
qs.setCond(18);
}
}
else if ((qs != null) && qs.isCompleted())
{
htmltext = "31281-01.html";
}
else
{
htmltext = "31281.html";
}
}
else if (event.equals("exitInstance"))
{
final Instance world = getPlayerInstance(player);
if (world != null)
{
teleportPlayerOut(player, world);
}
}
return htmltext;
}
public static void main(String[] args)
{
new EvasHiddenSpace();
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Aden Vanguard Member:<br>
Go ahead and speak with the Captain and help the Aden Vanguard out!
</body></html>

View File

@@ -1,4 +1,4 @@
<html><body>Aden Vanguard Captain Adolph:<br>
You've caught me resting after a particularly tough battle. So, you're the soldier Orven has sent? Good! You can help my squad with that never-ending stream of monsters. Got any questions?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest IncubatorOfEvil 33170-3.htm">"I'm ready."</Button>
<html><body>Aden Vanguard Captain Adolph:<br>
You've caught me resting after a particularly tough battle. So, you're the soldier Orven has sent? Good! You can help my squad with that never-ending stream of monsters. Got any questions?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EvilIncubator 33170-02.html">"I'm ready."</Button>
</body></html>

View File

@@ -1,4 +1,4 @@
<html><body>Aden Vanguard Captain Adolph:<br>
See my subordinates there? They are elite veterans who have known many victories. Two of them will wait here, while you, me, and the other two enter the enemy base.<br>
Go and talk to my squad and pick out two you'd like to have at your side.
<html><body>Aden Vanguard Captain Adolph:<br>
See my subordinates there? They are elite veterans who have known many victories. Two of them will wait here, while you, me, and the other two enter the enemy base.<br>
Go and talk to my squad and pick out two you'd like to have at your side.
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Aden Vanguard Captain Adolph:<br>
I see you've chosen strong allies.<br1>
This battle will be fierce, and if you see me go down, do not hesitate to run. We can't afford to lose any more people, and if that happens, you will need time to regroup.<br1>
Now, I hope you're ready to take this fight to the enemy, because we're going into their base.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EvilIncubator teamSelected">"I'm ready."</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Aden Vanguard Captain Adolph:<br>
Focus on the enemies in front of you. Looking away in battle is suicide.
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Aden Vanguard Captain Adolph:<br>
Phew! What a fight, eh? Now, there is a boss beyond that door, so let's take a short break. We must call him out and defeat him before we can leave.<br>
I was worried, but I think I will be able to bring out your full potential. I will lend you this temporarily.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EvilIncubator giveItem">"Thank you."</Button>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Aden Vanguard Captain Adolph:<br>
The kingdom gave me this ring, and I've been holding onto it for someone worthy. Now I've seen you in action, I think you should borrow it for the coming fight.<br>
It is imbued with a magic that allows the wearer to draw upon power that they will some day come to possess. With this, you will be formidable indeed.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Aden Vanguard Captain Adolph:<br>
When you're rested, let's take on those monsters. Are you ready?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EvilIncubator resumeFight">"I'm ready."</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Aden Vanguard Captain Adolph:<br>
I don't know where you came from, but Aden Castle is certainly glad of your help. Now, go back to your master for further instructions. I'm sure you need to report on what happened here, and I think we have things under control now.
</body></html>

View File

@@ -1,4 +1,4 @@
<html><body>Aden Vanguard Captain Adolph:<br>
As Shilen grows in power, more monsters will emerge from here. We can't just let this happen without fighting back!<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h Quest IncubatorOfEvil">Quest</Button>
<html><body>Aden Vanguard Captain Adolph:<br>
As Shilen grows in power, more monsters will emerge from here. We can't just let this happen without fighting back!<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h Quest EvilIncubator">Quest</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Priest Alice:<br>
Speak with Adolph first.
</body></html>

View File

@@ -1,4 +1,4 @@
<html><body>Priest Alice:<br>
Do you need my help? I can heal, and provide support in combat.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest IncubatorOfEvil select_alice">Select</Button>
<html><body>Priest Alice:<br>
Do you need my help? I can heal, and provide support in combat.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EvilIncubator selectHelper">Select</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Alice:<br>
This is dangerous. Quit fidgeting and concentrate.
</body></html>

View File

@@ -1,4 +1,4 @@
<html><body>Priest Alice:<br>
Even the strongest soldier will fall if they cannot be healed in battle. My healing power will lead us to victory.<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h Quest IncubatorOfEvil">Quest</Button>
<html><body>Priest Alice:<br>
Even the strongest soldier will fall if they cannot be healed in battle. My healing power will lead us to victory.<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h Quest EvilIncubator">Quest</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Officer Barton:<br>
Speak with Adolph.
</body></html>

View File

@@ -1,4 +1,4 @@
<html><body>Officer Barton:<br>
You need my help? Well, you look like a capable sort. I need someone like you to watch my back.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest IncubatorOfEvil select_barton">Select</Button>
<html><body>Officer Barton:<br>
You need my help? Well, you look like a capable sort. I need someone like you to watch my back.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EvilIncubator selectHelper">Select</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Officer Barton:<br>
I hope to see you on the battlefield again, but for now I must observe the enemy from here.
</body></html>

View File

@@ -1,4 +1,4 @@
<html><body>Officer Barton:<br>
Not to brag, but a star soldier such as myself can make the difference between winning and losing.<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h Quest IncubatorOfEvil">Quest</Button>
<html><body>Officer Barton:<br>
Not to brag, but a star soldier such as myself can make the difference between winning and losing.<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h Quest EvilIncubator">Quest</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Sniper Hayuk:<br>
You don't want to talk to me, you want Captain Adolph.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Sniper Hayuk:<br>
Do you need my help? Of course! I will cover your back! You can trust me.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EvilIncubator selectHelper">"Yes, I could use some help."</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Hayuk:<br>
We are in the middle of a battle. Let's deal with the enemies first.
</body></html>

View File

@@ -1,4 +1,4 @@
<html><body>Sniper Hayuk:<br>
If you can defeat your enemy before they get close, you can annihilate their forces without incurring any damage to your own team. Heh! That there is what's called strategy!<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h Quest IncubatorOfEvil">Quest</Button>
<html><body>Sniper Hayuk:<br>
If you can defeat your enemy before they get close, you can annihilate their forces without incurring any damage to your own team. Heh! That there is what's called strategy!<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h Quest EvilIncubator">Quest</Button>
</body></html>

View File

@@ -0,0 +1,2 @@
<html><body>Magus Eliyah:<br>
Instead of talking to me, perhaps you should speak with Adolph first?</body></html>

View File

@@ -1,4 +1,4 @@
<html><body>Magus Eliyah:<br>
You need my help? Well, if you protect me from the monsters, I suppose I can help.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest IncubatorOfEvil select_eliyah">Select</Button>
<html><body>Magus Eliyah:<br>
You need my help? Well, if you protect me from the monsters, I suppose I can help.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest EvilIncubator selectHelper">Select</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Magus Eliyah:<br>
What is it? I don't think you have any business with me, do you? Now get out there and concentrate on living to fight another day.
</body></html>

View File

@@ -1,4 +1,4 @@
<html><body>Magus Eliyah:<br>
The Ivory Tower's magic is much too powerful for these monsters. We have no need to skulk on the sidelines!<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h Quest IncubatorOfEvil">Quest</Button>
<html><body>Magus Eliyah:<br>
The Ivory Tower's magic is much too powerful for these monsters. We have no need to skulk on the sidelines!<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h Quest EvilIncubator">Quest</Button>
</body></html>

View File

@@ -0,0 +1,566 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.EvilIncubator;
import java.util.EnumMap;
import java.util.List;
import com.l2jmobius.commons.util.CommonUtil;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.enums.Race;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Attackable;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.FriendlyNpcInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.base.ClassId;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureDeath;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.model.quest.State;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import instances.AbstractInstance;
import quests.Q10341_DayOfDestinyHumansFate.Q10341_DayOfDestinyHumansFate;
import quests.Q10342_DayOfDestinyElvenFate.Q10342_DayOfDestinyElvenFate;
import quests.Q10343_DayOfDestinyDarkElfsFate.Q10343_DayOfDestinyDarkElfsFate;
import quests.Q10344_DayOfDestinyOrcsFate.Q10344_DayOfDestinyOrcsFate;
import quests.Q10345_DayOfDestinyDwarfsFate.Q10345_DayOfDestinyDwarfsFate;
import quests.Q10346_DayOfDestinyKamaelsFate.Q10346_DayOfDestinyKamaelsFate;
/**
* Evil Incubator instance zone.
* @author St3eT
*/
public final class EvilIncubator extends AbstractInstance
{
// NPCs
private static final int VANGUARD_MEMBER = 33165;
private static final int ADOLPH = 33170;
private static final int ALICE = 33171;
private static final int BARTON = 33172;
private static final int HAYUK = 33173;
private static final int ELIYAH = 33174;
private static final int[] MONSTERS =
{
27431, // Slayer
27432, // Tracker
27433, // Priest of Darkness
27434, // Guardian of Darkness
27430, // Screaming Shaman
};
private static final int[] BOSSES =
{
27425, // Death Wound
27426, // Death Wound
27427, // Death Wound
27428, // Death Wound
27429, // Death Wound
};
private static final int[] HELPERS =
{
33170, // Adolph
// 33171, // Priest Alice
33172, // Officer Barton
33173, // Sniper Hayuk
33174, // Magus Eliyah
33414, // Van Archer
33415, // Van Infantry
};
// Items
private static final int SOE = 736; // Scroll of Escape
// Locations
private static final Location PLAYER_BATTLE_LOC = new Location(56167, -175615, -7944);
private static final Location BATTLE_LOC_2 = new Location(56005, -175536, -7952);
private static final Location BATTLE_LOC_3 = new Location(56325, -175536, -7952);
private static final Location BOSS_LOC = new Location(56165, -177550, -7944);
// Misc
private static final int TEMPLATE_ID = 185;
//@formatter:off
private static final EnumMap<Race, String> RACE_QUESTS = new EnumMap<>(Race.class);
static
{
RACE_QUESTS.put(Race.HUMAN, Q10341_DayOfDestinyHumansFate.class.getSimpleName());
RACE_QUESTS.put(Race.ELF, Q10342_DayOfDestinyElvenFate.class.getSimpleName());
RACE_QUESTS.put(Race.DARK_ELF, Q10343_DayOfDestinyDarkElfsFate.class.getSimpleName());
RACE_QUESTS.put(Race.ORC, Q10344_DayOfDestinyOrcsFate.class.getSimpleName());
RACE_QUESTS.put(Race.DWARF, Q10345_DayOfDestinyDwarfsFate.class.getSimpleName());
RACE_QUESTS.put(Race.KAMAEL, Q10346_DayOfDestinyKamaelsFate.class.getSimpleName());
}
private static final EnumMap<ClassId, Integer> CLASS_BOSS = new EnumMap<>(ClassId.class);
static
{
CLASS_BOSS.put(ClassId.GLADIATOR, 27426);
CLASS_BOSS.put(ClassId.WARLORD, 27426);
CLASS_BOSS.put(ClassId.PALADIN, 27425);
CLASS_BOSS.put(ClassId.DARK_AVENGER, 27425);
CLASS_BOSS.put(ClassId.TREASURE_HUNTER, 27426);
CLASS_BOSS.put(ClassId.HAWKEYE, 27428);
CLASS_BOSS.put(ClassId.SORCERER, 27428);
CLASS_BOSS.put(ClassId.NECROMANCER, 27428);
CLASS_BOSS.put(ClassId.WARLOCK, 27428);
CLASS_BOSS.put(ClassId.BISHOP, 27427);
CLASS_BOSS.put(ClassId.PROPHET, 27429);
CLASS_BOSS.put(ClassId.TEMPLE_KNIGHT, 27425);
CLASS_BOSS.put(ClassId.SWORDSINGER, 27429);
CLASS_BOSS.put(ClassId.PLAINS_WALKER, 27426);
CLASS_BOSS.put(ClassId.SILVER_RANGER, 27428);
CLASS_BOSS.put(ClassId.SPELLSINGER, 27428);
CLASS_BOSS.put(ClassId.ELEMENTAL_SUMMONER, 27428);
CLASS_BOSS.put(ClassId.ELDER, 27427);
CLASS_BOSS.put(ClassId.SHILLIEN_KNIGHT, 27425);
CLASS_BOSS.put(ClassId.BLADEDANCER, 27429);
CLASS_BOSS.put(ClassId.ABYSS_WALKER, 27426);
CLASS_BOSS.put(ClassId.PHANTOM_RANGER, 27428);
CLASS_BOSS.put(ClassId.SPELLHOWLER, 27428);
CLASS_BOSS.put(ClassId.PHANTOM_SUMMONER, 27428);
CLASS_BOSS.put(ClassId.SHILLIEN_ELDER, 27427);
CLASS_BOSS.put(ClassId.DESTROYER, 27426);
CLASS_BOSS.put(ClassId.TYRANT, 27426);
CLASS_BOSS.put(ClassId.OVERLORD, 27429);
CLASS_BOSS.put(ClassId.WARCRYER, 27429);
CLASS_BOSS.put(ClassId.BOUNTY_HUNTER, 27426);
CLASS_BOSS.put(ClassId.WARSMITH, 27426);
CLASS_BOSS.put(ClassId.BERSERKER, 27426);
CLASS_BOSS.put(ClassId.MALE_SOULBREAKER, 27426);
CLASS_BOSS.put(ClassId.FEMALE_SOULBREAKER, 27426);
CLASS_BOSS.put(ClassId.ARBALESTER, 27428);
}
private static final EnumMap<ClassId, Integer> CLASS_ITEMS = new EnumMap<>(ClassId.class);
static
{
CLASS_ITEMS.put(ClassId.GLADIATOR, 17484);
CLASS_ITEMS.put(ClassId.WARLORD, 17485);
CLASS_ITEMS.put(ClassId.PALADIN, 17486);
CLASS_ITEMS.put(ClassId.DARK_AVENGER, 17487);
CLASS_ITEMS.put(ClassId.TREASURE_HUNTER, 17488);
CLASS_ITEMS.put(ClassId.HAWKEYE, 17489);
CLASS_ITEMS.put(ClassId.SORCERER, 17490);
CLASS_ITEMS.put(ClassId.NECROMANCER, 17491);
CLASS_ITEMS.put(ClassId.WARLOCK, 17492);
CLASS_ITEMS.put(ClassId.BISHOP, 17493);
CLASS_ITEMS.put(ClassId.PROPHET, 17494);
CLASS_ITEMS.put(ClassId.TEMPLE_KNIGHT, 17495);
CLASS_ITEMS.put(ClassId.SWORDSINGER, 17496);
CLASS_ITEMS.put(ClassId.PLAINS_WALKER, 17497);
CLASS_ITEMS.put(ClassId.SILVER_RANGER, 17498);
CLASS_ITEMS.put(ClassId.SPELLSINGER, 17499);
CLASS_ITEMS.put(ClassId.ELEMENTAL_SUMMONER, 17500);
CLASS_ITEMS.put(ClassId.ELDER, 17501);
CLASS_ITEMS.put(ClassId.SHILLIEN_KNIGHT, 17502);
CLASS_ITEMS.put(ClassId.BLADEDANCER, 17503);
CLASS_ITEMS.put(ClassId.ABYSS_WALKER, 17504);
CLASS_ITEMS.put(ClassId.PHANTOM_RANGER, 17505);
CLASS_ITEMS.put(ClassId.SPELLHOWLER, 17506);
CLASS_ITEMS.put(ClassId.PHANTOM_SUMMONER, 17507);
CLASS_ITEMS.put(ClassId.SHILLIEN_ELDER, 17508);
CLASS_ITEMS.put(ClassId.DESTROYER, 17509);
CLASS_ITEMS.put(ClassId.TYRANT, 17510);
CLASS_ITEMS.put(ClassId.OVERLORD, 17511);
CLASS_ITEMS.put(ClassId.WARCRYER, 17512);
CLASS_ITEMS.put(ClassId.BOUNTY_HUNTER, 17513);
CLASS_ITEMS.put(ClassId.WARSMITH, 17514);
CLASS_ITEMS.put(ClassId.BERSERKER, 17515);
CLASS_ITEMS.put(ClassId.MALE_SOULBREAKER, 17516);
CLASS_ITEMS.put(ClassId.FEMALE_SOULBREAKER, 17516);
CLASS_ITEMS.put(ClassId.ARBALESTER, 17517);
}
//@formatter:on
public EvilIncubator()
{
addStartNpc(VANGUARD_MEMBER);
addTalkId(VANGUARD_MEMBER, ADOLPH, ALICE, BARTON, HAYUK, ELIYAH);
addFirstTalkId(ADOLPH, ALICE, BARTON, HAYUK, ELIYAH);
setCreatureKillId(this::onCreatureKill, MONSTERS);
setCreatureKillId(this::onCreatureKill, BOSSES);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final QuestState st = getQuestState(player);
if ((st == null) || !st.isStarted())
{
return super.onAdvEvent(event, npc, player);
}
String htmltext = null;
if (event.equals("enterInstance"))
{
enterInstance(player, npc, TEMPLATE_ID);
st.setCond(5);
htmltext = "33165-01.html";
}
else
{
final Instance world = npc.getInstanceWorld();
if (world != null)
{
switch (event)
{
case "33170-02.html":
{
if (st.isCond(5))
{
st.setCond(6, true);
htmltext = event;
}
break;
}
case "selectHelper":
{
int helperCount = world.getParameters().getInt("HELPER_COUNT", 0);
if ((helperCount < 2) && st.isCond(6))
{
helperCount++;
world.setParameter("HELPER_COUNT", helperCount);
npc.teleToLocation(helperCount == 1 ? BATTLE_LOC_2 : BATTLE_LOC_3);
if (helperCount == 2)
{
st.setCond(7, true);
L2World.getInstance().getVisibleObjects(world.getNpc(ADOLPH), FriendlyNpcInstance.class, 1000).forEach(c -> c.deleteMe());
}
}
break;
}
case "teamSelected":
{
int helperCount = world.getParameters().getInt("HELPER_COUNT", 0);
if ((helperCount == 2) && st.isCond(7))
{
helperCount++;
world.setParameter("HELPER_COUNT", helperCount);
st.setCond(8, true);
npc.teleToLocation(PLAYER_BATTLE_LOC);
player.teleToLocation(PLAYER_BATTLE_LOC);
getTimers().addTimer("SPAWN_WAVE", 5000, e -> manageWaveSpawn(world));
}
break;
}
case "giveItem":
{
if (st.isCond(9))
{
st.setCond(10, true);
final int classItemId = CLASS_ITEMS.getOrDefault(player.getClassId(), -1);
if ((classItemId != -1) && !hasQuestItems(player, classItemId))
{
giveItems(player, classItemId, 1);
}
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.THE_CRY_OF_DESTINY_PENDANT_WILL_BE_HELPFUL_TO_YOU_PLEASE_EQUIP_IT_AND_BRING_OUT_THE_POWER_OF_THE_PENDANT_TO_PREPARE_FOR_THE_NEXT_FIGHT);
htmltext = "33170-06.html";
}
break;
}
case "resumeFight":
{
if (st.isCond(10))
{
st.setCond(11, true);
manageWaveSpawn(world);
}
break;
}
}
}
}
return htmltext;
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player, boolean isSimulated)
{
String htmltext = getNoQuestMsg(player);
final QuestState st = getQuestState(player);
if ((st == null) || !st.isStarted())
{
return super.onTalk(npc, player, isSimulated);
}
if (st.getState() == State.STARTED)
{
switch (npc.getId())
{
case ADOLPH:
{
switch (st.getCond())
{
case 5:
{
htmltext = npc.getId() + "-01.html";
break;
}
case 6:
{
htmltext = "33170-02.html";
break;
}
case 7:
{
htmltext = "33170-03.html";
break;
}
case 9:
{
htmltext = "33170-05.html";
break;
}
case 10:
{
htmltext = "33170-07.html";
break;
}
case 12:
{
st.setCond(13, true);
giveItems(player, SOE, 1);
}
case 13:
{
htmltext = "33170-08.html";
break;
}
}
break;
}
case ALICE:
case BARTON:
case ELIYAH:
case HAYUK:
{
switch (st.getCond())
{
case 5:
{
htmltext = npc.getId() + "-01.html";
break;
}
case 6:
{
htmltext = npc.getId() + "-02.html";
break;
}
}
break;
}
}
}
return htmltext;
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
String htmltext = null;
final QuestState st = getQuestState(player);
if ((st == null) || !st.isStarted())
{
return htmltext;
}
switch (npc.getId())
{
case ADOLPH:
{
switch (st.getCond())
{
case 5:
case 6:
case 7:
case 9:
case 10:
case 12:
case 13:
{
htmltext = "33170.html";
break;
}
default:
{
htmltext = "33170-04.html";
}
}
break;
}
case ALICE:
case BARTON:
case ELIYAH:
case HAYUK:
{
htmltext = st.getCond() > 7 ? (npc.getId() + "-03.html") : (npc.getId() + ".html");
break;
}
}
return htmltext;
}
public void onCreatureKill(OnCreatureDeath event)
{
final L2Npc npc = (L2Npc) event.getTarget();
final Instance world = npc.getInstanceWorld();
if (world != null)
{
final int waveId = world.getParameters().getInt("WORLD_WAVE", 1);
if (CommonUtil.contains(BOSSES, npc.getId()))
{
final QuestState st = getQuestState(world.getFirstPlayer());
if ((st == null) || !st.isStarted())
{
return;
}
st.setCond(12, true);
}
else if (waveId < 8)
{
if (world.getAliveNpcs(MONSTERS).isEmpty())
{
getTimers().addTimer("SPAWN_WAVE", 5000, e -> manageWaveSpawn(world));
}
}
getTimers().addTimer("WORLD_ATTACK", 1000, e -> managerWorldAttack(world, null));
}
}
@Override
public void onTimerEvent(String event, StatsSet params, L2Npc npc, L2PcInstance player)
{
}
private void manageWaveSpawn(Instance world)
{
final QuestState st = getQuestState(world.getFirstPlayer());
if ((st == null) || !st.isStarted())
{
return;
}
List<L2Npc> spawnedNpcs = null;
int waveId = world.getParameters().getInt("WORLD_WAVE", 1);
switch (waveId)
{
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
{
spawnedNpcs = world.spawnGroup("wave_" + waveId);
waveId++;
world.setParameter("WORLD_WAVE", waveId);
showOnScreenMsg(world, NpcStringId.CREATURES_RESURRECTED_DEFEND_YOURSELF, ExShowScreenMessage.TOP_CENTER, 5000, true);
break;
}
case 7:
{
waveId++;
world.setParameter("WORLD_WAVE", waveId);
showOnScreenMsg(world, NpcStringId.CREATURES_HAVE_STOPPED_THEIR_ATTACK_REST_AND_THEN_SPEAK_WITH_ADOLPH, ExShowScreenMessage.TOP_CENTER, 5000, true);
st.setCond(9, true);
break;
}
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
{
spawnedNpcs = world.spawnGroup("wave_" + waveId);
waveId++;
world.setParameter("WORLD_WAVE", waveId);
showOnScreenMsg(world, NpcStringId.CREATURES_RESURRECTED_DEFEND_YOURSELF, ExShowScreenMessage.TOP_CENTER, 5000, true);
getTimers().addTimer("SPAWN_WAVE", 20000, e -> manageWaveSpawn(world));
break;
}
case 15:
{
spawnedNpcs = world.spawnGroup("wave_" + waveId);
waveId++;
world.setParameter("WORLD_WAVE", waveId);
showOnScreenMsg(world, NpcStringId.I_DEATH_WOUND_CHAMPION_OF_SHILEN_SHALL_END_YOUR_WORLD, ExShowScreenMessage.TOP_CENTER, 5000, true);
getTimers().addTimer("SPAWN_WAVE", 20000, e -> manageWaveSpawn(world));
final L2Npc boss = addSpawn(CLASS_BOSS.get(world.getFirstPlayer().getClassId()), BOSS_LOC, false, 0, false, world.getId());
world.broadcastPacket(new Earthquake(boss, 50, 10));
break;
}
}
managerWorldAttack(world, spawnedNpcs);
}
private void managerWorldAttack(Instance world, List<L2Npc> spawnedNpcs)
{
final List<FriendlyNpcInstance> helperList = L2World.getInstance().getVisibleObjects(world.getFirstPlayer(), FriendlyNpcInstance.class);
if ((spawnedNpcs != null) && !spawnedNpcs.isEmpty())
{
for (L2Npc npc : spawnedNpcs)
{
if (!helperList.isEmpty())
{
final FriendlyNpcInstance helper = helperList.get(getRandom(helperList.size()));
if (CommonUtil.contains(HELPERS, helper.getId()))
{
npc.reduceCurrentHp(1, helper, null);
helper.reduceCurrentHp(1, npc, null);
addAttackDesire(helper, npc);
helperList.remove(helper);
}
}
}
}
for (FriendlyNpcInstance helper : helperList)
{
for (L2Attackable monster : L2World.getInstance().getVisibleObjects(helper, L2Attackable.class))
{
if (!(monster instanceof FriendlyNpcInstance))
{
addAttackDesire(helper, monster);
}
}
}
}
private QuestState getQuestState(L2PcInstance player)
{
if (player == null)
{
return null;
}
return RACE_QUESTS.containsKey(player.getRace()) ? player.getQuestState(RACE_QUESTS.get(player.getRace())) : null;
}
public static void main(String[] args)
{
new EvilIncubator();
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Magister Ayanthe:<br>
The monsters are coming. Concentrate and attack!
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Magister Ayanthe:<br>
Focus on the fight!<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest FaeronTrainingGrounds1 33944-03.html">"Create more monsters so I can train."</Button>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Magister Ayanthe:<br>
Good. It pleases me that you're taking your training so seriously.<br>
But bear in mind that this is training, and not the real world. We will limit the number of monsters you face in a single encounter.
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Magister Ayanthe:<br>
You're better than I expected. Feels different from training with a dummy, right?<br>
Here, take these <font color="LEVEL">Spiritshots</font>. Right now, your weapon has no grade, but as you become stronger, you'll be using D-grade, C-grade, and even R-grade weapons. They're proving to be very valuable in the Material Realm.<br>
Go ahead and <font color="LEVEL">activate the Spiritshots</font>.<br>
I'll go prepare more monsters for your next training session, so let me know when the Spiritshots have been activated.<br>
(You can conveniently automate your Spiritshots by creating a <font color="LEVEL">shortcut</font> and then <font color="LEVEL">right-clicking</font> on it.)
</body></html>

View File

@@ -0,0 +1,3 @@
<html><head><body>Magister Ayanthe:<br>
All right, now your training begins again!
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Mastery Ayanthe:<br>
I see you're a quick study. I'm impressed. I can't wait to see how much you'll have improved in the future. You have recovered some of your power that has been sealed while passing through the Dimensional Rift. These are called <font color="LEVEL">Skills</font>.<br>
The more abilities you recover, the stronger you'll grow.<br>
Now that you've recovered some of your power, shall we face tougher enemies? Are you ready?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest FaeronTrainingGrounds1 33944-07.html">"My body is ready."</Button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Magister Ayanthe:<br>
If you don't use your <font color="LEVEL">skills</font>, this next battle will be difficult!
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Magister Ayanthe:<br>
Great work. You've made me very proud. You must be exhausted. Shall we step outside?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest FaeronTrainingGrounds1 exit_instance">"I'd like to go outside."</button>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Magister Ayanthe:<br>
Don't underestimate the enemy you see before you.<br>
While in battle, you must never lose focus.<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest FaeronTrainingGrounds1">Quest</Button>
</body></html>

View File

@@ -1,90 +1,309 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.FaeronTrainingGrounds1;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import instances.AbstractInstance;
import quests.Q10735_ASpecialPower.Q10735_ASpecialPower;
/**
* Fearon Training Grounds Instance Zone.
* @author Sdw
*/
public final class FaeronTrainingGrounds1 extends AbstractInstance
{
// NPCs
private static final int AYANTHE = 33942;
private static final int AYANTHE_2 = 33944;
// Locations
private static final Location START_LOC = new Location(-74903, 240618, -3584);
private static final Location EXIT_LOC = new Location(-82088, 249880, -3392);
// Misc
private static final int TEMPLATE_ID = 251;
class FTGWorld extends InstanceWorld
{
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final QuestState qs = player.getQuestState(Q10735_ASpecialPower.class.getSimpleName());
if (qs == null)
{
return null;
}
if (event.equals("enter_instance"))
{
enterInstance(player, new FTGWorld(), "FaeronTrainingGrounds1.xml", TEMPLATE_ID);
}
else if (event.equals("exit_instance"))
{
final InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
world.removeAllowed(player.getObjectId());
teleportPlayer(player, EXIT_LOC, 0);
}
return super.onAdvEvent(event, npc, player);
}
public FaeronTrainingGrounds1()
{
super(FaeronTrainingGrounds1.class.getSimpleName());
addStartNpc(AYANTHE, AYANTHE_2);
addTalkId(AYANTHE, AYANTHE_2);
}
@Override
public void onEnterInstance(L2PcInstance player, InstanceWorld world, boolean firstEntrance)
{
if (firstEntrance)
{
world.addAllowed(player.getObjectId());
showOnScreenMsg(player, NpcStringId.TALK_TO_MAGISTER_AYANTHE, ExShowScreenMessage.TOP_CENTER, 4500);
}
teleportPlayer(player, START_LOC, world.getInstanceId());
}
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.FaeronTrainingGrounds1;
import com.l2jmobius.gameserver.enums.QuestSound;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import com.l2jmobius.gameserver.network.serverpackets.TutorialShowHtml;
import instances.AbstractInstance;
import quests.Q10735_ASpecialPower.Q10735_ASpecialPower;
/**
* Fearon Training Grounds Instance Zone.
* @author Sdw, malyelfik
*/
public final class FaeronTrainingGrounds1 extends AbstractInstance
{
// NPCs
private static final int AYANTHE = 33942;
private static final int AYANTHE_2 = 33944;
// Monsters
private static final int FLOATO = 27526;
private static final int FLOATO2 = 27531;
private static final int RATEL = 27527;
// Items
private static final ItemHolder SPIRITSHOTS_TRAINING = new ItemHolder(2509, 150);
// Locations
private static final Location[] MOB_SPAWNS =
{
new Location(-74721, 240513, -3584),
new Location(-74760, 240773, -3560)
};
// Misc
private static final int TEMPLATE_ID = 251;
private static final double DAMAGE_BY_SKILL = 0.5d; // Percent
public FaeronTrainingGrounds1()
{
addStartNpc(AYANTHE, AYANTHE_2);
addFirstTalkId(AYANTHE_2);
addTalkId(AYANTHE, AYANTHE_2);
addKillId(FLOATO, FLOATO2, RATEL);
addSkillSeeId(RATEL);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final QuestState qs = player.getQuestState(Q10735_ASpecialPower.class.getSimpleName());
String htmltext = null;
if (qs == null)
{
return htmltext;
}
switch (event)
{
case "enter_instance":
enterInstance(player, npc, TEMPLATE_ID);
break;
case "exit_instance":
finishInstance(player, 0);
break;
case "33944-03.html":
{
if (qs.isCond(6))
{
spawnMonsters(RATEL, player);
showOnScreenMsg(player, NpcStringId.FIGHT_USING_SKILLS, ExShowScreenMessage.TOP_CENTER, 10000);
}
else
{
final int npcId = (qs.isCond(4)) ? FLOATO2 : FLOATO;
spawnMonsters(npcId, player);
showOnScreenMsg(player, NpcStringId.ATTACK_THE_MONSTER, ExShowScreenMessage.TOP_CENTER, 10000);
}
htmltext = event;
break;
}
case "33944-07.html":
{
if (qs.isCond(5))
{
qs.setCond(6, true);
showOnScreenMsg(player, NpcStringId.FIGHT_USING_SKILLS, ExShowScreenMessage.TOP_CENTER, 10000);
spawnMonsters(RATEL, player);
htmltext = event;
}
break;
}
}
return htmltext;
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
final QuestState qs = player.getQuestState(Q10735_ASpecialPower.class.getSimpleName());
String htmltext = getNoQuestMsg(player);
if (qs == null)
{
return htmltext;
}
if ((npc.getId() == AYANTHE_2) && qs.isStarted())
{
switch (qs.getCond())
{
case 1:
{
qs.setCond(2, true);
spawnMonsters(FLOATO, player);
showOnScreenMsg(player, NpcStringId.ATTACK_THE_MONSTER, ExShowScreenMessage.TOP_CENTER, 10000);
htmltext = "33944-01.html";
break;
}
case 2:
case 4:
case 6:
{
htmltext = "33944-02.html";
break;
}
case 3:
{
if (qs.getInt("ss") == 1)
{
spawnMonsters(FLOATO2, player);
showOnScreenMsg(player, NpcStringId.ATTACK_THE_MONSTER, ExShowScreenMessage.TOP_CENTER, 10000);
qs.setCond(4, true);
htmltext = "33944-05.html";
}
else
{
qs.set("ss", 1);
giveItems(player, SPIRITSHOTS_TRAINING);
showOnScreenMsg(player, NpcStringId.AUTOMATE_SPIRITSHOT_AS_SHOWN_IN_THE_TUTORIAL, ExShowScreenMessage.TOP_CENTER, 10000);
player.sendPacket(new TutorialShowHtml(npc.getObjectId(), "..\\L2Text\\QT_003_bullet_01.htm", TutorialShowHtml.LARGE_WINDOW));
htmltext = "33944-04.html";
}
break;
}
case 5:
{
player.sendPacket(new TutorialShowHtml(npc.getObjectId(), "..\\L2Text\\QT_004_skill_01.htm", TutorialShowHtml.LARGE_WINDOW));
htmltext = "33944-06.html";
break;
}
case 7:
{
htmltext = "33944-08.html";
break;
}
}
}
return htmltext;
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
// Check if monster is inside instance
final Instance world = npc.getInstanceWorld();
if (world == null)
{
return super.onKill(npc, killer, isSummon);
}
// Remove monster from instance spawn holder
world.setParameter("Mob" + npc.getScriptValue(), null);
// Handle quest state
final QuestState qs = killer.getQuestState(Q10735_ASpecialPower.class.getSimpleName());
if (qs != null)
{
switch (npc.getId())
{
case FLOATO:
case FLOATO2:
{
if ((qs.isCond(2) || qs.isCond(4)) && onKillQuestChange(killer, qs))
{
despawnMonsters(killer);
if (qs.isCond(5) && (killer.getLevel() < 5))
{
addExpAndSp(killer, 1716, 0);
}
}
break;
}
case RATEL:
{
if (qs.isCond(6) && onKillQuestChange(killer, qs))
{
despawnMonsters(killer);
showOnScreenMsg(killer, NpcStringId.TALK_TO_AYANTHE_TO_LEAVE_THE_TRAINING_GROUNDS, ExShowScreenMessage.TOP_CENTER, 10000);
}
break;
}
}
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onSkillSee(L2Npc npc, L2PcInstance player, Skill skill, com.l2jmobius.gameserver.model.L2Object[] targets, boolean isSummon)
{
if (!npc.isDead() && (player.getTarget() == npc))
{
final double dmg = npc.getMaxHp() * DAMAGE_BY_SKILL;
npc.reduceCurrentHp(dmg, player, null);
}
return super.onSkillSee(npc, player, skill, targets, isSummon);
}
/**
* Handle death of training monster. When all monsters are killed, quest cond is increased.
* @param killer player who killed monster
* @param qs quest state of killer
* @return {@code true} when all monsters are killed, otherwise {@code false}
*/
private boolean onKillQuestChange(L2PcInstance killer, QuestState qs)
{
final int value = qs.getMemoStateEx(Q10735_ASpecialPower.KILL_COUNT_VAR) + 1;
if (value >= 2)
{
qs.setCond(qs.getCond() + 1, true);
qs.setMemoStateEx(Q10735_ASpecialPower.KILL_COUNT_VAR, 0);
return true;
}
playSound(killer, QuestSound.ITEMSOUND_QUEST_ITEMGET);
qs.setMemoStateEx(Q10735_ASpecialPower.KILL_COUNT_VAR, value);
qs.getQuest().sendNpcLogList(killer);
return false;
}
/**
* Spawn training monsters inside instance
* @param npcId template id of training monster
* @param player player that owns instance
*/
private void spawnMonsters(int npcId, L2PcInstance player)
{
final Instance world = player.getInstanceWorld();
if (world != null)
{
final StatsSet params = world.getParameters();
for (int i = 0; i < MOB_SPAWNS.length; i++)
{
if (params.getObject("Mob" + i, L2Npc.class) == null)
{
final L2Npc npc = addSpawn(npcId, MOB_SPAWNS[i], false, 0, false, world.getId());
npc.setScriptValue(i);
params.set("Mob" + i, npc);
}
}
}
}
/**
* Despawn training monsters inside instance
* @param player player that owns instance
*/
private void despawnMonsters(L2PcInstance player)
{
final Instance world = player.getInstanceWorld();
if (world != null)
{
final StatsSet params = world.getParameters();
for (int i = 0; i < MOB_SPAWNS.length; i++)
{
final L2Npc mob = params.getObject("Mob" + i, L2Npc.class);
if (mob != null)
{
mob.deleteMe();
params.remove("Mob" + i);
}
}
}
}
public static void main(String[] args)
{
new FaeronTrainingGrounds1();
}
}

View File

@@ -0,0 +1,4 @@
<html><body>Master Katalin:<br>
The monsters are here.<br>
Stay focused in battle and take care not to get hurt.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Master Katalin:<br>
Focus on your battle!<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest FaeronTrainingGrounds2 33945-03.html">"More monsters please."</button>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Master Katalin:<br>
It's good to see you train hard.<br>
But for your safety, there's a limit to the number of monsters at once.
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Master Katalin:<br>
Different from the Training Dummies?<br>
Take these <font color="LEVEL">Soulshots</font>. They have no grade, but as you get stronger and get better weapons, you can use Grade D, C, B, A, S, S-80, and eventually R. It's very important in the Material Realm.<br>
<font color="LEVEL">Activate Soulshots</font>.<br>
I will prepare the next set of monsters. Tell me when you have activated the Soulshots.<br>
(How to Enable Auto-Use Soulshot or Spiritshot: Open your <font color="LEVEL">Inventory</font>. <font color="LEVEL">Click and Drag</font> Soulshot/Spiritshot into your Shortcut Bar. Right Click the Soulshot/Spiritshot Shortcut Icon to use it automatically.)
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Master Katalin:<br>
Okay, here we go again.
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Master Katalin:<br>
Do you know what just happened? You were able to use a lot of abilities when you were in the Wind Spirit Realm. But as you came through the Dimensional Rift, your abilities were locked.<br>
But you just unlocked one of those abilities. They call them <font color="LEVEL">Skills</font> here.<br>
As you train more, you will be able to get more skills back.<br>
Shall we fight a more powerful enemy with your new skill?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest FaeronTrainingGrounds2 33945-07.html">"Okay."</button>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Master Katalin:<br>
This battle won't be easy without your <font color="LEVEL">Skills</font>!
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Master Katalin:<br>
Good work! I am proud of you.<br>
We're done. Let's get out.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest FaeronTrainingGrounds2 exit_instance">"Okay."</button>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Master Katalin:<br>
You can't let your guard down with your enemy in front of you.<br>
You must always focus during battle.<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest FaeronTrainingGrounds2">Quest</Button>
</body></html>

View File

@@ -1,90 +1,306 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.FaeronTrainingGrounds2;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import instances.AbstractInstance;
import quests.Q10736_ASpecialPower.Q10736_ASpecialPower;
/**
* Fearon Training Grounds Instance Zone.
* @author Sdw
*/
public final class FaeronTrainingGrounds2 extends AbstractInstance
{
// NPCs
private static final int KATALIN = 33943;
private static final int KATALIN_2 = 33945;
// Locations
private static final Location START_LOC = new Location(-74903, 240618, -3584);
private static final Location EXIT_LOC = new Location(-82088, 249880, -3392);
// Misc
private static final int TEMPLATE_ID = 252;
class FTGWorld extends InstanceWorld
{
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final QuestState qs = player.getQuestState(Q10736_ASpecialPower.class.getSimpleName());
if (qs == null)
{
return null;
}
if (event.equals("enter_instance"))
{
enterInstance(player, new FTGWorld(), "FaeronTrainingGrounds2.xml", TEMPLATE_ID);
}
else if (event.equals("exit_instance"))
{
final InstanceWorld world = InstanceManager.getInstance().getPlayerWorld(player);
world.removeAllowed(player.getObjectId());
teleportPlayer(player, EXIT_LOC, 0);
}
return super.onAdvEvent(event, npc, player);
}
public FaeronTrainingGrounds2()
{
super(FaeronTrainingGrounds2.class.getSimpleName());
addStartNpc(KATALIN, KATALIN_2);
addTalkId(KATALIN, KATALIN_2);
}
@Override
public void onEnterInstance(L2PcInstance player, InstanceWorld world, boolean firstEntrance)
{
if (firstEntrance)
{
world.addAllowed(player.getObjectId());
showOnScreenMsg(player, NpcStringId.TALK_TO_MASTER_KATALIN, ExShowScreenMessage.TOP_CENTER, 4500);
}
teleportPlayer(player, START_LOC, world.getInstanceId());
}
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.FaeronTrainingGrounds2;
import com.l2jmobius.gameserver.enums.QuestSound;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import com.l2jmobius.gameserver.network.serverpackets.TutorialShowHtml;
import instances.AbstractInstance;
import quests.Q10736_ASpecialPower.Q10736_ASpecialPower;
/**
* Fearon Training Grounds Instance Zone.
* @author Sdw, malyelfik
*/
public final class FaeronTrainingGrounds2 extends AbstractInstance
{
// NPCs
private static final int KATALIN = 33943;
private static final int KATALIN_2 = 33945;
// Monsters
private static final int FLOATO = 27526;
private static final int FLOATO2 = 27531;
private static final int RATEL = 27527;
// Item
private static final ItemHolder SOULSHOTS_TRAINING = new ItemHolder(1835, 150);
// Locations
private static final Location[] MOB_SPAWNS =
{
new Location(-74760, 240773, -3560),
new Location(-74721, 240513, -3584)
};
// Misc
private static final int TEMPLATE_ID = 252;
private static final double DAMAGE_BY_SKILL = 0.5d; // Percent
public FaeronTrainingGrounds2()
{
addStartNpc(KATALIN, KATALIN_2);
addFirstTalkId(KATALIN_2);
addTalkId(KATALIN, KATALIN_2);
addKillId(FLOATO, FLOATO2, RATEL);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final QuestState qs = player.getQuestState(Q10736_ASpecialPower.class.getSimpleName());
String htmltext = null;
if (qs == null)
{
return htmltext;
}
switch (event)
{
case "enter_instance":
enterInstance(player, npc, TEMPLATE_ID);
break;
case "exit_instance":
finishInstance(player, 0);
break;
case "33945-03.html":
{
if (qs.isCond(6))
{
spawnMonsters(RATEL, player);
showOnScreenMsg(player, NpcStringId.FIGHT_USING_SKILLS, ExShowScreenMessage.TOP_CENTER, 10000);
}
else
{
final int npcId = (qs.isCond(4)) ? FLOATO2 : FLOATO;
spawnMonsters(npcId, player);
showOnScreenMsg(player, NpcStringId.ATTACK_THE_MONSTER, ExShowScreenMessage.TOP_CENTER, 10000);
}
htmltext = event;
break;
}
case "33945-07.html":
{
if (qs.isCond(5))
{
qs.setCond(6, true);
showOnScreenMsg(player, NpcStringId.FIGHT_USING_SKILLS, ExShowScreenMessage.TOP_CENTER, 10000);
spawnMonsters(RATEL, player);
htmltext = event;
}
break;
}
}
return htmltext;
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
final QuestState qs = player.getQuestState(Q10736_ASpecialPower.class.getSimpleName());
String htmltext = getNoQuestMsg(player);
if (qs == null)
{
return htmltext;
}
if ((npc.getId() == KATALIN_2) && qs.isStarted())
{
switch (qs.getCond())
{
case 1:
{
qs.setCond(2, true);
spawnMonsters(FLOATO, player);
htmltext = "33945-01.html";
break;
}
case 2:
case 4:
case 6:
{
htmltext = "33945-02.html";
break;
}
case 3:
{
if (qs.getInt("ss") == 1)
{
spawnMonsters(FLOATO2, player);
qs.setCond(4, true);
htmltext = "33945-05.html";
}
else
{
qs.set("ss", 1);
giveItems(player, SOULSHOTS_TRAINING);
showOnScreenMsg(player, NpcStringId.AUTOMATE_SOULSHOT_AS_SHOWN_IN_THE_TUTORIAL, ExShowScreenMessage.TOP_CENTER, 10000);
player.sendPacket(new TutorialShowHtml(npc.getObjectId(), "..\\L2Text\\QT_003_bullet_01.htm", TutorialShowHtml.LARGE_WINDOW));
htmltext = "33945-04.html";
}
break;
}
case 5:
{
player.sendPacket(new TutorialShowHtml(npc.getObjectId(), "..\\L2Text\\QT_004_skill_01.htm", TutorialShowHtml.LARGE_WINDOW));
htmltext = "33945-06.html";
break;
}
case 7:
{
htmltext = "33945-08.html";
break;
}
}
}
return htmltext;
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
// Check if monster is inside instance
final Instance world = npc.getInstanceWorld();
if (world == null)
{
return super.onKill(npc, killer, isSummon);
}
// Remove monster from instance spawn holder
world.setParameter("Mob" + npc.getScriptValue(), null);
// Handle quest state
final QuestState qs = killer.getQuestState(Q10736_ASpecialPower.class.getSimpleName());
if (qs != null)
{
switch (npc.getId())
{
case FLOATO:
case FLOATO2:
{
if ((qs.isCond(2) || qs.isCond(4)) && onKillQuestChange(killer, qs))
{
despawnMonsters(killer);
if (qs.isCond(5) && (killer.getLevel() < 5))
{
addExpAndSp(killer, 1716, 0);
}
}
break;
}
case RATEL:
{
if (qs.isCond(6) && onKillQuestChange(killer, qs))
{
despawnMonsters(killer);
showOnScreenMsg(killer, NpcStringId.TALK_TO_KATALIN_TO_LEAVE_THE_TRAINING_GROUNDS, ExShowScreenMessage.TOP_CENTER, 10000);
}
break;
}
}
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onSkillSee(L2Npc npc, L2PcInstance player, Skill skill, com.l2jmobius.gameserver.model.L2Object[] targets, boolean isSummon)
{
if (!npc.isDead() && (player.getTarget() == npc))
{
final double dmg = npc.getMaxHp() * DAMAGE_BY_SKILL;
npc.reduceCurrentHp(dmg, player, null);
}
return super.onSkillSee(npc, player, skill, targets, isSummon);
}
/**
* Handle death of training monster. When all monsters are killed, quest cond is increased.
* @param killer player who killed monster
* @param qs quest state of killer
* @return {@code true} when all monsters are killed, otherwise {@code false}
*/
private boolean onKillQuestChange(L2PcInstance killer, QuestState qs)
{
final int value = qs.getMemoStateEx(Q10736_ASpecialPower.KILL_COUNT_VAR) + 1;
if (value >= 2)
{
qs.setCond(qs.getCond() + 1, true);
qs.setMemoStateEx(Q10736_ASpecialPower.KILL_COUNT_VAR, 0);
return true;
}
playSound(killer, QuestSound.ITEMSOUND_QUEST_ITEMGET);
qs.setMemoStateEx(Q10736_ASpecialPower.KILL_COUNT_VAR, value);
qs.getQuest().sendNpcLogList(killer);
return false;
}
/**
* Spawn training monsters inside instance
* @param npcId template id of training monster
* @param player player that owns instance
*/
private void spawnMonsters(int npcId, L2PcInstance player)
{
final Instance world = player.getInstanceWorld();
if (world != null)
{
final StatsSet params = world.getParameters();
for (int i = 0; i < MOB_SPAWNS.length; i++)
{
if (params.getObject("Mob" + i, L2Npc.class) == null)
{
final L2Npc npc = addSpawn(npcId, MOB_SPAWNS[i], false, 0, false, world.getId());
npc.setScriptValue(i);
params.set("Mob" + i, npc);
}
}
}
}
/**
* Despawn training monsters inside instance
* @param player player that owns instance
*/
private void despawnMonsters(L2PcInstance player)
{
final Instance world = player.getInstanceWorld();
if (world != null)
{
final StatsSet params = world.getParameters();
for (int i = 0; i < MOB_SPAWNS.length; i++)
{
final L2Npc mob = params.getObject("Mob" + i, L2Npc.class);
if (mob != null)
{
mob.deleteMe();
params.remove("Mob" + i);
}
}
}
}
public static void main(String[] args)
{
new FaeronTrainingGrounds2();
}
}

View File

@@ -0,0 +1,260 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.FortressDungeon;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import com.l2jmobius.commons.util.CommonUtil;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.enums.QuestSound;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Fort;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.instancezone.InstanceTemplate;
import com.l2jmobius.gameserver.model.quest.QuestState;
import instances.AbstractInstance;
import quests.Q00511_AwlUnderFoot.Q00511_AwlUnderFoot;
/**
* <b>Fortress dungeon</b> instance for quest <b>Awl Under Foot (511)</b>
* @author malyelfik
*/
public final class FortressDungeon extends AbstractInstance
{
// NPCs
private static final Map<Integer, Integer> NPCS = new HashMap<>();
static
{
NPCS.put(35666, 22); // Shanty
NPCS.put(35698, 23); // Southern
NPCS.put(35735, 24); // Hive
NPCS.put(35767, 25); // Valley
NPCS.put(35804, 26); // Ivory
NPCS.put(35835, 27); // Narsell
NPCS.put(35867, 28); // Bayou
NPCS.put(35904, 29); // White Sands
NPCS.put(35936, 30); // Borderland
NPCS.put(35974, 31); // Swamp
NPCS.put(36011, 32); // Archaic
NPCS.put(36043, 33); // Floran
NPCS.put(36081, 34); // Cloud Mountain
NPCS.put(36118, 35); // Tanor
NPCS.put(36149, 36); // Dragonspine
NPCS.put(36181, 37); // Antharas
NPCS.put(36219, 38); // Western
NPCS.put(36257, 39); // Hunter
NPCS.put(36294, 40); // Aaru
NPCS.put(36326, 41); // Demon
NPCS.put(36364, 42); // Monastic
}
// Monsters
private static final int[] RAIDS1 =
{
25572,
25575,
25578
};
private static final int[] RAIDS2 =
{
25579,
25582,
25585,
25588
};
private static final int[] RAIDS3 =
{
25589,
25592,
25593
};
// Item
private static final int MARK = 9797;
// Locations
private static final Location SPAWN_LOC = new Location(53319, 245814, -6576);
// Misc
private static final int MARK_COUNT = 2520;
private static final long REENTER = 24 * 3600000; // 24 hours
private static final Map<Integer, Long> REENETER_HOLDER = new ConcurrentHashMap<>();
public FortressDungeon()
{
// NPCs
addStartNpc(NPCS.keySet());
addTalkId(NPCS.keySet());
// Monsters
addKillId(RAIDS1);
addKillId(RAIDS2);
addKillId(RAIDS3);
// Instance
addInstanceCreatedId(NPCS.values());
addInstanceDestroyId(NPCS.values());
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
final int npcId = npc.getId();
if (NPCS.containsKey(npcId))
{
enterInstance(player, npc, NPCS.get(npcId));
}
return null;
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final Instance world = npc.getInstanceWorld();
if (world != null)
{
if (CommonUtil.contains(RAIDS3, npc.getId()))
{
// Get players with active quest
final List<L2PcInstance> members = new ArrayList<>();
for (L2PcInstance member : world.getPlayers())
{
final QuestState qs = member.getQuestState(Q00511_AwlUnderFoot.class.getSimpleName());
if ((qs != null) && qs.isCond(1))
{
members.add(member);
}
}
// Distribute marks between them
if (!members.isEmpty())
{
final long itemCount = MARK_COUNT / members.size();
for (L2PcInstance member : members)
{
giveItems(member, MARK, itemCount);
playSound(member, QuestSound.ITEMSOUND_QUEST_ITEMGET);
}
}
world.finishInstance();
}
else
{
world.incStatus();
spawnRaid(world);
}
}
return super.onKill(npc, player, isSummon);
}
@Override
public void onInstanceCreated(Instance instance, L2PcInstance player)
{
// Put re-enter for instance
REENETER_HOLDER.put(instance.getTemplateId(), System.currentTimeMillis() + REENTER);
// Schedule spawn of first raid
spawnRaid(instance);
}
@Override
protected boolean validateConditions(List<L2PcInstance> group, L2Npc npc, InstanceTemplate template)
{
final L2PcInstance groupLeader = group.get(0);
final Fort fort = npc.getFort();
if (fort == null)
{
showHtmlFile(groupLeader, "noProperPledge.html");
return false;
}
else if (fort.getFortState() == 0)
{
showHtmlFile(groupLeader, "noContractYet.html");
return false;
}
else if (fort.getFortState() == 2)
{
showHtmlFile(groupLeader, "noCastleContract.html");
return false;
}
else if (REENETER_HOLDER.containsKey(template.getId()))
{
final long time = REENETER_HOLDER.get(template.getId());
if (time > System.currentTimeMillis())
{
showHtmlFile(groupLeader, "enterRestricted.html");
return false;
}
REENETER_HOLDER.remove(template.getId());
}
return true;
}
@Override
public void onInstanceDestroy(Instance instance)
{
// Stop running spawn task
final ScheduledFuture<?> task = instance.getParameters().getObject("spawnTask", ScheduledFuture.class);
if ((task != null) && !task.isDone())
{
task.cancel(true);
}
instance.setParameter("spawnTask", null);
}
/**
* Spawn raid boss according to instance status.
* @param instance instance world where instance should be spawned
*/
private void spawnRaid(Instance instance)
{
final ScheduledFuture<?> spawnTask = ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
// Get template id of raid
final int npcId;
switch (instance.getStatus())
{
case 0:
npcId = RAIDS1[getRandom(RAIDS1.length)];
break;
case 1:
npcId = RAIDS2[getRandom(RAIDS2.length)];
break;
default:
npcId = RAIDS3[getRandom(RAIDS3.length)];
}
// Spawn raid
addSpawn(npcId, SPAWN_LOC, false, 0, false, instance.getId());
// Unset spawn task reference
instance.setParameter("spawnTask", null);
}, 2, TimeUnit.MINUTES);
// Save timer to instance world
instance.setParameter("spawnTask", spawnTask);
}
public static void main(String[] args)
{
new FortressDungeon();
}
}

View File

@@ -0,0 +1,4 @@
<html><body>Training is currently closed.<br>
You can undertake training once every 24 hours with your clan.<br>
If training is closed, check with your clan members to see when the last training session started.
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>
Only a party may enter the camp. Once you begin the training session, you may not attend another one for at least 24 hours.
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Off limits! Lord's orders.<br>
(You cannot enter the camp with a contract related to the castle.)
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>
The fortress is currently in an unsettled state because our relationship with the castle lord must be clearly determined.<br>
(Entry into the camps is only possible after gaining independence from the main castle.)
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>
To enter the Detention Camp, your party must include at least 2 people.
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>
The clan does not possess this fortress.
</body></html>

View File

@@ -1,4 +1,4 @@
<html><body>Kain Van Halter:<br>
You're Ertheia. Child of the wind. Why would you try to kill Giselle all the way out here?<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDeadInstance 33979-02.html">"I didn't know that it was Giselle. She attacked first!"</button>
<html><body>Kain Van Halter:<br>
You're Ertheia. Child of the wind. Why would you try to kill Giselle all the way out here?<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDead 33979-02.html">"I didn't know that it was Giselle. She attacked first!"</button>
</body></html>

View File

@@ -1,5 +1,5 @@
<html><body>Kain Van Halter:<br>
That's not a good reason. The fact that you came all the way here alone is suspicious.<br>
You were after Giselle's life in the first place!<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDeadInstance 33979-03.html">"I have Queen Navari's Mark."</button>
<html><body>Kain Van Halter:<br>
That's not a good reason. The fact that you came all the way here alone is suspicious.<br>
You were after Giselle's life in the first place!<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDead 33979-03.html">"I have Queen Navari's Mark."</button>
</body></html>

View File

@@ -1,6 +1,6 @@
<html><body>Kain Van Halter:<br>
The Queen of Ertheia sent you?<br>
All right, then. Since Giselle became very aggressive after becoming a vampire, I will take your word on your dispute.<br>
But what brings you all the way here? Why were you looking for Giselle? I can't imagine Ertheia having business with her.<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDeadInstance 33979-04.html">"I was looking for you."</button>
</body></html>
<html><body>Kain Van Halter:<br>
The Queen of Ertheia sent you?<br>
All right, then. Since Giselle became very aggressive after becoming a vampire, I will take your word on your dispute.<br>
But what brings you all the way here? Why were you looking for Giselle? I can't imagine Ertheia having business with her.<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDead 33979-04.html">"I was looking for you."</button>
</body></html>

View File

@@ -1,5 +1,5 @@
<html><body>Kain Van Halter:<br>
Me?<br>
What do you want with a wanderer like me? And I don't see why I should even help you. You tried to harm my sister! Good thing I stopped by to check on her.<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDeadInstance 33979-05.html">"It's about the Prophecy Machine."</button>
<html><body>Kain Van Halter:<br>
Me?<br>
What do you want with a wanderer like me? And I don't see why I should even help you. You tried to harm my sister! Good thing I stopped by to check on her.<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDead 33979-05.html">"It's about the Prophecy Machine."</button>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Kain Van Halter:<br>
Prophecy Machine?<br>
What about the Prophecy Machine?<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDead 33979-06.html">"Here, take a look."</button>
</body></html>

View File

@@ -0,0 +1,9 @@
<html><body>Kain Van Halter:<br>
<center><font color="LEVEL">A red river flows...hard frost upon the earth...<br1>
One of half-noble blood,<br1>
descending with the winds to deliver from...<br1>
When joined by one...<br1>
The path will open to the Grail.</font></center><br1>
So why are you showing me this?<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDead 33979-07.html">"I know that you're interested in the Grail."</button>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Kain Van Halter:<br>
I see. Did Karla tell you? So she still remembers me mentioning the Grail that day.<br>
Check this out first.<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDead 33979-08.html">"This?"</button>
</body></html>

View File

@@ -1,6 +1,6 @@
<html><body>Kain Van Halter:<br>
Surprised? I found it while passing Goddard Territory.<br>
This looks similar to the Prophecy Machine that you showed me. It's probably a part of the whole.<br>
And about what's written on your machine... I think I know what it's saying.<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDeadInstance 33979-09.html">"Do tell."</button>
</body></html>
<html><body>Kain Van Halter:<br>
Surprised? I found it while passing Goddard Territory.<br>
This looks similar to the Prophecy Machine that you showed me. It's probably a part of the whole.<br>
And about what's written on your machine... I think I know what it's saying.<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDead 33979-09.html">"Do tell."</button>
</body></html>

View File

@@ -1,6 +1,6 @@
<html><body>Kain Van Halter:<br>
<font color="LEVEL">A red river flows...Hm. I think I can see where this is going.</font><br>
It's talking about this continent. A red river flows...hard frost upon the earth. You see, <font color="LEVEL">Elmore</font> rules over a cold part of the land, which it once shared with Aden as Elmoreden. Now the whole continent is swarming with Shilen's bloody works.<br>
But this part is surprising. When joined by one...the path will open to the Grail. Truly?<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDeadInstance 33979-10.html">"Who is this one?"</button>
</body></html>
<html><body>Kain Van Halter:<br>
<font color="LEVEL">A red river flows...Hm. I think I can see where this is going.</font><br>
It's talking about this continent. A red river flows...hard frost upon the earth. You see, <font color="LEVEL">Elmore</font> rules over a cold part of the land, which it once shared with Aden as Elmoreden. Now the whole continent is swarming with Shilen's bloody works.<br>
But this part is surprising. When joined by one...the path will open to the Grail. Truly?<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDead 33979-10.html">"Who is this one?"</button>
</body></html>

View File

@@ -1,7 +1,8 @@
<html><body>Kain Van Halter:<br>
<font color="LEVEL">One of half-noble blood...</font><br>
Ha! Even the prophecy of Ertheia describes me so, huh? Well, it's right. My mother was a commoner. A tragic farce, to be loved by the king! So here I am, a prince only in name. And descending with the winds to deliver from...yes, that is me. I happened to save Faeron once. <font color="LEVEL">Kain</font> is your man!<br>
The <font color="LEVEL">Grail</font>...if it's the same <font color="LEVEL">Grail</font>, then...anyway, you can read the rest of the prophecy with the fragment that I found, right?<br>
Take it. Your village needs it more than I.<br>Hmm? Wait...<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDeadInstance 33979-11.html">"What?"</button>
</body></html>
<html><body>Kain Van Halter:<br>
<font color="LEVEL">One of half-noble blood...</font><br>
Ha! Even the prophecy of Ertheia describes me so, huh? Well, it's right. My mother was a commoner. A tragic farce, to be loved by the king! So here I am, a prince only in name. And descending with the winds to deliver from...yes, that is me. I happened to save Faeron once. <font color="LEVEL">Kain</font> is your man!<br>
The <font color="LEVEL">Grail</font>...if it's the same <font color="LEVEL">Grail</font>, then...anyway, you can read the rest of the prophecy with the fragment that I found, right?<br>
Take it. Your village needs it more than I.<br>
Hmm? Wait...<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDead spawnWizard">"What?"</button>
</body></html>

View File

@@ -0,0 +1,2 @@
<html><body>Kain Van Halter:<br>
Who is that person standing there?</body></html>

View File

@@ -1,5 +1,5 @@
<html><body>Kain Van Halter:<br>
You trespass on the land of death. Who are you?<br1>
No matter. You threatened Giselle with harm, and you will answer to me!<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h Quest FortressOfTheDeadInstance">Quest</button>
<html><body>Kain Van Halter:<br>
You trespass on the land of death. Who are you?<br1>
No matter. You threatened Giselle with harm, and you will answer to me!<br>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h Quest FortressOfTheDead 33979-01.html">Quest</button>
</body></html>

View File

@@ -0,0 +1,169 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.FortressOfTheDead;
import com.l2jmobius.gameserver.enums.Movie;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import instances.AbstractInstance;
import quests.Q10752_WindsOfFateAPromise.Q10752_WindsOfFateAPromise;
/**
* Fortress of the Dead instance zone.
* @author Gladicek
*/
public final class FortressOfTheDead extends AbstractInstance
{
// NPCs
private static final int BROKEN_BOOKSHELF = 31526;
private static final int VAMPIRIC_SOLDIER = 19567;
private static final int VON_HELLMAN = 19566;
private static final int MYSTERIOUS_WIZARD = 33980;
private static final int KAIN_VAN_HALTER = 33979;
// Items
private static final int KAIN_PROPHECY_MACHINE_FRAGMENT = 39538;
// Location
private static final Location VON_HELLMAN_LOC = new Location(57963, -28676, 568, 49980);
private static final Location MYSTERIOUS_WIZARD_LOC = new Location(57982, -28645, 568);
private static final Location KAIN_VAN_HALTER_LOC = new Location(57963, -28676, 568, 49980);
// Misc
private static final int TEMPLATE_ID = 254;
public FortressOfTheDead()
{
addStartNpc(BROKEN_BOOKSHELF);
addFirstTalkId(KAIN_VAN_HALTER);
addTalkId(BROKEN_BOOKSHELF, KAIN_VAN_HALTER, MYSTERIOUS_WIZARD);
addKillId(VAMPIRIC_SOLDIER, VON_HELLMAN);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = null;
if (event.equals("enterInstance"))
{
enterInstance(player, npc, TEMPLATE_ID);
}
else
{
final Instance world = npc.getInstanceWorld();
if (isFotDInstance(world))
{
switch (event)
{
case "33979-01.html":
case "33979-02.html":
case "33979-03.html":
case "33979-04.html":
case "33979-05.html":
case "33979-06.html":
case "33979-07.html":
case "33979-08.html":
case "33979-09.html":
case "33979-10.html":
{
htmltext = event;
break;
}
case "exitInstance":
{
world.finishInstance(0);
break;
}
case "vampire_dead":
{
addSpawn(VON_HELLMAN, VON_HELLMAN_LOC, false, 0, false, world.getId());
break;
}
case "hellman_dead":
{
addSpawn(KAIN_VAN_HALTER, KAIN_VAN_HALTER_LOC, false, 0, false, world.getId());
break;
}
case "spawnWizard":
{
showOnScreenMsg(player, NpcStringId.TALK_TO_THE_MYSTERIOUS_WIZARD, ExShowScreenMessage.TOP_CENTER, 5000);
final L2Npc wizzard = addSpawn(MYSTERIOUS_WIZARD, MYSTERIOUS_WIZARD_LOC, true, 0, false, world.getId());
wizzard.setSummoner(player);
wizzard.setTitle(player.getAppearance().getVisibleName());
wizzard.broadcastInfo();
htmltext = "33979-11.html";
break;
}
case "endCinematic":
{
final QuestState qs = player.getQuestState(Q10752_WindsOfFateAPromise.class.getSimpleName());
if ((qs != null) && qs.isCond(8))
{
qs.setCond(9, true);
giveItems(player, KAIN_PROPHECY_MACHINE_FRAGMENT, 1);
}
world.getNpc(KAIN_VAN_HALTER).deleteMe();
world.getNpc(MYSTERIOUS_WIZARD).deleteMe();
playMovie(player, Movie.ERT_QUEST_B);
startQuestTimer("exitInstance", 25000, npc, player);
break;
}
}
}
}
return htmltext;
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final Instance world = npc.getInstanceWorld();
if (isFotDInstance(world))
{
if (npc.getId() == VAMPIRIC_SOLDIER)
{
if (world.getAliveNpcs(VAMPIRIC_SOLDIER).isEmpty())
{
startQuestTimer("vampire_dead", 3000, npc, player);
}
}
else if (npc.getId() == VON_HELLMAN)
{
npc.deleteMe();
playMovie(player, Movie.ERT_QUEST_A);
startQuestTimer("hellman_dead", 6000, npc, player);
}
}
return super.onKill(npc, player, isSummon);
}
private boolean isFotDInstance(Instance instance)
{
return (instance != null) && (instance.getTemplateId() == TEMPLATE_ID);
}
public static void main(String[] args)
{
new FortressOfTheDead();
}
}

View File

@@ -1,4 +0,0 @@
<html><body>Kain Van Halter:<br>
Prophecy Machine?<br>What about the Prophecy Machine?<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDeadInstance 33979-06.html">"Here, take a look."</button>
</body></html>

View File

@@ -1,7 +0,0 @@
<html><body>Kain Van Halter:<br>
<center><font color="LEVEL">A red river flows...hard frost upon the earth...<br1>
One of half-noble blood,<br1>descending with the winds to deliver from...<br1>
When joined by one...<br1>The path will open to the Grail.</font></center><br1>
So why are you showing me this?<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDeadInstance 33979-07.html">"I know that you're interested in the Grail."</button>
</body></html>

View File

@@ -1,4 +0,0 @@
<html><body>Kain Van Halter:<br>
I see. Did Karla tell you? So she still remembers me mentioning the Grail that day.<br>
Check this out first.<br><Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDeadInstance 33979-08.html">"This?"</button>
</body></html>

View File

@@ -1,3 +0,0 @@
<html><body>Kain Van Halter:<br>
Who is that person standing there?
</body></html>

View File

@@ -1,4 +0,0 @@
<html><body>Mysterious Wizard:<br>
I was just worried about you.<br>I guess I was worried that a small Ertheia was led by the souls of the dead to somewhere. <br>
But it seems I picked the wrong time.<br><Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDeadInstance exit_instance">"What do you mean?"</button>
</body></html>

View File

@@ -1,5 +0,0 @@
<html><body>Mysterious Wizard:<br>
It seems nothing happened.<br>
Did you find the person you were looking for?<br>
<Button ALIGN=LEFT ICON="Normal" action="bypass -h Quest FortressOfTheDeadInstance">Why did you come here?"</button>
</body></html>

View File

@@ -1,232 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package instances.FortressOfTheDeadInstance;
import com.l2jmobius.gameserver.instancemanager.InstanceManager;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.instancezone.InstanceWorld;
import com.l2jmobius.gameserver.model.quest.QuestState;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.ExQuestNpcLogList;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import instances.AbstractInstance;
import quests.Q10752_WindsOfFateAPromise.Q10752_WindsOfFateAPromise;
/**
* Fortress of The Dead Instance Zone.
* @author Gigi
*/
public final class FortressOfTheDeadInstance extends AbstractInstance
{
// NPCs
private static final int KAIN_VAN_HALTER = 33979;
private static final int MYSTERIOUS_WIZARD_2 = 33980;
// Monsters
private static final int VON_HELLMANN = 19566;
private static final int VAMPIRIC_SOLDIER = 19567;
// Locations
private static final Location START_LOC = new Location(57972, -28955, 568);
private static final Location EXIT_LOC = new Location(52084, -51317, -3096);
// Misc
private static final int TEMPLATE_ID = 254;
private static final int KAINS_PROPHECY_MACHINE_FRAGMENT = 39538;
private static final int VAMPIRIC_SOLDIER_KILL = 4;
private static final int VON_HELLMANN_KILL = 1;
class FTODWorld extends InstanceWorld
{
}
public FortressOfTheDeadInstance()
{
super(FortressOfTheDeadInstance.class.getSimpleName());
addTalkId(KAIN_VAN_HALTER, MYSTERIOUS_WIZARD_2);
addFirstTalkId(KAIN_VAN_HALTER, MYSTERIOUS_WIZARD_2);
addKillId(VAMPIRIC_SOLDIER, VON_HELLMANN);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
final QuestState qs = player.getQuestState(Q10752_WindsOfFateAPromise.class.getSimpleName());
final InstanceWorld tmpworld = InstanceManager.getInstance().getPlayerWorld(player);
if (qs == null)
{
return null;
}
String htmltext = null;
switch (event)
{
case "33979-02.html":
case "33979-03.html":
case "33979-04.html":
case "33979-05.html":
case "33979-06.html":
case "33979-07.html":
case "33979-08.html":
case "33979-09.html":
case "33979-10.html":
{
htmltext = event;
break;
}
case "33979-11.html":
{
if (tmpworld instanceof FTODWorld)
{
final FTODWorld world = (FTODWorld) tmpworld;
showOnScreenMsg(player, NpcStringId.TALK_TO_THE_MYSTERIOUS_WIZARD, ExShowScreenMessage.TOP_CENTER, 10000);
L2Npc wizard = addSpawn(MYSTERIOUS_WIZARD_2, npc.getX() + getRandom(-50, 50), npc.getY() + getRandom(-50, 50), npc.getZ(), npc.getHeading(), true, 60000, false, world.getInstanceId());
wizard.setTitle(player.getName());
wizard.setIsRunning(false);
wizard.broadcastInfo();
npc.deleteMe();
}
htmltext = event;
break;
}
case "exit_instance":
{
npc.deleteMe();
player.showQuestMovie(111);
giveItems(player, KAINS_PROPHECY_MACHINE_FRAGMENT, 1);
qs.setCond(9, true);
startQuestTimer("TELEPORT", 27000, npc, player);
break;
}
case "enter_instance":
{
enterInstance(player, new FTODWorld(), "FortressOfTheDead.xml", TEMPLATE_ID);
qs.set(Integer.toString(VAMPIRIC_SOLDIER), 0);
break;
}
case "SPAWN_HELLMANN":
{
if (tmpworld instanceof FTODWorld)
{
final FTODWorld world = (FTODWorld) tmpworld;
L2Npc hellmann = addSpawn(VON_HELLMANN, 57963, -28676, 568, 49980, false, 300000, false, world.getInstanceId());
addAttackDesire(hellmann, player);
}
break;
}
case "SPAWN_KAIN_VAN_HALTER":
{
if (tmpworld instanceof FTODWorld)
{
final FTODWorld world = (FTODWorld) tmpworld;
addSpawn(KAIN_VAN_HALTER, 57963, -28676, 568, 49980, false, 300000, false, world.getInstanceId());
}
break;
}
case "TELEPORT":
{
tmpworld.removeAllowed(player.getObjectId());
teleportPlayer(player, EXIT_LOC, 0);
break;
}
}
return htmltext;
}
@Override
public final String onTalk(L2Npc npc, L2PcInstance player)
{
String htmltext = getNoQuestMsg(player);
switch (npc.getId())
{
case KAIN_VAN_HALTER:
{
htmltext = "33979-01.html";
break;
}
case MYSTERIOUS_WIZARD_2:
{
htmltext = "33980-01.html";
break;
}
}
return htmltext;
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
return npc.getId() + ".htm";
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final QuestState qs = player.getQuestState(Q10752_WindsOfFateAPromise.class.getSimpleName());
if ((qs != null) && (qs.isCond(8)))
{
switch (npc.getId())
{
case VAMPIRIC_SOLDIER:
{
int kills = qs.getInt(Integer.toString(VAMPIRIC_SOLDIER));
if (kills < VAMPIRIC_SOLDIER_KILL)
{
kills++;
qs.set(Integer.toString(VAMPIRIC_SOLDIER), kills);
}
break;
}
case VON_HELLMANN:
{
int kills = qs.getInt(Integer.toString(VON_HELLMANN));
if (kills < VON_HELLMANN_KILL)
{
kills++;
qs.set(Integer.toString(VON_HELLMANN), kills);
}
break;
}
}
final ExQuestNpcLogList log = new ExQuestNpcLogList(getId());
log.addNpc(VAMPIRIC_SOLDIER, qs.getInt(Integer.toString(VAMPIRIC_SOLDIER)));
log.addNpc(VON_HELLMANN, qs.getInt(Integer.toString(VON_HELLMANN)));
if (qs.getInt(Integer.toString(VAMPIRIC_SOLDIER)) >= VAMPIRIC_SOLDIER_KILL)
{
qs.unset(Integer.toString(VAMPIRIC_SOLDIER));
startQuestTimer("SPAWN_HELLMANN", 8000, npc, player);
}
if (qs.getInt(Integer.toString(VON_HELLMANN)) >= VON_HELLMANN_KILL)
{
npc.deleteMe();
qs.unset(Integer.toString(VON_HELLMANN));
player.showQuestMovie(110);
startQuestTimer("SPAWN_KAIN_VAN_HALTER", 5000, npc, player);
}
}
return super.onKill(npc, player, isSummon);
}
@Override
public void onEnterInstance(L2PcInstance player, InstanceWorld world, boolean firstEntrance)
{
if (firstEntrance)
{
world.addAllowed(player.getObjectId());
}
teleportPlayer(player, START_LOC, world.getInstanceId());
}
}

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