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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user