/* * 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 . */ package com.l2jserver.gameserver.model.actor; import java.util.Collection; import java.util.logging.Level; import com.l2jserver.gameserver.ThreadPoolManager; import com.l2jserver.gameserver.model.L2ItemInstance; import com.l2jserver.gameserver.model.L2Skill; import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; import com.l2jserver.gameserver.model.actor.knownlist.TrapKnownList; import com.l2jserver.gameserver.model.quest.Quest; import com.l2jserver.gameserver.model.quest.Quest.TrapAction; import com.l2jserver.gameserver.network.serverpackets.AbstractNpcInfo; import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket; import com.l2jserver.gameserver.network.serverpackets.SocialAction; import com.l2jserver.gameserver.taskmanager.DecayTaskManager; import com.l2jserver.gameserver.templates.chars.L2NpcTemplate; import com.l2jserver.gameserver.templates.item.L2Weapon; /** * * @author nBd */ public class L2Trap extends L2Character { protected static final int TICK = 1000; // 1s private boolean _isTriggered; private final L2Skill _skill; private final int _lifeTime; private int _timeRemaining; private boolean _hasLifeTime; /** * @param objectId * @param template */ public L2Trap(int objectId, L2NpcTemplate template, int lifeTime, L2Skill skill) { super(objectId, template); setInstanceType(InstanceType.L2Trap); setName(template.name); setIsInvul(false); _isTriggered = false; _skill = skill; _hasLifeTime = true; if (lifeTime != 0) _lifeTime = lifeTime; else _lifeTime = 30000; _timeRemaining = _lifeTime; if (lifeTime < 0) _hasLifeTime = false; if (skill != null) ThreadPoolManager.getInstance().scheduleGeneral(new TrapTask(), TICK); } /** * * @see com.l2jserver.gameserver.model.actor.L2Character#getKnownList() */ @Override public TrapKnownList getKnownList() { return (TrapKnownList) super.getKnownList(); } @Override public void initKnownList() { setKnownList(new TrapKnownList(this)); } @Override public boolean isAutoAttackable(L2Character attacker) { return !canSee(attacker); } /** * * */ public void stopDecay() { DecayTaskManager.getInstance().cancelDecayTask(this); } /** * * @see com.l2jserver.gameserver.model.actor.L2Character#onDecay() */ @Override public void onDecay() { deleteMe(); } /** * * @return */ public final int getNpcId() { return getTemplate().npcId; } /** * * @see com.l2jserver.gameserver.model.actor.L2Character#doDie(com.l2jserver.gameserver.model.actor.L2Character) */ @Override public boolean doDie(L2Character killer) { if (!super.doDie(killer)) return false; DecayTaskManager.getInstance().addDecayTask(this); return true; } /** * * @param owner */ @Override public void deleteMe() { decayMe(); getKnownList().removeAllKnownObjects(); super.deleteMe(); } /** * * @param owner */ public synchronized void unSummon() { if (isVisible() && !isDead()) { if (getWorldRegion() != null) getWorldRegion().removeFromZones(this); deleteMe(); } } /** * * @see com.l2jserver.gameserver.model.actor.L2Character#getActiveWeaponInstance() */ @Override public L2ItemInstance getActiveWeaponInstance() { return null; } /** * * @see com.l2jserver.gameserver.model.actor.L2Character#getActiveWeaponItem() */ @Override public L2Weapon getActiveWeaponItem() { return null; } /** * * @see com.l2jserver.gameserver.model.actor.L2Character#getLevel() */ @Override public int getLevel() { return getTemplate().level; } /** * * @see com.l2jserver.gameserver.model.actor.L2Character#getTemplate() */ @Override public L2NpcTemplate getTemplate() { return (L2NpcTemplate) super.getTemplate(); } /** * * @see com.l2jserver.gameserver.model.actor.L2Character#getSecondaryWeaponInstance() */ @Override public L2ItemInstance getSecondaryWeaponInstance() { return null; } /** * * @see com.l2jserver.gameserver.model.actor.L2Character#getSecondaryWeaponItem() */ @Override public L2Weapon getSecondaryWeaponItem() { return null; } /** * * @see com.l2jserver.gameserver.model.actor.L2Character#updateAbnormalEffect() */ @Override public void updateAbnormalEffect() { } public L2Skill getSkill() { return _skill; } public L2PcInstance getOwner() { return null; } public int getKarma() { return 0; } public byte getPvpFlag() { return 0; } /** * Checks is triggered * @return True if trap is triggered. */ public boolean isTriggered() { return _isTriggered; } /** * Checks trap visibility * @param cha - checked character * @return True if character can see trap */ public boolean canSee(L2Character cha) { return false; } /** * Reveal trap to the detector (if possible) * @param detector */ public void setDetected(L2Character detector) { detector.sendPacket(new AbstractNpcInfo.TrapInfo(this, detector)); } /** * Check if target can trigger trap * @param target * @return */ protected boolean checkTarget(L2Character target) { return L2Skill.checkForAreaOffensiveSkills(this, target, _skill, false); } private class TrapTask implements Runnable { public void run() { try { if (!_isTriggered) { if (_hasLifeTime) { _timeRemaining -= TICK; if (_timeRemaining < _lifeTime - 15000) { SocialAction sa = new SocialAction(getObjectId(), 2); broadcastPacket(sa); } if (_timeRemaining < 0) { switch (getSkill().getTargetType()) { case TARGET_AURA: case TARGET_FRONT_AURA: case TARGET_BEHIND_AURA: trigger(L2Trap.this); break; default: unSummon(); } return; } } for (L2Character target : getKnownList().getKnownCharactersInRadius(_skill.getSkillRadius())) { if (!checkTarget(target)) continue; trigger(target); return; } ThreadPoolManager.getInstance().scheduleGeneral(new TrapTask(), TICK); } } catch (Exception e) { _log.log(Level.SEVERE, "", e); unSummon(); } } } /** * Trigger trap * @param target */ public void trigger(L2Character target) { _isTriggered = true; broadcastPacket(new AbstractNpcInfo.TrapInfo(this, null)); setTarget(target); if (getTemplate().getEventQuests(Quest.QuestEventType.ON_TRAP_ACTION) != null) for (Quest quest : getTemplate().getEventQuests(Quest.QuestEventType.ON_TRAP_ACTION)) quest.notifyTrapAction(this, target, TrapAction.TRAP_TRIGGERED); ThreadPoolManager.getInstance().scheduleGeneral(new TriggerTask(), 300); } private class TriggerTask implements Runnable { public void run() { try { doCast(_skill); ThreadPoolManager.getInstance().scheduleGeneral(new UnsummonTask(), _skill.getHitTime() + 300); } catch (Exception e) { unSummon(); } } } private class UnsummonTask implements Runnable { public void run() { unSummon(); } } @Override public void sendInfo(L2PcInstance activeChar) { if (_isTriggered || canSee(activeChar)) activeChar.sendPacket(new AbstractNpcInfo.TrapInfo(this, activeChar)); } @Override public void broadcastPacket(L2GameServerPacket mov) { Collection plrs = getKnownList().getKnownPlayers().values(); for (L2PcInstance player : plrs) if (player != null && (_isTriggered || canSee(player))) player.sendPacket(mov); } @Override public void broadcastPacket(L2GameServerPacket mov, int radiusInKnownlist) { Collection plrs = getKnownList().getKnownPlayers().values(); for (L2PcInstance player : plrs) { if (player == null) continue; if (isInsideRadius(player, radiusInKnownlist, false, false)) if (_isTriggered || canSee(player)) player.sendPacket(mov); } } }