diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/WorldObject.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/WorldObject.java index 42fc3feceb..46f48f046c 100644 --- a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/WorldObject.java +++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/WorldObject.java @@ -395,6 +395,15 @@ public abstract class WorldObject } } + /** + * Verify if object can be attacked. + * @return {@code true} if object can be attacked, {@code false} otherwise + */ + public boolean canBeAttacked() + { + return false; + } + public PlayerInstance getActingPlayer() { return null; diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Attackable.java index ded4aa6696..dee6a7ce4a 100644 --- a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Attackable.java +++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Attackable.java @@ -2563,9 +2563,12 @@ public class Attackable extends NpcInstance return bonusOverhit; } - /** - * Return True. - */ + @Override + public boolean canBeAttacked() + { + return true; + } + @Override public boolean isAttackable() { diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Creature.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Creature.java index ac6306d552..782d61dde3 100644 --- a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Creature.java +++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Creature.java @@ -281,7 +281,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder _calculators = new Calculator[Stat.NUM_STATS]; Formulas.getInstance().addFuncsToNewCharacter(this); - if (!(this instanceof Attackable) && !isAttackable() && !(this instanceof DoorInstance)) + if (!isAttackable() && !canBeAttacked() && !(this instanceof DoorInstance)) { setInvul(true); } @@ -6332,6 +6332,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder } } + if ((player.getTarget() != null) && !player.getTarget().canBeAttacked() && !player.getAccessLevel().allowPeaceAttack()) + { + // If target is not attackable, send a Server->Client packet ActionFailed + player.sendPacket(ActionFailed.STATIC_PACKET); + return; + } + if (player.isConfused() || player.isBlocked()) { // If target is confused, send a Server->Client packet ActionFailed @@ -7432,9 +7439,9 @@ public abstract class Creature extends WorldObject implements ISkillsHolder // if the skill has changed the character's state to something other than STATE_CASTING // then just leave it that way, otherwise switch back to STATE_IDLE. - if ((skill.getId() != 345) && (skill.getId() != 346)) + if ((skill.getId() != 345) && (skill.getId() != 346) && _target.canBeAttacked()) { - // Like L2OFF while use a skill and next interntion == null the char stop auto attack + // Like L2OFF while use a skill and next intention == null the char stop auto attack if (((getAI().getNextIntention() == null) && ((skill.getSkillType() == SkillType.PDAM) && (skill.getCastRange() < 400))) || (skill.getSkillType() == SkillType.BLOW) || (skill.getSkillType() == SkillType.DRAIN_SOUL) || (skill.getSkillType() == SkillType.SOW) || (skill.getSkillType() == SkillType.SPOIL)) { if (this instanceof PlayerInstance) @@ -7459,6 +7466,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder getAI().clientStartAutoAttack(); } } + if (this instanceof PlayerInstance) { final PlayerInstance currPlayer = (PlayerInstance) this; @@ -7469,7 +7477,6 @@ public abstract class Creature extends WorldObject implements ISkillsHolder { getAI().setIntention(AI_INTENTION_ATTACK, _target); } - getAI().clientStartAutoAttack(); } } @@ -7479,7 +7486,6 @@ public abstract class Creature extends WorldObject implements ISkillsHolder { getAI().setIntention(AI_INTENTION_ATTACK, _target); } - getAI().clientStartAutoAttack(); } } diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Playable.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Playable.java index b7144aaf5e..2a32f6ff7a 100644 --- a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Playable.java +++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Playable.java @@ -182,10 +182,12 @@ public abstract class Playable extends Creature return true; } - /** - * Return True. - * @return true, if is attackable - */ + @Override + public boolean canBeAttacked() + { + return true; + } + @Override public boolean isAttackable() { diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Summon.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Summon.java index 62ed1915a8..1606d96cc4 100644 --- a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Summon.java +++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/Summon.java @@ -287,7 +287,7 @@ public abstract class Summon extends Playable getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE); return; } - if (!target.isAttackable() && !(this instanceof SiegeSummonInstance)) + if (!target.canBeAttacked() && !(this instanceof SiegeSummonInstance)) { getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE); return; @@ -699,7 +699,7 @@ public abstract class Summon extends Playable } else { - if (!target.isAttackable() && (_owner != null) && _owner.getAccessLevel().allowPeaceAttack()) + if (!target.canBeAttacked() && (_owner != null) && _owner.getAccessLevel().allowPeaceAttack()) { return; } diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/instance/ArtefactInstance.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/instance/ArtefactInstance.java index a1f780c2a5..b475ed224b 100644 --- a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/instance/ArtefactInstance.java +++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/instance/ArtefactInstance.java @@ -57,6 +57,12 @@ public class ArtefactInstance extends NpcInstance return false; } + @Override + public boolean canBeAttacked() + { + return false; + } + @Override public boolean isAttackable() { diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/instance/NpcInstance.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/instance/NpcInstance.java index 0371b80e3a..fb4427ca5c 100644 --- a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/instance/NpcInstance.java +++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/instance/NpcInstance.java @@ -310,9 +310,9 @@ public class NpcInstance extends Creature } @Override - public boolean isAttackable() + public boolean canBeAttacked() { - return Config.NPC_ATTACKABLE || (this instanceof Attackable); + return Config.NPC_ATTACKABLE; } /** diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java index f02e73a7bd..0d4fbd8636 100644 --- a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java +++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java @@ -9904,6 +9904,13 @@ public class PlayerInstance extends Playable } } + // If target is not attackable, send a Server->Client packet ActionFailed + if (!target.canBeAttacked() && !getAccessLevel().allowPeaceAttack() && !target.isDoor()) + { + sendPacket(ActionFailed.STATIC_PACKET); + return; + } + // Pk protection config if (Config.ALLOW_CHAR_KILL_PROTECT && skill.isOffensive() && !isGM() && target.isPlayer() && (target.getActingPlayer().getPvpFlag() == 0) && (target.getActingPlayer().getKarma() == 0)) { diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/WorldObject.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/WorldObject.java index 42fc3feceb..46f48f046c 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/WorldObject.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/WorldObject.java @@ -395,6 +395,15 @@ public abstract class WorldObject } } + /** + * Verify if object can be attacked. + * @return {@code true} if object can be attacked, {@code false} otherwise + */ + public boolean canBeAttacked() + { + return false; + } + public PlayerInstance getActingPlayer() { return null; diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Attackable.java index 3661063f21..67abfef347 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Attackable.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Attackable.java @@ -2915,9 +2915,12 @@ public class Attackable extends NpcInstance return bonusOverhit; } - /** - * Return True. - */ + @Override + public boolean canBeAttacked() + { + return true; + } + @Override public boolean isAttackable() { diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Creature.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Creature.java index ea8a40bc05..187ccfa7a5 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Creature.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Creature.java @@ -283,7 +283,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder _calculators = new Calculator[Stat.NUM_STATS]; Formulas.getInstance().addFuncsToNewCharacter(this); - if (!(this instanceof Attackable) && !isAttackable() && !(this instanceof DoorInstance)) + if (!isAttackable() && !canBeAttacked() && !(this instanceof DoorInstance)) { setInvul(true); } @@ -6379,6 +6379,13 @@ public abstract class Creature extends WorldObject implements ISkillsHolder } } + if ((player.getTarget() != null) && !player.getTarget().canBeAttacked() && !player.getAccessLevel().allowPeaceAttack()) + { + // If target is not attackable, send a Server->Client packet ActionFailed + player.sendPacket(ActionFailed.STATIC_PACKET); + return; + } + if (player.isConfused() || player.isBlocked()) { // If target is confused, send a Server->Client packet ActionFailed @@ -7479,9 +7486,9 @@ public abstract class Creature extends WorldObject implements ISkillsHolder // if the skill has changed the character's state to something other than STATE_CASTING // then just leave it that way, otherwise switch back to STATE_IDLE. - if ((skill.getId() != 345) && (skill.getId() != 346)) + if ((skill.getId() != 345) && (skill.getId() != 346) && _target.canBeAttacked()) { - // Like L2OFF while use a skill and next interntion == null the char stop auto attack + // Like L2OFF while use a skill and next intention == null the char stop auto attack if (((getAI().getNextIntention() == null) && ((skill.getSkillType() == SkillType.PDAM) && (skill.getCastRange() < 400))) || (skill.getSkillType() == SkillType.BLOW) || (skill.getSkillType() == SkillType.DRAIN_SOUL) || (skill.getSkillType() == SkillType.SOW) || (skill.getSkillType() == SkillType.SPOIL)) { if (this instanceof PlayerInstance) @@ -7506,6 +7513,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder getAI().clientStartAutoAttack(); } } + if (this instanceof PlayerInstance) { final PlayerInstance currPlayer = (PlayerInstance) this; @@ -7516,7 +7524,6 @@ public abstract class Creature extends WorldObject implements ISkillsHolder { getAI().setIntention(AI_INTENTION_ATTACK, _target); } - getAI().clientStartAutoAttack(); } } @@ -7526,7 +7533,6 @@ public abstract class Creature extends WorldObject implements ISkillsHolder { getAI().setIntention(AI_INTENTION_ATTACK, _target); } - getAI().clientStartAutoAttack(); } } diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Playable.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Playable.java index b7144aaf5e..2a32f6ff7a 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Playable.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Playable.java @@ -182,10 +182,12 @@ public abstract class Playable extends Creature return true; } - /** - * Return True. - * @return true, if is attackable - */ + @Override + public boolean canBeAttacked() + { + return true; + } + @Override public boolean isAttackable() { diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Summon.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Summon.java index 62ed1915a8..1606d96cc4 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Summon.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Summon.java @@ -287,7 +287,7 @@ public abstract class Summon extends Playable getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE); return; } - if (!target.isAttackable() && !(this instanceof SiegeSummonInstance)) + if (!target.canBeAttacked() && !(this instanceof SiegeSummonInstance)) { getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE); return; @@ -699,7 +699,7 @@ public abstract class Summon extends Playable } else { - if (!target.isAttackable() && (_owner != null) && _owner.getAccessLevel().allowPeaceAttack()) + if (!target.canBeAttacked() && (_owner != null) && _owner.getAccessLevel().allowPeaceAttack()) { return; } diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/instance/ArtefactInstance.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/instance/ArtefactInstance.java index a1f780c2a5..b475ed224b 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/instance/ArtefactInstance.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/instance/ArtefactInstance.java @@ -57,6 +57,12 @@ public class ArtefactInstance extends NpcInstance return false; } + @Override + public boolean canBeAttacked() + { + return false; + } + @Override public boolean isAttackable() { diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/instance/NpcInstance.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/instance/NpcInstance.java index 98c7f47272..99bafd5382 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/instance/NpcInstance.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/instance/NpcInstance.java @@ -312,9 +312,9 @@ public class NpcInstance extends Creature } @Override - public boolean isAttackable() + public boolean canBeAttacked() { - return Config.NPC_ATTACKABLE || (this instanceof Attackable); + return Config.NPC_ATTACKABLE; } /** diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java index 5fb73a4b06..7a687deb76 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java @@ -10067,6 +10067,13 @@ public class PlayerInstance extends Playable } } + // If target is not attackable, send a Server->Client packet ActionFailed + if (!target.canBeAttacked() && !getAccessLevel().allowPeaceAttack() && !target.isDoor()) + { + sendPacket(ActionFailed.STATIC_PACKET); + return; + } + // Are the target and the player in the same duel? if (isInDuel() && (!(target instanceof PlayerInstance) || (target.getActingPlayer().getDuelId() != getDuelId())) && (!(target instanceof SummonInstance) || (((Summon) target).getOwner().getDuelId() != getDuelId()))) {