From c9208000bb7a153e82ae492d19d816f7966aab54 Mon Sep 17 00:00:00 2001 From: MagicBot Date: Thu, 15 Oct 2026 08:52:56 -0400 Subject: [PATCH] Pull siege engine aggro on damage only A siege engine switches to whoever damages it, player or pet, even when it already has a target. Pre-roll melee retaliation, harmful-power direct aggro (which also fires on misses) and Taunt no longer change a siege engine's target. The attack timer is untouched, so a switched engine still waits for its next cycle before firing. Co-Authored-By: Claude Opus 5.5 --- src/engine/gameManager/CombatManager.java | 3 ++- src/engine/objects/AbstractCharacter.java | 7 +++++++ src/engine/objects/Mob.java | 5 +++++ src/engine/powers/poweractions/ApplyEffectPowerAction.java | 4 +++- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/engine/gameManager/CombatManager.java b/src/engine/gameManager/CombatManager.java index 633cc5eb..1924d61b 100644 --- a/src/engine/gameManager/CombatManager.java +++ b/src/engine/gameManager/CombatManager.java @@ -257,7 +257,8 @@ public enum CombatManager { //handle retaliate - if (AbstractCharacter.IsAbstractCharacter(target)) { + //siege engines only retaliate on damage, see AbstractCharacter.modifyHealth + if (AbstractCharacter.IsAbstractCharacter(target) && !(target.getObjectType().equals(mbEnums.GameObjectType.Mob) && ((Mob) target).isSiege())) { if (((AbstractCharacter) target).combatTarget == null || !((AbstractCharacter) target).combatTarget.isAlive()) { ((AbstractCharacter) target).combatTarget = attacker; if (target.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter) && ((AbstractCharacter) target).isCombat()) diff --git a/src/engine/objects/AbstractCharacter.java b/src/engine/objects/AbstractCharacter.java index 3eb88ddf..48ff4cae 100644 --- a/src/engine/objects/AbstractCharacter.java +++ b/src/engine/objects/AbstractCharacter.java @@ -1863,6 +1863,13 @@ public abstract class AbstractCharacter extends AbstractWorldObject { if (this.getObjectType().equals(GameObjectType.Mob)) { //handle hate value addition Mob target = (Mob) this; + + // Siege engines switch to whoever damages them, players and pets alike. + // Misses and non-damaging powers do not pull them. + + if (target.isSiege() && value < 0f && attacker != null && !attacker.equals(target)) + target.setCombatTarget(attacker); + if (attacker.getObjectType().equals(GameObjectType.PlayerCharacter)) { if (target.playerAgroMap.containsKey(attacker.getObjectUUID())) diff --git a/src/engine/objects/Mob.java b/src/engine/objects/Mob.java index 550b09f9..946ece4d 100644 --- a/src/engine/objects/Mob.java +++ b/src/engine/objects/Mob.java @@ -1318,6 +1318,11 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed { if (!ac.getObjectType().equals(GameObjectType.PlayerCharacter)) return; + // siege engines only switch targets on damage, see AbstractCharacter.modifyHealth + + if (this.isSiege()) + return; + if (this.getCombatTarget() == null) this.setCombatTarget(ac); diff --git a/src/engine/powers/poweractions/ApplyEffectPowerAction.java b/src/engine/powers/poweractions/ApplyEffectPowerAction.java index 5fa82e9d..169b8831 100644 --- a/src/engine/powers/poweractions/ApplyEffectPowerAction.java +++ b/src/engine/powers/poweractions/ApplyEffectPowerAction.java @@ -246,7 +246,9 @@ public class ApplyEffectPowerAction extends AbstractPowerAction { if (this.effectID.equals("TAUNT")) { - if (awo != null && awo.getObjectType() == GameObjectType.Mob) { + // siege engines only switch targets on damage, see AbstractCharacter.modifyHealth + + if (awo != null && awo.getObjectType() == GameObjectType.Mob && !((Mob) awo).isSiege()) { ((Mob) awo).setCombatTarget(source); ChatSystemMsg msg = ChatManager.CombatInfo(source, awo); DispatchManager.sendToAllInRange(source, msg);