Merged with released L2J-Unity files.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
337
trunk/dist/game/data/scripts/instances/BaylorWarzone/BaylorWarzone.java
vendored
Normal file
337
trunk/dist/game/data/scripts/instances/BaylorWarzone/BaylorWarzone.java
vendored
Normal 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();
|
||||
}
|
||||
}
|
3
trunk/dist/game/data/scripts/instances/BaylorWarzone/condNoParty.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/BaylorWarzone/condNoParty.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Crystal Prison Entrance Portal:<br>
|
||||
You must be in a party to enter.
|
||||
</body></html>
|
3
trunk/dist/game/data/scripts/instances/BaylorWarzone/condNoPartyLeader.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/BaylorWarzone/condNoPartyLeader.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Crystal Prison Entrance Portal:<br>
|
||||
The leader of the party should try to enter.
|
||||
</body></html>
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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 "";
|
||||
}
|
||||
}
|
449
trunk/dist/game/data/scripts/instances/ChambersOfDelusion/ChamberOfDelusion.java
vendored
Normal file
449
trunk/dist/game/data/scripts/instances/ChambersOfDelusion/ChamberOfDelusion.java
vendored
Normal 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();
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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>
|
@@ -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>
|
@@ -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
@@ -1,3 +0,0 @@
|
||||
<html><body>Oracle Guide:<br>
|
||||
I can't speak with you, while bleeding.
|
||||
</body></html>
|
File diff suppressed because it is too large
Load Diff
@@ -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();
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
4
trunk/dist/game/data/scripts/instances/EvasHiddenSpace/31281-01.html
vendored
Normal file
4
trunk/dist/game/data/scripts/instances/EvasHiddenSpace/31281-01.html
vendored
Normal 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>
|
3
trunk/dist/game/data/scripts/instances/EvasHiddenSpace/31281.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/EvasHiddenSpace/31281.html
vendored
Normal 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>
|
5
trunk/dist/game/data/scripts/instances/EvasHiddenSpace/33686.html
vendored
Normal file
5
trunk/dist/game/data/scripts/instances/EvasHiddenSpace/33686.html
vendored
Normal 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>
|
92
trunk/dist/game/data/scripts/instances/EvasHiddenSpace/EvasHiddenSpace.java
vendored
Normal file
92
trunk/dist/game/data/scripts/instances/EvasHiddenSpace/EvasHiddenSpace.java
vendored
Normal 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();
|
||||
}
|
||||
}
|
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33165-01.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33165-01.html
vendored
Normal 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>
|
@@ -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>
|
@@ -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>
|
6
trunk/dist/game/data/scripts/instances/EvilIncubator/33170-03.html
vendored
Normal file
6
trunk/dist/game/data/scripts/instances/EvilIncubator/33170-03.html
vendored
Normal 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>
|
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33170-04.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33170-04.html
vendored
Normal 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>
|
5
trunk/dist/game/data/scripts/instances/EvilIncubator/33170-05.html
vendored
Normal file
5
trunk/dist/game/data/scripts/instances/EvilIncubator/33170-05.html
vendored
Normal 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>
|
4
trunk/dist/game/data/scripts/instances/EvilIncubator/33170-06.html
vendored
Normal file
4
trunk/dist/game/data/scripts/instances/EvilIncubator/33170-06.html
vendored
Normal 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>
|
4
trunk/dist/game/data/scripts/instances/EvilIncubator/33170-07.html
vendored
Normal file
4
trunk/dist/game/data/scripts/instances/EvilIncubator/33170-07.html
vendored
Normal 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>
|
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33170-08.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33170-08.html
vendored
Normal 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>
|
@@ -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>
|
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33171-01.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33171-01.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Priest Alice:<br>
|
||||
Speak with Adolph first.
|
||||
</body></html>
|
@@ -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>
|
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33171-03.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33171-03.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Alice:<br>
|
||||
This is dangerous. Quit fidgeting and concentrate.
|
||||
</body></html>
|
@@ -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>
|
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33172-01.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33172-01.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Officer Barton:<br>
|
||||
Speak with Adolph.
|
||||
</body></html>
|
@@ -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>
|
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33172-03.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33172-03.html
vendored
Normal 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>
|
@@ -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>
|
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33173-01.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33173-01.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Sniper Hayuk:<br>
|
||||
You don't want to talk to me, you want Captain Adolph.
|
||||
</body></html>
|
4
trunk/dist/game/data/scripts/instances/EvilIncubator/33173-02.html
vendored
Normal file
4
trunk/dist/game/data/scripts/instances/EvilIncubator/33173-02.html
vendored
Normal 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>
|
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33173-03.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33173-03.html
vendored
Normal 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>
|
@@ -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>
|
2
trunk/dist/game/data/scripts/instances/EvilIncubator/33174-01.html
vendored
Normal file
2
trunk/dist/game/data/scripts/instances/EvilIncubator/33174-01.html
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
<html><body>Magus Eliyah:<br>
|
||||
Instead of talking to me, perhaps you should speak with Adolph first?</body></html>
|
@@ -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>
|
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33174-03.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/EvilIncubator/33174-03.html
vendored
Normal 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>
|
@@ -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>
|
566
trunk/dist/game/data/scripts/instances/EvilIncubator/EvilIncubator.java
vendored
Normal file
566
trunk/dist/game/data/scripts/instances/EvilIncubator/EvilIncubator.java
vendored
Normal 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();
|
||||
}
|
||||
}
|
3
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-01.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-01.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Magister Ayanthe:<br>
|
||||
The monsters are coming. Concentrate and attack!
|
||||
</body></html>
|
4
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-02.html
vendored
Normal file
4
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-02.html
vendored
Normal 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>
|
4
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-03.html
vendored
Normal file
4
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-03.html
vendored
Normal 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>
|
7
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-04.html
vendored
Normal file
7
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-04.html
vendored
Normal 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>
|
3
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-05.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-05.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><head><body>Magister Ayanthe:<br>
|
||||
All right, now your training begins again!
|
||||
</body></html>
|
6
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-06.html
vendored
Normal file
6
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-06.html
vendored
Normal 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>
|
3
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-07.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-07.html
vendored
Normal 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>
|
4
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-08.html
vendored
Normal file
4
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944-08.html
vendored
Normal 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>
|
5
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944.html
vendored
Normal file
5
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds1/33944.html
vendored
Normal 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>
|
@@ -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();
|
||||
}
|
||||
}
|
4
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-01.html
vendored
Normal file
4
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-01.html
vendored
Normal 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>
|
4
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-02.html
vendored
Normal file
4
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-02.html
vendored
Normal 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>
|
4
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-03.html
vendored
Normal file
4
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-03.html
vendored
Normal 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>
|
7
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-04.html
vendored
Normal file
7
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-04.html
vendored
Normal 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>
|
3
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-05.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-05.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>Master Katalin:<br>
|
||||
Okay, here we go again.
|
||||
</body></html>
|
7
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-06.html
vendored
Normal file
7
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-06.html
vendored
Normal 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>
|
3
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-07.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-07.html
vendored
Normal 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>
|
5
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-08.html
vendored
Normal file
5
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945-08.html
vendored
Normal 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>
|
5
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945.html
vendored
Normal file
5
trunk/dist/game/data/scripts/instances/FaeronTrainingGrounds2/33945.html
vendored
Normal 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>
|
@@ -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();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
260
trunk/dist/game/data/scripts/instances/FortressDungeon/FortressDungeon.java
vendored
Normal file
260
trunk/dist/game/data/scripts/instances/FortressDungeon/FortressDungeon.java
vendored
Normal 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();
|
||||
}
|
||||
}
|
4
trunk/dist/game/data/scripts/instances/FortressDungeon/enterRestricted.html
vendored
Normal file
4
trunk/dist/game/data/scripts/instances/FortressDungeon/enterRestricted.html
vendored
Normal 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>
|
3
trunk/dist/game/data/scripts/instances/FortressDungeon/hasReenter.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/FortressDungeon/hasReenter.html
vendored
Normal 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>
|
3
trunk/dist/game/data/scripts/instances/FortressDungeon/noCastleContract.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/FortressDungeon/noCastleContract.html
vendored
Normal 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>
|
4
trunk/dist/game/data/scripts/instances/FortressDungeon/noContractYet.html
vendored
Normal file
4
trunk/dist/game/data/scripts/instances/FortressDungeon/noContractYet.html
vendored
Normal 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>
|
3
trunk/dist/game/data/scripts/instances/FortressDungeon/noParty.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/FortressDungeon/noParty.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>
|
||||
To enter the Detention Camp, your party must include at least 2 people.
|
||||
</body></html>
|
3
trunk/dist/game/data/scripts/instances/FortressDungeon/noProperPledge.html
vendored
Normal file
3
trunk/dist/game/data/scripts/instances/FortressDungeon/noProperPledge.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><body>
|
||||
The clan does not possess this fortress.
|
||||
</body></html>
|
@@ -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>
|
@@ -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>
|
@@ -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>
|
@@ -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>
|
5
trunk/dist/game/data/scripts/instances/FortressOfTheDead/33979-05.html
vendored
Normal file
5
trunk/dist/game/data/scripts/instances/FortressOfTheDead/33979-05.html
vendored
Normal 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>
|
9
trunk/dist/game/data/scripts/instances/FortressOfTheDead/33979-06.html
vendored
Normal file
9
trunk/dist/game/data/scripts/instances/FortressOfTheDead/33979-06.html
vendored
Normal 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>
|
5
trunk/dist/game/data/scripts/instances/FortressOfTheDead/33979-07.html
vendored
Normal file
5
trunk/dist/game/data/scripts/instances/FortressOfTheDead/33979-07.html
vendored
Normal 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>
|
@@ -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>
|
@@ -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>
|
@@ -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>
|
2
trunk/dist/game/data/scripts/instances/FortressOfTheDead/33979-11.html
vendored
Normal file
2
trunk/dist/game/data/scripts/instances/FortressOfTheDead/33979-11.html
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
<html><body>Kain Van Halter:<br>
|
||||
Who is that person standing there?</body></html>
|
@@ -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>
|
169
trunk/dist/game/data/scripts/instances/FortressOfTheDead/FortressOfTheDead.java
vendored
Normal file
169
trunk/dist/game/data/scripts/instances/FortressOfTheDead/FortressOfTheDead.java
vendored
Normal 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();
|
||||
}
|
||||
}
|
@@ -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>
|
@@ -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>
|
@@ -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>
|
@@ -1,3 +0,0 @@
|
||||
<html><body>Kain Van Halter:<br>
|
||||
Who is that person standing there?
|
||||
</body></html>
|
@@ -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>
|
@@ -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>
|
@@ -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
Reference in New Issue
Block a user