From a796f5fe4b0c3a39b05ee8a41d7fb39a7b15a8f5 Mon Sep 17 00:00:00 2001
From: MagicBot <MagicBot@magicbane.com>
Date: Sat, 26 Aug 2023 11:55:18 -0400
Subject: [PATCH] More siege engine work.

---
 src/engine/Enum.java                          | 15 ++---
 src/engine/mobileAI/MobAI.java                | 19 +++---
 .../mobileAI/utilities/MovementUtilities.java |  4 +-
 .../handlers/MinionTrainingMsgHandler.java    |  2 +-
 src/engine/net/client/msg/ManageNPCMsg.java   |  4 +-
 src/engine/objects/Mob.java                   | 66 +++++++++----------
 6 files changed, 53 insertions(+), 57 deletions(-)

diff --git a/src/engine/Enum.java b/src/engine/Enum.java
index 15ed5702..d9d2527b 100644
--- a/src/engine/Enum.java
+++ b/src/engine/Enum.java
@@ -2846,7 +2846,7 @@ public class Enum {
         //Independent Types
         SimpleStandingGuard(null, false, false, false, false, false),
         Pet1(null, false, false, true, false, false),
-        SiegeEngine(null, false, false, true, false, false),
+        SiegeEngine(null, false, false, false, false, false),
         Simple(null, false, false, true, false, false),
         Helpee(null, false, true, true, false, true),
         HelpeeWimpy(null, true, false, true, false, false),
@@ -2857,13 +2857,12 @@ public class Enum {
         HamletGuard(null, false, true, false, false, false),
         AggroWanderer(null, false, false, true, false, false);
 
-        private static HashMap<Integer, MobBehaviourType> _behaviourTypes = new HashMap<>();
-        public MobBehaviourType BehaviourHelperType;
-        public boolean isWimpy;
-        public boolean isAgressive;
-        public boolean canRoam;
-        public boolean callsForHelp;
-        public boolean respondsToCallForHelp;
+        public final MobBehaviourType BehaviourHelperType;
+        public final boolean isWimpy;
+        public final boolean isAgressive;
+        public final boolean canRoam;
+        public final boolean callsForHelp;
+        public final boolean respondsToCallForHelp;
 
         MobBehaviourType(MobBehaviourType helpeebehaviourType, boolean wimpy, boolean agressive, boolean canroam, boolean callsforhelp, boolean respondstocallforhelp) {
             this.BehaviourHelperType = helpeebehaviourType;
diff --git a/src/engine/mobileAI/MobAI.java b/src/engine/mobileAI/MobAI.java
index 2f5d2fbd..94230778 100644
--- a/src/engine/mobileAI/MobAI.java
+++ b/src/engine/mobileAI/MobAI.java
@@ -313,7 +313,7 @@ public class MobAI {
                 int contractID;
 
                 if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion))
-                    contractID = mob.npcOwner.contract.getContractID();
+                    contractID = mob.guardCaptain.contract.getContractID();
                 else
                     contractID = mob.contract.getContractID();
 
@@ -609,7 +609,7 @@ public class MobAI {
             if (mob.despawned && mob.isPlayerGuard) {
 
                 if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion)) {
-                    if (mob.npcOwner.isAlive() == false || ((Mob) mob.npcOwner).despawned == true) {
+                    if (mob.guardCaptain.isAlive() == false || ((Mob) mob.guardCaptain).despawned == true) {
 
                         //minions don't respawn while guard captain is dead
 
@@ -808,7 +808,7 @@ public class MobAI {
                         chaseTarget(mob);
                     break;
                 case GuardMinion:
-                    if (!mob.npcOwner.isAlive() || ((Mob) mob.npcOwner).despawned)
+                    if (!mob.guardCaptain.isAlive() || ((Mob) mob.guardCaptain).despawned)
                         randomGuardPatrolPoint(mob);
                     else {
                         if (mob.getCombatTarget() != null) {
@@ -1055,7 +1055,7 @@ public class MobAI {
     public static void GuardMinionLogic(Mob mob) {
 
         try {
-            if (!mob.npcOwner.isAlive()) {
+            if (!mob.guardCaptain.isAlive()) {
 
                 if (mob.getCombatTarget() == null) {
                     CheckForPlayerGuardAggro(mob);
@@ -1074,11 +1074,10 @@ public class MobAI {
                     }
                 }
             }else {
-                if (mob.npcOwner.getCombatTarget() != null)
-                    mob.setCombatTarget(mob.npcOwner.getCombatTarget());
-                else
-                    if (mob.getCombatTarget() != null)
-                        mob.setCombatTarget(null);
+                if (mob.guardCaptain.getCombatTarget() != null)
+                    mob.setCombatTarget(mob.guardCaptain.getCombatTarget());
+                else if (mob.getCombatTarget() != null)
+                    mob.setCombatTarget(null);
             }
             CheckMobMovement(mob);
             CheckForAttack(mob);
@@ -1246,7 +1245,7 @@ public class MobAI {
                 return false;
 
             if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion)) {
-                if (((Mob) mob.npcOwner).building.getCity().cityOutlaws.contains(target.getObjectUUID()) == true) {
+                if (((Mob) mob.guardCaptain).building.getCity().cityOutlaws.contains(target.getObjectUUID()) == true) {
                     return true;
                 }
             } else if (mob.building.getCity().cityOutlaws.contains(target.getObjectUUID()) == true) {
diff --git a/src/engine/mobileAI/utilities/MovementUtilities.java b/src/engine/mobileAI/utilities/MovementUtilities.java
index 85affdca..9bda3497 100644
--- a/src/engine/mobileAI/utilities/MovementUtilities.java
+++ b/src/engine/mobileAI/utilities/MovementUtilities.java
@@ -13,10 +13,10 @@ import engine.Enum;
 import engine.Enum.GameObjectType;
 import engine.Enum.ModType;
 import engine.Enum.SourceType;
-import engine.mobileAI.Threads.MobAIThread;
 import engine.exception.MsgSendException;
 import engine.gameManager.MovementManager;
 import engine.math.Vector3fImmutable;
+import engine.mobileAI.Threads.MobAIThread;
 import engine.net.client.msg.MoveToPointMsg;
 import engine.objects.*;
 import org.pmw.tinylog.Logger;
@@ -38,7 +38,7 @@ public class MovementUtilities {
             if (agent.getContract() != null)
                 guardCaptain = agent;
             else
-                guardCaptain = (Mob) agent.npcOwner;
+                guardCaptain = (Mob) agent.guardCaptain;
 
             if (guardCaptain != null) {
                 Building barracks = guardCaptain.building;
diff --git a/src/engine/net/client/handlers/MinionTrainingMsgHandler.java b/src/engine/net/client/handlers/MinionTrainingMsgHandler.java
index 8d489fc2..76f1d928 100644
--- a/src/engine/net/client/handlers/MinionTrainingMsgHandler.java
+++ b/src/engine/net/client/handlers/MinionTrainingMsgHandler.java
@@ -167,7 +167,7 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
                             if (building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.ARTYTOWER))
                                 slot = 2;
                             else
-                                slot = ((NPC) siegeMob.npcOwner).getSiegeMinionMap().get(siegeMob) + 1;  // First slot is for the captain
+                                slot = ((NPC) siegeMob.guardCaptain).getSiegeMinionMap().get(siegeMob) + 1;  // First slot is for the captain
 
                             BuildingLocation slotLocation = BuildingManager._slotLocations.get(building.meshUUID).get(slot);
                             siegeMob.bindLoc = building.getLoc().add(slotLocation.getLocation());
diff --git a/src/engine/net/client/msg/ManageNPCMsg.java b/src/engine/net/client/msg/ManageNPCMsg.java
index 8fcda7f7..c6c07279 100644
--- a/src/engine/net/client/msg/ManageNPCMsg.java
+++ b/src/engine/net/client/msg/ManageNPCMsg.java
@@ -366,7 +366,7 @@ public class ManageNPCMsg extends ClientNetMsg {
                                 long timeLife = upgradeTime - curTime;
 
                                 if (upgradeTime * 1000 > System.currentTimeMillis()) {
-                                    if (mob.npcOwner.isAlive()) {
+                                    if (mob.guardCaptain.isAlive()) {
                                         writer.put((byte) 0);//shows respawning timer
                                         writer.putInt(mob.spawnTime);
                                         writer.putInt(mob.spawnTime);
@@ -689,7 +689,7 @@ public class ManageNPCMsg extends ClientNetMsg {
                                 long timeLife = upgradeTime - curTime;
 
                                 if (upgradeTime * 1000 > System.currentTimeMillis()) {
-                                    if (mob.npcOwner.isAlive()) {
+                                    if (mob.guardCaptain.isAlive()) {
                                         writer.put((byte) 0);//shows respawning timer
                                         writer.putInt(mob.spawnTime);
                                         writer.putInt(mob.spawnTime);
diff --git a/src/engine/objects/Mob.java b/src/engine/objects/Mob.java
index 282d26fb..743f795b 100644
--- a/src/engine/objects/Mob.java
+++ b/src/engine/objects/Mob.java
@@ -61,13 +61,14 @@ public class Mob extends AbstractIntelligenceAgent {
     public Zone parentZone;
     public boolean hasLoot = false;
     public boolean isPlayerGuard = false;
-    public AbstractCharacter npcOwner;
+    public AbstractCharacter guardCaptain;
     public long deathTime = 0;
     public int equipmentSetID = 0;
     public int runeSet = 0;
     public int bootySet = 0;
-    public EnumBitSet<MonsterType> notEnemy;
-    public EnumBitSet<Enum.MonsterType> enemy;
+    public EnumBitSet<MonsterType> notEnemy = EnumBitSet.noneOf(MonsterType.class);
+    public EnumBitSet<Enum.MonsterType> enemy = EnumBitSet.noneOf(MonsterType.class);
+    ;
     public MobBehaviourType behaviourType;
     public ArrayList<Vector3fImmutable> patrolPoints;
     public int lastPatrolPointIndex = 0;
@@ -323,7 +324,7 @@ public class Mob extends AbstractIntelligenceAgent {
 
         writer.putInt(0); // NPC menu options
 
-        if (mob.contract != null && mob.npcOwner == null) {
+        if (mob.contract != null && mob.guardCaptain == null) {
             writer.put((byte) 1);
             writer.putLong(0);
             writer.putLong(0);
@@ -336,12 +337,12 @@ public class Mob extends AbstractIntelligenceAgent {
         } else
             writer.put((byte) 0);
 
-        if (mob.npcOwner != null) {
+        if (mob.guardCaptain != null) {
             writer.put((byte) 1);
             writer.putInt(GameObjectType.PlayerCharacter.ordinal());
             writer.putInt(131117009);
-            writer.putInt(mob.npcOwner.getObjectType().ordinal());
-            writer.putInt(mob.npcOwner.getObjectUUID());
+            writer.putInt(mob.guardCaptain.getObjectType().ordinal());
+            writer.putInt(mob.guardCaptain.getObjectUUID());
             writer.putInt(8);
         } else
             writer.put((byte) 0);
@@ -618,7 +619,7 @@ public class Mob extends AbstractIntelligenceAgent {
         minionMobile.notEnemy = guardCaptain.notEnemy;
 
         minionMobile.deathTime = System.currentTimeMillis();
-        minionMobile.npcOwner = guardCaptain;
+        minionMobile.guardCaptain = guardCaptain;
         minionMobile.spawnTime = (int) (-2.500 * guardCaptain.building.getRank() + 22.5) * 60;
         minionMobile.behaviourType = Enum.MobBehaviourType.GuardMinion;
         minionMobile.isPlayerGuard = true;
@@ -651,7 +652,6 @@ public class Mob extends AbstractIntelligenceAgent {
         // Configure and spawn minion
 
         minionMobile.runAfterLoad();
-        minionMobile.despawned = false;
         DbManager.addToCache(minionMobile);
 
         minionMobile.setLoc(minionMobile.bindLoc);
@@ -665,26 +665,22 @@ public class Mob extends AbstractIntelligenceAgent {
 
     public static synchronized Mob createSiegeMob(NPC owner, int loadID, Guild guild, Zone parent, Vector3fImmutable loc, short level) {
 
-        MobBase minionMobBase;
-        Mob mob;
+        Mob siegeMinion;
 
         if (owner.getSiegeMinionMap().size() == 3)
             return null;
 
-        minionMobBase = MobBase.getMobBase(loadID);
-
-        if (minionMobBase == null)
-            return null;
-
-        mob = new Mob(minionMobBase, guild, parent, level, new Vector3fImmutable(1, 1, 1), 0, false);
-        //mob.runAfterLoad();
-        mob.despawned = true;
-        DbManager.addToCache(mob);
+        siegeMinion = new Mob();
 
-        mob.setObjectTypeMask(MBServerStatics.MASK_MOB | mob.getTypeMasks());
-
-        //mob.setMob();
-        //      mob.setSiege(true);
+        siegeMinion.level = 1;
+        siegeMinion.loadID = loadID;
+        siegeMinion.guildUUID = guild.getObjectUUID();
+        siegeMinion.equipmentSetID = 0;
+        siegeMinion.buildingUUID = owner.buildingUUID;
+        siegeMinion.guardCaptain = owner;
+        siegeMinion.parentZoneUUID = parent.getObjectUUID();
+        siegeMinion.behaviourType = MobBehaviourType.SiegeEngine;
+        siegeMinion.bindLoc = Vector3fImmutable.ZERO;
 
         int slot = 0;
 
@@ -693,12 +689,14 @@ public class Mob extends AbstractIntelligenceAgent {
         else if (!owner.getSiegeMinionMap().containsValue(2))
             slot = 2;
 
-        owner.getSiegeMinionMap().put(mob, slot);
+        owner.getSiegeMinionMap().put(siegeMinion, slot);
 
-        mob.setNpcOwner(owner);
-        mob.behaviourType = MobBehaviourType.Pet1;
-        mob.behaviourType.canRoam = false;
-        return mob;
+        siegeMinion.runAfterLoad();
+        siegeMinion.despawned = true;
+        DbManager.addToCache(siegeMinion);
+        siegeMinion.setLoc(siegeMinion.bindLoc);
+
+        return siegeMinion;
     }
 
 
@@ -995,7 +993,7 @@ public class Mob extends AbstractIntelligenceAgent {
                 this.playerAgroMap.clear();
 
                 if (this.behaviourType.ordinal() == Enum.MobBehaviourType.GuardMinion.ordinal())
-                    this.spawnTime = (int) (-2.500 * this.npcOwner.building.getRank() + 22.5) * 60;
+                    this.spawnTime = (int) (-2.500 * this.guardCaptain.building.getRank() + 22.5) * 60;
 
                 if (this.isPet()) {
 
@@ -1084,8 +1082,8 @@ public class Mob extends AbstractIntelligenceAgent {
         this.recalculateStats();
         this.setHealth(this.healthMax);
 
-        if (this.building == null && this.npcOwner != null && ((Mob) this.npcOwner).behaviourType.ordinal() == MobBehaviourType.GuardCaptain.ordinal())
-            this.building = this.npcOwner.building;
+        if (this.building == null && this.guardCaptain != null && ((Mob) this.guardCaptain).behaviourType.ordinal() == MobBehaviourType.GuardCaptain.ordinal())
+            this.building = this.guardCaptain.building;
         else if (this.building != null)
             this.region = BuildingManager.GetRegion(this.building, bindLoc.x, bindLoc.y, bindLoc.z);
 
@@ -1843,8 +1841,8 @@ public class Mob extends AbstractIntelligenceAgent {
         return this.behaviourType.equals(MobBehaviourType.SiegeEngine);
     }
 
-    public void setNpcOwner(AbstractCharacter npcOwner) {
-        this.npcOwner = npcOwner;
+    public void setGuardCaptain(AbstractCharacter guardCaptain) {
+        this.guardCaptain = guardCaptain;
     }
 
     public boolean isNecroPet() {