From d4e430e8163e5ad5872ca4337ac7ae19bc505b5d Mon Sep 17 00:00:00 2001 From: FatBoy-DOTC Date: Mon, 3 Mar 2025 19:22:23 -0600 Subject: [PATCH] simplified mob aI --- .../mobileAI/Behaviours/StandardMob.java | 170 ++++++++++++++++++ src/engine/mobileAI/MobAI.java | 17 ++ 2 files changed, 187 insertions(+) create mode 100644 src/engine/mobileAI/Behaviours/StandardMob.java diff --git a/src/engine/mobileAI/Behaviours/StandardMob.java b/src/engine/mobileAI/Behaviours/StandardMob.java new file mode 100644 index 00000000..50b413c4 --- /dev/null +++ b/src/engine/mobileAI/Behaviours/StandardMob.java @@ -0,0 +1,170 @@ +package engine.mobileAI.Behaviours; + +import engine.Enum; +import engine.InterestManagement.WorldGrid; +import engine.math.Vector3fImmutable; +import engine.mobileAI.utilities.CombatUtilities; +import engine.mobileAI.utilities.MovementUtilities; +import engine.objects.*; +import engine.server.MBServerStatics; +import java.util.HashSet; + +public class StandardMob { + + public static void run(Mob mob){ + if(!mob.isAlive()){ + CheckForRespawn(mob); + return; + } + + mob.updateLocation(); + + if(mob.combatTarget == null) { + HashSet inRange = WorldGrid.getObjectsInRangePartial(mob.loc, MBServerStatics.CHARACTER_LOAD_RANGE, MBServerStatics.MASK_PLAYER); + if (!inRange.isEmpty()) { + CheckForAggro(mob, inRange); + return; + } + }else{ + CheckToDropCombatTarget(mob); + if(mob.combatTarget == null){ + HashSet inRange = WorldGrid.getObjectsInRangePartial(mob.loc, MBServerStatics.CHARACTER_LOAD_RANGE, MBServerStatics.MASK_PLAYER); + CheckForAggro(mob, inRange); + return; + } + } + + if(MovementUtilities.canMove(mob)) + CheckForMovement(mob); + + if(mob.combatTarget != null) + CheckForAttack(mob); + } + + public static void CheckToDropCombatTarget(Mob mob){ + + if(!mob.combatTarget.isAlive()){ + mob.setCombatTarget(null); + return; + } + + if(mob.combatTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)){ + PlayerCharacter pcTarget = (PlayerCharacter) mob.combatTarget; + if (!mob.canSee(pcTarget)) { + mob.setCombatTarget(null); + return; + } + } + + if(mob.bindLoc.distanceSquared(mob.combatTarget.loc) > 90 * 90){ + mob.setCombatTarget(null); + } + + + } + + public static void CheckForRespawn(Mob mob){ + if (mob.deathTime == 0) { + mob.setDeathTime(System.currentTimeMillis()); + return; + } + + if (!mob.despawned) { + + if (mob.getCharItemManager().getInventoryCount() > 0) { + if (System.currentTimeMillis() > mob.deathTime + MBServerStatics.DESPAWN_TIMER_WITH_LOOT) { + mob.despawn(); + mob.deathTime = System.currentTimeMillis(); + return; + } + //No items in inventory. + } else if (mob.isHasLoot()) { + if (System.currentTimeMillis() > mob.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) { + mob.despawn(); + mob.deathTime = System.currentTimeMillis(); + return; + } + //Mob never had Loot. + } else { + if (System.currentTimeMillis() > mob.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) { + mob.despawn(); + mob.deathTime = System.currentTimeMillis(); + return; + } + } + return; + } + + if(Mob.discDroppers.contains(mob)) + return; + + if (System.currentTimeMillis() > (mob.deathTime + (mob.spawnTime * 1000L))) { + Zone.respawnQue.add(mob); + } + } + + public static void CheckForAggro(Mob mob, HashSet inRange){ + + } + + public static void CheckForMovement(Mob mob){ + + if(mob.combatTarget != null){ + //chase player + float rangeSquared = mob.getRange() * mob.getRange(); + Vector3fImmutable loc2D = mob.loc; + loc2D.setY(0); + Vector3fImmutable tarLoc2D = mob.combatTarget.loc; + tarLoc2D.setY(0); + if(loc2D.distanceSquared(tarLoc2D) > rangeSquared) + MovementUtilities.aiMove(mob,mob.combatTarget.loc,false); + + }else{ + //patrol + if (mob.isMoving()) { + return; + } + Vector3fImmutable patrolPoint = Vector3fImmutable.getRandomPointOnCircle(mob.bindLoc,40f); + MovementUtilities.aiMove(mob,patrolPoint,true); + } + } + + public static void CheckForAttack(Mob mob){ + float rangeSquared = mob.getRange() * mob.getRange(); + Vector3fImmutable loc2D = mob.loc; + loc2D.setY(0); + Vector3fImmutable tarLoc2D = mob.combatTarget.loc; + tarLoc2D.setY(0); + if(loc2D.distanceSquared(tarLoc2D) > rangeSquared) + return; + + if (mob.BehaviourType.callsForHelp) + MobCallForHelp(mob); + + ItemBase mainHand = mob.getWeaponItemBase(true); + ItemBase offHand = mob.getWeaponItemBase(false); + + if (mainHand == null && offHand == null) { + CombatUtilities.combatCycle(mob, mob.combatTarget, true, null); + int delay = 3000; + mob.setLastAttackTime(System.currentTimeMillis() + delay); + } else if (mob.getWeaponItemBase(true) != null) { + int delay = 3000; + CombatUtilities.combatCycle(mob, mob.combatTarget, true, mob.getWeaponItemBase(true)); + mob.setLastAttackTime(System.currentTimeMillis() + delay); + } else if (mob.getWeaponItemBase(false) != null) { + int attackDelay = 3000; + CombatUtilities.combatCycle(mob, mob.combatTarget, false, mob.getWeaponItemBase(false)); + mob.setLastAttackTime(System.currentTimeMillis() + attackDelay); + } + } + public static void MobCallForHelp(Mob mob){ + HashSet mobs = WorldGrid.getObjectsInRangePartial(mob.loc,60f, MBServerStatics.MASK_MOB); + for(AbstractWorldObject awo : mobs){ + Mob responder = (Mob)awo; + if(responder.combatTarget == null) + if(MovementUtilities.canMove(responder)) + MovementUtilities.aiMove(responder,mob.loc,false); + } + } +} diff --git a/src/engine/mobileAI/MobAI.java b/src/engine/mobileAI/MobAI.java index 890781d4..86bd5fcb 100644 --- a/src/engine/mobileAI/MobAI.java +++ b/src/engine/mobileAI/MobAI.java @@ -14,6 +14,7 @@ import engine.InterestManagement.WorldGrid; import engine.gameManager.*; import engine.math.Vector3f; import engine.math.Vector3fImmutable; +import engine.mobileAI.Behaviours.StandardMob; import engine.mobileAI.Threads.MobAIThread; import engine.mobileAI.utilities.CombatUtilities; import engine.mobileAI.utilities.MovementUtilities; @@ -620,6 +621,22 @@ public class MobAI { try { + + boolean override = true; + switch (mob.BehaviourType) { + case GuardCaptain: + case GuardMinion: + case GuardWallArcher: + case Pet1: + case HamletGuard: + override = false; + break; + } + if(override){ + if(!mob.isSiege()) + StandardMob.run(mob); + } + //always check the respawn que, respawn 1 mob max per second to not flood the client if (mob == null)