|
@@ -18,89 +18,209 @@
|
|
|
*/
|
|
|
package com.l2jserver.gameserver.model.actor.instance;
|
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
|
|
|
-import javolution.util.FastList;
|
|
|
-
|
|
|
+import com.l2jserver.gameserver.ThreadPoolManager;
|
|
|
import com.l2jserver.gameserver.model.actor.L2Attackable;
|
|
|
import com.l2jserver.gameserver.model.actor.L2Character;
|
|
|
-import com.l2jserver.gameserver.model.actor.L2Trap;
|
|
|
+import com.l2jserver.gameserver.model.actor.L2Npc;
|
|
|
+import com.l2jserver.gameserver.model.actor.knownlist.TrapKnownList;
|
|
|
+import com.l2jserver.gameserver.model.actor.tasks.npc.trap.TrapTask;
|
|
|
+import com.l2jserver.gameserver.model.actor.tasks.npc.trap.TrapTriggerTask;
|
|
|
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
|
|
|
+import com.l2jserver.gameserver.model.items.L2Weapon;
|
|
|
+import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
|
|
|
import com.l2jserver.gameserver.model.olympiad.OlympiadGameManager;
|
|
|
import com.l2jserver.gameserver.model.quest.Quest;
|
|
|
import com.l2jserver.gameserver.model.quest.Quest.TrapAction;
|
|
|
import com.l2jserver.gameserver.model.skills.L2Skill;
|
|
|
import com.l2jserver.gameserver.model.zone.ZoneId;
|
|
|
import com.l2jserver.gameserver.network.SystemMessageId;
|
|
|
+import com.l2jserver.gameserver.network.serverpackets.AbstractNpcInfo.TrapInfo;
|
|
|
+import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
|
|
|
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
|
|
|
+import com.l2jserver.gameserver.taskmanager.DecayTaskManager;
|
|
|
|
|
|
-public class L2TrapInstance extends L2Trap
|
|
|
+/**
|
|
|
+ * Trap instance.
|
|
|
+ * @author Zoey76
|
|
|
+ */
|
|
|
+public final class L2TrapInstance extends L2Npc
|
|
|
{
|
|
|
- private L2PcInstance _owner;
|
|
|
- private int _level;
|
|
|
+ private static final int TICK = 1000; // 1s
|
|
|
+ private boolean _hasLifeTime;
|
|
|
private boolean _isInArena = false;
|
|
|
- private final List<Integer> _playersWhoDetectedMe = new FastList<>();
|
|
|
+ private boolean _isTriggered;
|
|
|
+ private final int _lifeTime;
|
|
|
+ private L2PcInstance _owner;
|
|
|
+ private final List<Integer> _playersWhoDetectedMe = new ArrayList<>();
|
|
|
+ private L2Skill _skill;
|
|
|
+ private int _remainingTime;
|
|
|
|
|
|
- /**
|
|
|
- * @param objectId
|
|
|
- * @param template
|
|
|
- * @param owner
|
|
|
- * @param lifeTime
|
|
|
- * @param skill
|
|
|
- */
|
|
|
- public L2TrapInstance(int objectId, L2NpcTemplate template, L2PcInstance owner, int lifeTime, L2Skill skill)
|
|
|
+ public L2TrapInstance(int objectId, L2NpcTemplate template, int instanceId, int lifeTime)
|
|
|
{
|
|
|
- super(objectId, template, lifeTime, skill);
|
|
|
+ super(objectId, template);
|
|
|
setInstanceType(InstanceType.L2TrapInstance);
|
|
|
+ setInstanceId(instanceId);
|
|
|
+ setName(template.getName());
|
|
|
+ setIsInvul(false);
|
|
|
|
|
|
- setInstanceId(owner.getInstanceId());
|
|
|
-
|
|
|
- _owner = owner;
|
|
|
- _level = owner.getLevel();
|
|
|
+ _owner = null;
|
|
|
+ _isTriggered = false;
|
|
|
+ // TODO: Manage this properly when NPC templates are complete and in XML.
|
|
|
+ for (L2Skill skill : template.getSkills().values())
|
|
|
+ {
|
|
|
+ _skill = skill; // Last skill
|
|
|
+ }
|
|
|
+ _hasLifeTime = lifeTime >= 0;
|
|
|
+ _lifeTime = lifeTime != 0 ? lifeTime : 30000;
|
|
|
+ _remainingTime = _lifeTime;
|
|
|
+ if (_skill != null)
|
|
|
+ {
|
|
|
+ ThreadPoolManager.getInstance().scheduleGeneral(new TrapTask(this), TICK);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- public L2TrapInstance(int objectId, L2NpcTemplate template, int instanceId, int lifeTime, L2Skill skill)
|
|
|
+ public L2TrapInstance(int objectId, L2NpcTemplate template, L2PcInstance owner, int lifeTime)
|
|
|
{
|
|
|
- super(objectId, template, lifeTime, skill);
|
|
|
+ super(objectId, template);
|
|
|
setInstanceType(InstanceType.L2TrapInstance);
|
|
|
+ setInstanceId(owner.getInstanceId());
|
|
|
+ setName(template.getName());
|
|
|
+ setIsInvul(false);
|
|
|
|
|
|
- setInstanceId(instanceId);
|
|
|
-
|
|
|
- _owner = null;
|
|
|
- if (skill != null)
|
|
|
+ _owner = owner;
|
|
|
+ _isTriggered = false;
|
|
|
+ // TODO: Manage this properly when NPC templates are complete and in XML.
|
|
|
+ for (L2Skill skill : template.getSkills().values())
|
|
|
{
|
|
|
- _level = skill.getLevel();
|
|
|
+ _skill = skill; // Last skill
|
|
|
}
|
|
|
- else
|
|
|
+ _hasLifeTime = lifeTime >= 0;
|
|
|
+ _lifeTime = lifeTime != 0 ? lifeTime : 30000;
|
|
|
+ _remainingTime = getLifeTime();
|
|
|
+ if (_skill != null)
|
|
|
{
|
|
|
- _level = 1;
|
|
|
+ ThreadPoolManager.getInstance().scheduleGeneral(new TrapTask(this), TICK);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public int getLevel()
|
|
|
+ public void broadcastPacket(L2GameServerPacket mov)
|
|
|
{
|
|
|
- return _level;
|
|
|
+ for (L2PcInstance player : getKnownList().getKnownPlayers().values())
|
|
|
+ {
|
|
|
+ if ((player != null) && (_isTriggered || canBeSeen(player)))
|
|
|
+ {
|
|
|
+ player.sendPacket(mov);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public L2PcInstance getOwner()
|
|
|
+ public void broadcastPacket(L2GameServerPacket mov, int radiusInKnownlist)
|
|
|
{
|
|
|
- return _owner;
|
|
|
+ for (L2PcInstance player : getKnownList().getKnownPlayers().values())
|
|
|
+ {
|
|
|
+ if ((player != null) && isInsideRadius(player, radiusInKnownlist, false, false) && (_isTriggered || canBeSeen(player)))
|
|
|
+ {
|
|
|
+ player.sendPacket(mov);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public L2PcInstance getActingPlayer()
|
|
|
+ /**
|
|
|
+ * Verify if the character can see the trap.
|
|
|
+ * @param cha the character to verify
|
|
|
+ * @return {@code true} if the character can see the trap, {@code false} otherwise
|
|
|
+ */
|
|
|
+ public boolean canBeSeen(L2Character cha)
|
|
|
{
|
|
|
- return _owner;
|
|
|
+ if ((cha != null) && _playersWhoDetectedMe.contains(cha.getObjectId()))
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((_owner == null) || (cha == null))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (cha == _owner)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cha instanceof L2PcInstance)
|
|
|
+ {
|
|
|
+ // observers can't see trap
|
|
|
+ if (((L2PcInstance) cha).inObserverMode())
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // olympiad competitors can't see trap
|
|
|
+ if (_owner.isInOlympiadMode() && ((L2PcInstance) cha).isInOlympiadMode() && (((L2PcInstance) cha).getOlympiadSide() != _owner.getOlympiadSide()))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_isInArena)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_owner.isInParty() && cha.isInParty() && (_owner.getParty().getLeaderObjectId() == cha.getParty().getLeaderObjectId()))
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public void onSpawn()
|
|
|
+ public boolean checkTarget(L2Character target)
|
|
|
{
|
|
|
- super.onSpawn();
|
|
|
- _isInArena = isInsideZone(ZoneId.PVP) && !isInsideZone(ZoneId.SIEGE);
|
|
|
- _playersWhoDetectedMe.clear();
|
|
|
+ if (!L2Skill.checkForAreaOffensiveSkills(this, target, _skill, _isInArena))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // observers
|
|
|
+ if ((target instanceof L2PcInstance) && ((L2PcInstance) target).inObserverMode())
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // olympiad own team and their summons not attacked
|
|
|
+ if ((_owner != null) && _owner.isInOlympiadMode())
|
|
|
+ {
|
|
|
+ final L2PcInstance player = target.getActingPlayer();
|
|
|
+ if ((player != null) && player.isInOlympiadMode() && (player.getOlympiadSide() == _owner.getOlympiadSide()))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_isInArena)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // trap owned by players not attack non-flagged players
|
|
|
+ if (_owner != null)
|
|
|
+ {
|
|
|
+ if (target instanceof L2Attackable)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ final L2PcInstance player = target.getActingPlayer();
|
|
|
+ if ((player == null) || ((player.getPvpFlag() == 0) && (player.getKarma() == 0)))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -115,28 +235,94 @@ public class L2TrapInstance extends L2Trap
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void unSummon()
|
|
|
+ public L2PcInstance getActingPlayer()
|
|
|
{
|
|
|
- if (_owner != null)
|
|
|
- {
|
|
|
- _owner.setTrap(null);
|
|
|
- _owner = null;
|
|
|
- }
|
|
|
- super.unSummon();
|
|
|
+ return _owner;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
+ public L2Weapon getActiveWeaponItem()
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
public int getKarma()
|
|
|
{
|
|
|
return _owner != null ? _owner.getKarma() : 0;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
+ public TrapKnownList getKnownList()
|
|
|
+ {
|
|
|
+ return (TrapKnownList) super.getKnownList();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get the owner of this trap.
|
|
|
+ * @return the owner
|
|
|
+ */
|
|
|
+ public L2PcInstance getOwner()
|
|
|
+ {
|
|
|
+ return _owner;
|
|
|
+ }
|
|
|
+
|
|
|
public byte getPvpFlag()
|
|
|
{
|
|
|
return _owner != null ? _owner.getPvpFlag() : 0;
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public L2ItemInstance getSecondaryWeaponInstance()
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public L2Weapon getSecondaryWeaponItem()
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public L2Skill getSkill()
|
|
|
+ {
|
|
|
+ return _skill;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void initKnownList()
|
|
|
+ {
|
|
|
+ setKnownList(new TrapKnownList(this));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean isAutoAttackable(L2Character attacker)
|
|
|
+ {
|
|
|
+ return !canBeSeen(attacker);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean isTrap()
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Checks is triggered
|
|
|
+ * @return True if trap is triggered.
|
|
|
+ */
|
|
|
+ public boolean isTriggered()
|
|
|
+ {
|
|
|
+ return _isTriggered;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onSpawn()
|
|
|
+ {
|
|
|
+ super.onSpawn();
|
|
|
+ _isInArena = isInsideZone(ZoneId.PVP) && !isInsideZone(ZoneId.SIEGE);
|
|
|
+ _playersWhoDetectedMe.clear();
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public void sendDamageMessage(L2Character target, int damage, boolean mcrit, boolean pcrit, boolean miss)
|
|
|
{
|
|
@@ -150,82 +336,44 @@ public class L2TrapInstance extends L2Trap
|
|
|
OlympiadGameManager.getInstance().notifyCompetitorDamage(getOwner(), damage);
|
|
|
}
|
|
|
|
|
|
- final SystemMessage sm;
|
|
|
-
|
|
|
if (target.isInvul() && !(target instanceof L2NpcInstance))
|
|
|
{
|
|
|
- sm = SystemMessage.getSystemMessage(SystemMessageId.ATTACK_WAS_BLOCKED);
|
|
|
+ _owner.sendPacket(SystemMessageId.ATTACK_WAS_BLOCKED);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- sm = SystemMessage.getSystemMessage(SystemMessageId.C1_DONE_S3_DAMAGE_TO_C2);
|
|
|
+ final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_DONE_S3_DAMAGE_TO_C2);
|
|
|
sm.addCharName(this);
|
|
|
sm.addCharName(target);
|
|
|
sm.addNumber(damage);
|
|
|
+ _owner.sendPacket(sm);
|
|
|
}
|
|
|
-
|
|
|
- _owner.sendPacket(sm);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public boolean canSee(L2Character cha)
|
|
|
+ public void sendInfo(L2PcInstance activeChar)
|
|
|
{
|
|
|
- if ((cha != null) && _playersWhoDetectedMe.contains(cha.getObjectId()))
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if ((_owner == null) || (cha == null))
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
- if (cha == _owner)
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if (cha instanceof L2PcInstance)
|
|
|
- {
|
|
|
- // observers can't see trap
|
|
|
- if (((L2PcInstance) cha).inObserverMode())
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // olympiad competitors can't see trap
|
|
|
- if (_owner.isInOlympiadMode() && ((L2PcInstance) cha).isInOlympiadMode() && (((L2PcInstance) cha).getOlympiadSide() != _owner.getOlympiadSide()))
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (_isInArena)
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if (_owner.isInParty() && cha.isInParty() && (_owner.getParty().getLeaderObjectId() == cha.getParty().getLeaderObjectId()))
|
|
|
+ if (_isTriggered || canBeSeen(activeChar))
|
|
|
{
|
|
|
- return true;
|
|
|
+ activeChar.sendPacket(new TrapInfo(this, activeChar));
|
|
|
}
|
|
|
-
|
|
|
- return false;
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
public void setDetected(L2Character detector)
|
|
|
{
|
|
|
if (_isInArena)
|
|
|
{
|
|
|
- super.setDetected(detector);
|
|
|
+ detector.sendPacket(new TrapInfo(this, detector));
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
if ((_owner != null) && (_owner.getPvpFlag() == 0) && (_owner.getKarma() == 0))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
_playersWhoDetectedMe.add(detector.getObjectId());
|
|
|
+
|
|
|
if (getTemplate().getEventQuests(Quest.QuestEventType.ON_TRAP_ACTION) != null)
|
|
|
{
|
|
|
for (Quest quest : getTemplate().getEventQuests(Quest.QuestEventType.ON_TRAP_ACTION))
|
|
@@ -233,58 +381,87 @@ public class L2TrapInstance extends L2Trap
|
|
|
quest.notifyTrapAction(this, detector, TrapAction.TRAP_DETECTED);
|
|
|
}
|
|
|
}
|
|
|
- super.setDetected(detector);
|
|
|
+ detector.sendPacket(new TrapInfo(this, detector));
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- protected boolean checkTarget(L2Character target)
|
|
|
+ public void stopDecay()
|
|
|
{
|
|
|
- if (!L2Skill.checkForAreaOffensiveSkills(this, target, getSkill(), _isInArena))
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // observers
|
|
|
- if ((target instanceof L2PcInstance) && ((L2PcInstance) target).inObserverMode())
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
+ DecayTaskManager.getInstance().cancelDecayTask(this);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Trigger the trap.
|
|
|
+ * @param target the target
|
|
|
+ */
|
|
|
+ public void triggerTrap(L2Character target)
|
|
|
+ {
|
|
|
+ _isTriggered = true;
|
|
|
+ broadcastPacket(new TrapInfo(this, null));
|
|
|
+ setTarget(target);
|
|
|
|
|
|
- // olympiad own team and their summons not attacked
|
|
|
- if ((_owner != null) && _owner.isInOlympiadMode())
|
|
|
+ if (getTemplate().getEventQuests(Quest.QuestEventType.ON_TRAP_ACTION) != null)
|
|
|
{
|
|
|
- final L2PcInstance player = target.getActingPlayer();
|
|
|
- if ((player != null) && player.isInOlympiadMode() && (player.getOlympiadSide() == _owner.getOlympiadSide()))
|
|
|
+ for (Quest quest : getTemplate().getEventQuests(Quest.QuestEventType.ON_TRAP_ACTION))
|
|
|
{
|
|
|
- return false;
|
|
|
+ quest.notifyTrapAction(this, target, TrapAction.TRAP_TRIGGERED);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (_isInArena)
|
|
|
+ ThreadPoolManager.getInstance().scheduleGeneral(new TrapTriggerTask(this), 300);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void unSummon()
|
|
|
+ {
|
|
|
+ if (_owner != null)
|
|
|
{
|
|
|
- return true;
|
|
|
+ _owner.setTrap(null);
|
|
|
+ _owner = null;
|
|
|
}
|
|
|
|
|
|
- // trap owned by players not attack non-flagged players
|
|
|
- if (_owner != null)
|
|
|
+ if (isVisible() && !isDead())
|
|
|
{
|
|
|
- final L2PcInstance player = target.getActingPlayer();
|
|
|
- if (target instanceof L2Attackable)
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
- else if ((player == null) || ((player.getPvpFlag() == 0) && (player.getKarma() == 0)))
|
|
|
+ if (getWorldRegion() != null)
|
|
|
{
|
|
|
- return false;
|
|
|
+ getWorldRegion().removeFromZones(this);
|
|
|
}
|
|
|
+
|
|
|
+ deleteMe();
|
|
|
}
|
|
|
-
|
|
|
- return true;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public boolean isTrap()
|
|
|
+ public void updateAbnormalEffect()
|
|
|
{
|
|
|
- return true;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean hasLifeTime()
|
|
|
+ {
|
|
|
+ return _hasLifeTime;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setHasLifeTime(boolean val)
|
|
|
+ {
|
|
|
+ _hasLifeTime = val;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getRemainingTime()
|
|
|
+ {
|
|
|
+ return _remainingTime;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setRemainingTime(int time)
|
|
|
+ {
|
|
|
+ _remainingTime = time;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setSkill(L2Skill _skill)
|
|
|
+ {
|
|
|
+ this._skill = _skill;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getLifeTime()
|
|
|
+ {
|
|
|
+ return _lifeTime;
|
|
|
}
|
|
|
}
|