diff --git a/src/engine/InterestManagement/InterestManager.java b/src/engine/InterestManagement/InterestManager.java index cd525d8d..24291887 100644 --- a/src/engine/InterestManagement/InterestManager.java +++ b/src/engine/InterestManagement/InterestManager.java @@ -10,8 +10,6 @@ package engine.InterestManagement; import engine.Enum.DispatchChannel; import engine.Enum.GameObjectType; -import engine.ai.MobileFSM; -import engine.ai.MobileFSM.STATE; import engine.gameManager.GroupManager; import engine.gameManager.SessionManager; import engine.job.JobScheduler; @@ -338,11 +336,12 @@ public enum InterestManager implements Runnable { if (!awonpc.isAlive() && (awonpc.isPet() || awonpc.isSiege() || awonpc.isNecroPet() || awonpc.isPlayerGuard())) continue; - if (awonpc.state.equals(STATE.Respawn) || awonpc.state.equals(STATE.Disabled)) + if (awonpc.isAlive() == false) continue; awonpc.playerAgroMap.put(player.getObjectUUID(), false); - MobileFSM.setAwake(awonpc, false); + //MobileFSM.setAwake(awonpc, false); + ((Mob)awonpc).setCombatTarget(null); // IVarController.setVariable(awonpc, "IntelligenceDisableDelay", (double) (System.currentTimeMillis() + 5000)); // awonpc.enableIntelligence(); lcm = new LoadCharacterMsg(awonpc, PlayerCharacter.hideNonAscii()); @@ -358,7 +357,8 @@ public enum InterestManager implements Runnable { awonpc.playerAgroMap.put(player.getObjectUUID(), false); if (awonpc.isMob()) - MobileFSM.setAwake(awonpc, false); + //MobileFSM.setAwake(awonpc, false); + ((Mob)awonpc).setCombatTarget(null); // IVarController.setVariable(awonpc, "IntelligenceDisableDelay", (double) (System.currentTimeMillis() + 5000)); // awonpc.enableIntelligence(); lcm = new LoadCharacterMsg(awonpc, PlayerCharacter.hideNonAscii()); diff --git a/src/engine/ai/MobileFSM.java b/src/engine/ai/MobileFSM.java index f82ce702..d76c621e 100644 --- a/src/engine/ai/MobileFSM.java +++ b/src/engine/ai/MobileFSM.java @@ -9,11 +9,7 @@ package engine.ai; - -import engine.Enum; import engine.Enum.DispatchChannel; -import engine.Enum.GameObjectType; -import engine.InterestManagement.WorldGrid; import engine.ai.utilities.CombatUtilities; import engine.ai.utilities.MovementUtilities; import engine.gameManager.BuildingManager; @@ -29,1425 +25,354 @@ import engine.objects.*; import engine.powers.ActionsBase; import engine.powers.PowersBase; import engine.server.MBServerStatics; -import org.pmw.tinylog.Logger; - import java.util.ArrayList; -import java.util.HashSet; +import java.util.HashMap; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; - import static engine.math.FastMath.sqr; - public class MobileFSM { - - public enum STATE { - Disabled, - Respawn, - Idle, - Awake, - Aggro, - Patrol, - Help, - Attack, - Home, - Dead, - Recalling, - Retaliate, - Chase + public enum MobBehaviourType { + //Power + Power(null, false, true, true, true, false), + PowerHelpee(Power, false, true, true, false, true), + PowerHelpeeWimpy(Power, true, false, true, false, false), + PowerGrouperWimpy(Power, true, false, true, false, false), + PowerAggro(Power, false, true, true, false, true), + PowerAggroHelpe(Power, false, true, true, false, true), + //Aggro + Aggro(null, false, true, true, true, false), + AggroHelpee(Aggro, false, true, true, false, true), + AggroHelpeeWimpy(Aggro, true, false, true, false, false), + AggroGrouperWimpy(Aggro, true, false, true, false, false), + //Spell + Spell(null, false, true, true, true, false), + SpellHelpee(Spell, false, true, true, false, true), + SpellHelpeeWimpy(Spell, true, false, true, false, false), + SpellGrouperWimpy(Spell, true, false, true, false, false), + SpellAggro(Spell, false, true, true, false, true), + SpellAggroHelpee(Spell, false, true, true, false, true), + SpellAggroHelpeeWimpy(Spell, true, false, true, false, false), + SpellAggroHelpeeEpic(Spell, false, true, true, false, true), + SpellAggroGrouperWimpy(Spell, true, false, true, false, false), + //Independent Types + SimpleStandingGuard(null, false, false, false, false, false), + Pet1(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); + + private static HashMap _behaviourTypes = new HashMap<>(); + public MobBehaviourType BehaviourHelperType; + public boolean isWimpy; + public boolean isAgressive; + public boolean canRoam; + public boolean callsForHelp; + public boolean respondsToCallForHelp; + + MobBehaviourType(MobBehaviourType helpeebehaviourType, boolean wimpy, boolean agressive, boolean canroam, boolean callsforhelp, boolean respondstocallforhelp) { + this.BehaviourHelperType = helpeebehaviourType; + this.isWimpy = wimpy; + this.isAgressive = agressive; + this.canRoam = canroam; + this.callsForHelp = callsforhelp; + this.respondsToCallForHelp = respondstocallforhelp; + } } + private static void mobAttack(Mob aiAgent) { - public static void run(Mob mob) { - if (mob == null) { + AbstractGameObject target = aiAgent.getCombatTarget(); + if (target == null) { return; } - STATE state = mob.state; - switch (state) { - case Idle: - if (mob.isAlive()) - mob.updateLocation(); - if (mob.isPlayerGuard()) { - guardAwake(mob); - break; + switch (target.getObjectType()) { + case PlayerCharacter: + PlayerCharacter player = (PlayerCharacter) target; + if (!player.isActive()) { + aiAgent.setCombatTarget(null); + CheckMobMovement(aiAgent); + return; } - idle(mob); - break; - case Awake: - if (mob.isAlive()) - mob.updateLocation(); - - if (mob.isPlayerGuard()) - guardAwake(mob); - else if (mob.isSiege() == false) { - if (mob.isPet()) - petAwake(mob); - else if (mob.isGuard()) - awakeNPCguard(mob); - else - awake(mob); + if (aiAgent.isNecroPet() && player.inSafeZone()) { + aiAgent.setCombatTarget(null); + return; } - break; - case Aggro: - if (mob.isAlive()) - mob.updateLocation(); - - if (mob.isPlayerGuard()) - guardAggro(mob, mob.getAggroTargetID()); - else if (mob.isGuard()) { - awakeNPCguard(mob); + if (canCast(aiAgent) == true) { + if (MobCast(aiAgent) == false) { + handlePlayerAttackForMob(aiAgent, player); + } } else { - aggro(mob, mob.getAggroTargetID()); - } - break; - case Patrol: - - if (mob.isAlive()) - mob.updateLocation(); - - if (mob.isPlayerGuard()) - guardPatrol(mob); - else - patrol(mob); - break; - case Attack: - if (mob.isAlive()) - mob.updateLocation(); - - - if (!mob.isCombat()) { - mob.setCombat(true); - UpdateStateMsg rwss = new UpdateStateMsg(); - rwss.setPlayer(mob); - DispatchMessage.sendToAllInRange(mob, rwss); + handlePlayerAttackForMob(aiAgent, player); } - if (mob.isPlayerGuard()) - guardAttack(mob); - else if (mob.isPet() || mob.isSiege()) - petAttack(mob); - else if (mob.isGuard()) - guardAttackMob(mob); - else - mobAttack(mob); - break; - case Home: - if (mob.isPlayerGuard()) - guardHome(mob, mob.isWalkingHome()); - else - home(mob, mob.isWalkingHome()); - break; - case Dead: - dead(mob); - break; - case Respawn: - respawn(mob); break; - case Recalling: - recalling(mob); - break; - case Retaliate: - retaliate(mob); - break; - case Chase: - handleMobChase(mob); + case Building: + Building building = (Building) target; + petHandleBuildingAttack(aiAgent, building); break; + case Mob: + Mob mob = (Mob) target; + handleMobAttackForMob(aiAgent, mob); } } + private static void petHandleBuildingAttack(Mob aiAgent, Building building) { - public static boolean setAwake(Mob aiAgent, boolean force) { - if (force) { - aiAgent.state = STATE.Awake; - return true; - } - if (aiAgent.state == STATE.Idle) { - aiAgent.state = STATE.Awake; - return true; - } - return false; - } - - public static boolean setAggro(Mob aiAgent, int targetID) { - if (aiAgent.state != STATE.Dead) { - aiAgent.setNoAggro(false); - aiAgent.setAggroTargetID(targetID); - aiAgent.state = STATE.Aggro; - return true; - } - return false; - } - private static void idle(Mob mob) { - - if (mob.getLoc().distanceSquared2D(mob.getBindLoc()) > sqr(2000)) { - - mob.setWalkingHome(false); - mob.state = STATE.Home; - } - } - private static void awake(Mob aiAgent) { - if (!aiAgent.isAlive()) { - aiAgent.state = STATE.Dead; - return; - } + int buildingHitBox = (int) CombatManager.calcHitBox(building); - if (aiAgent.getLoc().distanceSquared2D(aiAgent.getBindLoc()) > sqr(2000)) { - aiAgent.setWalkingHome(false); - aiAgent.state = STATE.Home; - return; - } - //Don't attempt to aggro if No aggro is on and aiAgent is not home yet. - if (aiAgent.isNoAggro() && aiAgent.isMoving()) { + if (building.getRank() == -1) { + aiAgent.setCombatTarget(null); return; } - //Mob stopped Moving let's turn aggro back on. - if (aiAgent.isNoAggro()) { - aiAgent.setNoAggro(false); - } - //no players currently have this mob loaded. return to IDLE. - if (aiAgent.playerAgroMap.isEmpty()) { - aiAgent.state = STATE.Idle; + if (!building.isVulnerable()) { + aiAgent.setCombatTarget(null); return; } - - //currently npc guards wont patrol or aggro - if (aiAgent.isGuard()) { + if (BuildingManager.getBuildingFromCache(building.getObjectUUID()) == null) { + aiAgent.setCombatTarget(null); return; } - //Get the Map for Players that loaded this mob. - - ConcurrentHashMap loadedPlayers = aiAgent.playerAgroMap; - - - if (!Enum.MobFlagType.AGGRESSIVE.elementOf(aiAgent.getMobBase().getFlags()) && aiAgent.getCombatTarget() == null) { - //attempt to patrol even if aiAgent isn't aggresive; - - int patrolRandom = ThreadLocalRandom.current().nextInt(1000); - if (patrolRandom <= MBServerStatics.AI_PATROL_DIVISOR) { - aiAgent.state = STATE.Patrol; - } - return; - } - //aiAgent finished moving home, set aggro on. + if (building.getParentZone() != null && building.getParentZone().isPlayerCity()) { - for (Entry playerEntry : loadedPlayers.entrySet()) { - int playerID = (int) playerEntry.getKey(); - PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerID); + for (Mob mob : building.getParentZone().zoneMobSet) { - //Player is null, let's remove them from the list. - if (loadedPlayer == null) { - // Logger.error("MobileFSM", "Player with UID " + playerID + " returned null in mob.getPlayerAgroMap()"); - loadedPlayers.remove(playerID); - continue; - } - //Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map. - if (!loadedPlayer.isAlive()) { - loadedPlayers.remove(playerID); - continue; - } - //Can't see target, skip aggro. - if (!aiAgent.canSee(loadedPlayer)) { - continue; - } + if (!mob.isPlayerGuard()) + continue; - // No aggro for this race type - if (loadedPlayer.getRace().getRaceType().getMonsterType().elementOf(aiAgent.notEnemy)) - continue; + if (mob.getCombatTarget() != null) + continue; + if (mob.getGuild() != null && building.getGuild() != null) + if (!Guild.sameGuild(mob.getGuild().getNation(), building.getGuild().getNation())) + continue; - if (MovementUtilities.inRangeToAggro(aiAgent, loadedPlayer)) { - aiAgent.setAggroTargetID(playerID); - aiAgent.state = STATE.Aggro; - return; + mob.setCombatTarget(aiAgent); } - - - } - - int patrolRandom = ThreadLocalRandom.current().nextInt(1000); - if (patrolRandom <= MBServerStatics.AI_PATROL_DIVISOR) { - aiAgent.state = STATE.Patrol; - } - - } - private static void guardAttackMob(Mob aiAgent) { - if (!aiAgent.isAlive()) { - aiAgent.state = STATE.Dead; - return; - } - - AbstractGameObject target = aiAgent.getCombatTarget(); - if (target == null) { - aiAgent.state = STATE.Awake; - return; - } - - if (target.getObjectType().equals(GameObjectType.Mob) == false) { - aiAgent.state = STATE.Awake; - return; - } - - if (target.equals(aiAgent)) { - aiAgent.state = STATE.Awake; - return; - } - - Mob mob = (Mob) target; - - if (!mob.isAlive() || mob.state == STATE.Dead) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - return; } - if (CombatUtilities.inRangeToAttack(aiAgent, mob)) { + if (CombatUtilities.inRangeToAttack(aiAgent, building)) { //not time to attack yet. - if (System.currentTimeMillis() < aiAgent.getLastAttackTime()) { - return; - } if (!CombatUtilities.RunAIRandom()) return; + if (System.currentTimeMillis() < aiAgent.getLastAttackTime()) + return; + if (aiAgent.getRange() >= 30 && aiAgent.isMoving()) return; + + //reset attack animation + if (aiAgent.isSiege()) + MovementManager.sendRWSSMsg(aiAgent); + + // Fire siege balls + // TODO: Fix animations not following stone + //no weapons, defualt mob attack speed 3 seconds. ItemBase mainHand = aiAgent.getWeaponItemBase(true); ItemBase offHand = aiAgent.getWeaponItemBase(false); + if (mainHand == null && offHand == null) { - CombatUtilities.combatCycle(aiAgent, mob, true, null); + + CombatUtilities.combatCycle(aiAgent, building, true, null); int delay = 3000; + if (aiAgent.isSiege()) - delay = 11000; - aiAgent.setLastAttackTime(System.currentTimeMillis() + delay); + delay = 15000; + aiAgent.setLastAttackTime(System.currentTimeMillis() + delay); } else //TODO set offhand attack time. if (aiAgent.getWeaponItemBase(true) != null) { + int attackDelay = 3000; + if (aiAgent.isSiege()) - attackDelay = 11000; - CombatUtilities.combatCycle(aiAgent, mob, true, aiAgent.getWeaponItemBase(true)); + attackDelay = 15000; + + CombatUtilities.combatCycle(aiAgent, building, true, aiAgent.getWeaponItemBase(true)); aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); + } else if (aiAgent.getWeaponItemBase(false) != null) { - int attackDelay = (int) (aiAgent.getSpeedHandTwo() * 100); + + int attackDelay = 3000; + if (aiAgent.isSiege()) - attackDelay = 3000; - CombatUtilities.combatCycle(aiAgent, mob, false, aiAgent.getWeaponItemBase(false)); + attackDelay = 15000; + + CombatUtilities.combatCycle(aiAgent, building, false, aiAgent.getWeaponItemBase(false)); aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); } - return; - } - if (!MovementUtilities.updateMovementToCharacter(aiAgent, mob)) - return; - - if (!MovementUtilities.canMove(aiAgent)) - return; - - double WeaponRange = aiAgent.getEquip().get(0).getItemBase().getRange(); - if (CombatUtilities.inRange2D(aiAgent, mob, WeaponRange)) + if (aiAgent.isSiege()) { + PowerProjectileMsg ppm = new PowerProjectileMsg(aiAgent, building); + ppm.setRange(50); + DispatchMessage.dispatchMsgToInterestArea(aiAgent, ppm, DispatchChannel.SECONDARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false); + } return; + } + //Outside of attack Range, Move to players predicted loc. - aiAgent.destination = MovementUtilities.GetDestinationToCharacter(aiAgent, mob); - - MovementUtilities.moveToLocation(aiAgent, aiAgent.destination, aiAgent.getRange()); + if (!aiAgent.isMoving()) + if (MovementUtilities.canMove(aiAgent)) + MovementUtilities.moveToLocation(aiAgent, building.getLoc(), aiAgent.getRange() + buildingHitBox); } - private static void awakeNPCguard(Mob aiAgent) { - if (!aiAgent.isAlive()) { - aiAgent.state = STATE.Dead; + private static void handlePlayerAttackForMob(Mob aiAgent, PlayerCharacter player) { + + if (aiAgent.getMobBase().getSeeInvis() < player.getHidden()) { + aiAgent.setCombatTarget(null); return; } - // Player guards are bound to their city zone - // and recall when leaving it. - - if (aiAgent.getLoc().distanceSquared2D(aiAgent.getBindLoc()) > sqr(2000)) { - aiAgent.setWalkingHome(false); - aiAgent.state = STATE.Home; + if (!player.isAlive()) { + aiAgent.setCombatTarget(null); return; } - //Don't attempt to aggro if No aggro is on and aiAgent is not home yet. - //no players currently have this mob loaded. return to IDLE. - //currently npc guards wont patrol or aggro - //Get the Map for Players that loaded this mob. - - HashSet awoList = WorldGrid.getObjectsInRangePartial(aiAgent, 100, MBServerStatics.MASK_MOB); - - for (AbstractWorldObject awoMob : awoList) { - - //dont scan self. - if (aiAgent.equals(awoMob)) - continue; - - Mob mob = (Mob) awoMob; - //dont attack other guards - if (mob.isGuard()) - continue; - if (aiAgent.getLoc().distanceSquared2D(mob.getLoc()) > sqr(50)) - continue; - aiAgent.setCombatTarget(mob); - aiAgent.state = STATE.Attack; + if (aiAgent.BehaviourType.callsForHelp) { + MobCallForHelp(aiAgent); } - } - private static void petAwake(Mob aiAgent) { - - if (!aiAgent.isAlive()) { - aiAgent.state = STATE.Dead; + if (!MovementUtilities.inRangeDropAggro(aiAgent, player)) { + aiAgent.setAggroTargetID(0); + aiAgent.setCombatTarget(null); + MovementUtilities.moveToLocation(aiAgent, aiAgent.getTrueBindLoc(), 0); return; } + if (CombatUtilities.inRange2D(aiAgent, player, aiAgent.getRange())) { - PlayerCharacter petOwner = aiAgent.getOwner(); - - if (petOwner == null) - return; - - //lets make mobs ai less twitchy, Don't call another movement until mob reaches it's destination. - if (aiAgent.isMoving()) - return; + //no weapons, defualt mob attack speed 3 seconds. - if (!MovementUtilities.canMove(aiAgent)) - return; + if (System.currentTimeMillis() < aiAgent.getLastAttackTime()) + return; - if (petOwner.getLoc().distanceSquared2D(aiAgent.getLoc()) > MBServerStatics.AI_RECALL_RANGE * MBServerStatics.AI_RECALL_RANGE) { - aiAgent.teleport(petOwner.getLoc()); - return; - } + //if (!CombatUtilities.RunAIRandom()) + // return; - if (petOwner.getLoc().distanceSquared2D(aiAgent.getLoc()) > 30 * 30) { + // ranged mobs cant attack while running. skip until they finally stop. + //if (aiAgent.getRange() >= 30 && aiAgent.isMoving()) if (aiAgent.isMoving()) return; - if (!MovementUtilities.canMove(aiAgent)) - return; - if (aiAgent.getLoc().distanceSquared2D(petOwner.getLoc()) < aiAgent.getRange() * aiAgent.getRange()) - return; - - MovementUtilities.moveToLocation(aiAgent, petOwner.getLoc(), aiAgent.getRange()); - } - } - private static void aggro(Mob aiAgent, int targetID) { - - if (!aiAgent.isAlive()) { - aiAgent.state = STATE.Dead; - return; - } - - if (aiAgent.getLoc().distanceSquared2D(aiAgent.getBindLoc()) > sqr(2000)) { - aiAgent.setWalkingHome(false); - aiAgent.state = STATE.Home; - return; - } - - if (!aiAgent.isCombat()) { - aiAgent.setCombat(true); - UpdateStateMsg rwss = new UpdateStateMsg(); - rwss.setPlayer(aiAgent); - DispatchMessage.sendToAllInRange(aiAgent, rwss); - } - - //a player got in aggro range. Move to player until in range of attack. - PlayerCharacter aggroTarget = PlayerCharacter.getFromCache(targetID); - - if (aggroTarget == null) { - // Logger.error("MobileFSM.aggro", "aggro target with UUID " + targetID + " returned null"); - aiAgent.playerAgroMap.remove(targetID); - aiAgent.setAggroTargetID(0); - aiAgent.state = STATE.Patrol; - return; - } - if (!aiAgent.canSee(aggroTarget)) { - aiAgent.setCombatTarget(null); - targetID = 0; - aiAgent.state = STATE.Patrol; - return; - } - - if (!aggroTarget.isActive()) { - aiAgent.setCombatTarget(null); - targetID = 0; - aiAgent.state = STATE.Patrol; - return; - } - aiAgent.setCombatTarget(aggroTarget); - if (canCast(aiAgent) == true) { - if (MobCast(aiAgent) == false) { - attack(aiAgent, targetID); - } - } else if (CombatUtilities.inRange2D(aiAgent, aggroTarget, aiAgent.getRange())) { - aiAgent.state = STATE.Attack; - attack(aiAgent, targetID); - return; - } - - if (!MovementUtilities.inRangeDropAggro(aiAgent, aggroTarget)) { - aiAgent.setAggroTargetID(0); - aiAgent.setCombatTarget(null); - MovementUtilities.moveToLocation(aiAgent, aiAgent.getTrueBindLoc(), 0); - aiAgent.state = STATE.Awake; - return; - } - - if (!MovementUtilities.inRangeOfBindLocation(aiAgent)) { - aiAgent.setCombatTarget(null); - aiAgent.setAggroTargetID(0); - aiAgent.state = STATE.Home; - return; - } - - //use this so mobs dont continue to try to move if they are underneath a flying target. only use 2D range check. - if (CombatUtilities.inRangeToAttack2D(aiAgent, aggroTarget)) - return; - - if (!MovementUtilities.updateMovementToCharacter(aiAgent, aggroTarget)) - return; - - if (!MovementUtilities.canMove(aiAgent)) - return; - - if (aiAgent.getLoc().distanceSquared2D(aggroTarget.getLoc()) < aiAgent.getRange() * aiAgent.getRange()) - return; - - aiAgent.destination = MovementUtilities.GetDestinationToCharacter(aiAgent, aggroTarget); - MovementUtilities.moveToLocation(aiAgent, aiAgent.destination, aiAgent.getRange()); - - } - private static void petAttack(Mob aiAgent) { - - if (!aiAgent.isAlive()) { - aiAgent.state = STATE.Dead; - return; - } - - AbstractGameObject target = aiAgent.getCombatTarget(); - - if (target == null) { - aiAgent.state = STATE.Awake; - return; - } - - switch (target.getObjectType()) { - - case PlayerCharacter: - - PlayerCharacter player = (PlayerCharacter) target; - - if (!player.isActive()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - return; - } - - if (player.inSafeZone()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - return; - } - - handlePlayerAttackForPet(aiAgent, player); - - break; - case Building: - Building building = (Building) target; - petHandleBuildingAttack(aiAgent, building); - break; - case Mob: - Mob mob = (Mob) target; - handleMobAttackForPet(aiAgent, mob); - break; - } - } - private static void mobAttack(Mob aiAgent) { - - if (!aiAgent.isAlive()) { - aiAgent.state = STATE.Dead; - return; - } - - if (aiAgent.getLoc().distanceSquared2D(aiAgent.getBindLoc()) > sqr(2000)) { - - aiAgent.setWalkingHome(false); - aiAgent.state = STATE.Home; - return; - } - - AbstractGameObject target = aiAgent.getCombatTarget(); - - if (target == null) { - aiAgent.state = STATE.Patrol; - return; - } - - switch (target.getObjectType()) { - - case PlayerCharacter: - - PlayerCharacter player = (PlayerCharacter) target; - - if (!player.isActive()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Patrol; - return; - } - - if (aiAgent.isNecroPet() && player.inSafeZone()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Idle; - return; - } - if (canCast(aiAgent) == true) { - if (MobCast(aiAgent) == false) { - handlePlayerAttackForMob(aiAgent, player); - } - } else { - handlePlayerAttackForMob(aiAgent, player); - } - break; - case Building: - Building building = (Building) target; - petHandleBuildingAttack(aiAgent, building); - break; - case Mob: - Mob mob = (Mob) target; - handleMobAttackForMob(aiAgent, mob); - } - } - private static void petHandleBuildingAttack(Mob aiAgent, Building building) { - - int buildingHitBox = (int) CombatManager.calcHitBox(building); - - if (building.getRank() == -1) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - return; - } - - if (!building.isVulnerable()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - return; - } - - if (BuildingManager.getBuildingFromCache(building.getObjectUUID()) == null) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - return; - } - - if (building.getParentZone() != null && building.getParentZone().isPlayerCity()) { - - for (Mob mob : building.getParentZone().zoneMobSet) { - - if (!mob.isPlayerGuard()) - continue; - - if (mob.getCombatTarget() != null) - continue; - - if (mob.getGuild() != null && building.getGuild() != null) - if (!Guild.sameGuild(mob.getGuild().getNation(), building.getGuild().getNation())) - continue; - - mob.setCombatTarget(aiAgent); - mob.state = STATE.Attack; - } - } - - if (CombatUtilities.inRangeToAttack(aiAgent, building)) { - //not time to attack yet. - - if (!CombatUtilities.RunAIRandom()) - return; - - if (System.currentTimeMillis() < aiAgent.getLastAttackTime()) - return; - - if (aiAgent.getRange() >= 30 && aiAgent.isMoving()) - return; - - //reset attack animation - if (aiAgent.isSiege()) - MovementManager.sendRWSSMsg(aiAgent); - - // Fire siege balls - // TODO: Fix animations not following stone - - //no weapons, defualt mob attack speed 3 seconds. - ItemBase mainHand = aiAgent.getWeaponItemBase(true); - ItemBase offHand = aiAgent.getWeaponItemBase(false); - - if (mainHand == null && offHand == null) { - - CombatUtilities.combatCycle(aiAgent, building, true, null); - int delay = 3000; - - if (aiAgent.isSiege()) - delay = 15000; - - aiAgent.setLastAttackTime(System.currentTimeMillis() + delay); - } else - //TODO set offhand attack time. - if (aiAgent.getWeaponItemBase(true) != null) { - - int attackDelay = 3000; - - if (aiAgent.isSiege()) - attackDelay = 15000; - - CombatUtilities.combatCycle(aiAgent, building, true, aiAgent.getWeaponItemBase(true)); - aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); - - } else if (aiAgent.getWeaponItemBase(false) != null) { - - int attackDelay = 3000; - - if (aiAgent.isSiege()) - attackDelay = 15000; - - CombatUtilities.combatCycle(aiAgent, building, false, aiAgent.getWeaponItemBase(false)); - aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); - } - - if (aiAgent.isSiege()) { - PowerProjectileMsg ppm = new PowerProjectileMsg(aiAgent, building); - ppm.setRange(50); - DispatchMessage.dispatchMsgToInterestArea(aiAgent, ppm, DispatchChannel.SECONDARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false); - } - return; - } - - //Outside of attack Range, Move to players predicted loc. - - if (!aiAgent.isMoving()) - if (MovementUtilities.canMove(aiAgent)) - MovementUtilities.moveToLocation(aiAgent, building.getLoc(), aiAgent.getRange() + buildingHitBox); - } - private static void handlePlayerAttackForPet(Mob aiAgent, PlayerCharacter player) { - - if (aiAgent.getMobBase().getSeeInvis() < player.getHidden()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - return; - } - - if (!player.isAlive()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - return; - } - - if (CombatUtilities.inRangeToAttack(aiAgent, player)) { - //not time to attack yet. - if (System.currentTimeMillis() < aiAgent.getLastAttackTime()) - return; - - if (!CombatUtilities.RunAIRandom()) - return; - - if (aiAgent.getRange() >= 30 && aiAgent.isMoving()) - return; - // add timer for last attack. - //player.setTimeStamp("LastCombatPlayer", System.currentTimeMillis()); - //no weapons, defualt mob attack speed 3 seconds. - ItemBase mainHand = aiAgent.getWeaponItemBase(true); - ItemBase offHand = aiAgent.getWeaponItemBase(false); - - if (mainHand == null && offHand == null) { - - CombatUtilities.combatCycle(aiAgent, player, true, null); - - int delay = 3000; - - if (aiAgent.isSiege()) - delay = 11000; - - aiAgent.setLastAttackTime(System.currentTimeMillis() + delay); - } - //TODO set offhand attack time. - - if (aiAgent.getWeaponItemBase(true) != null) { - - int attackDelay = 3000; - - if (aiAgent.isSiege()) - attackDelay = 11000; - - CombatUtilities.combatCycle(aiAgent, player, true, aiAgent.getWeaponItemBase(true)); - aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); - - } else if (aiAgent.getWeaponItemBase(false) != null) { - - int attackDelay = (int) (aiAgent.getSpeedHandTwo() * 100); - - if (aiAgent.isSiege()) - attackDelay = 3000; - - CombatUtilities.combatCycle(aiAgent, player, false, aiAgent.getWeaponItemBase(false)); - aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); - } - return; - } - - if (!MovementUtilities.updateMovementToCharacter(aiAgent, player)) - return; - - //out of range to attack move - if (!MovementUtilities.canMove(aiAgent)) - return; - - aiAgent.destination = MovementUtilities.GetDestinationToCharacter(aiAgent, player); - MovementUtilities.moveToLocation(aiAgent, aiAgent.destination, aiAgent.getRange()); - } - private static void handlePlayerAttackForMob(Mob aiAgent, PlayerCharacter player) { - - if (aiAgent.getMobBase().getSeeInvis() < player.getHidden()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - return; - } - - if (!player.isAlive()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - return; - } - - if (aiAgent.getMobBase().getFlags().contains(Enum.MobFlagType.CALLSFORHELP)) { - MobCallForHelp(aiAgent); - } - if (!MovementUtilities.inRangeOfBindLocation(aiAgent)) { - aiAgent.setCombatTarget(null); - aiAgent.setAggroTargetID(0); - aiAgent.setWalkingHome(false); - aiAgent.state = STATE.Home; - return; - } - if (!MovementUtilities.inRangeDropAggro(aiAgent, player)) { - aiAgent.setAggroTargetID(0); - aiAgent.setCombatTarget(null); - MovementUtilities.moveToLocation(aiAgent, aiAgent.getTrueBindLoc(), 0); - aiAgent.state = STATE.Awake; - return; - } - if (CombatUtilities.inRange2D(aiAgent, player, aiAgent.getRange())) { - - //no weapons, defualt mob attack speed 3 seconds. - - if (System.currentTimeMillis() < aiAgent.getLastAttackTime()) - return; - - //if (!CombatUtilities.RunAIRandom()) - // return; - - // ranged mobs cant attack while running. skip until they finally stop. - //if (aiAgent.getRange() >= 30 && aiAgent.isMoving()) - if(aiAgent.isMoving()) - return; - - // add timer for last attack. - // player.setTimeStamp("LastCombatPlayer", System.currentTimeMillis()); - ItemBase mainHand = aiAgent.getWeaponItemBase(true); - ItemBase offHand = aiAgent.getWeaponItemBase(false); - - if (mainHand == null && offHand == null) { - - CombatUtilities.combatCycle(aiAgent, player, true, null); - int delay = 3000; - - if (aiAgent.isSiege()) - delay = 11000; - - aiAgent.setLastAttackTime(System.currentTimeMillis() + delay); - - } else - //TODO set offhand attack time. - if (aiAgent.getWeaponItemBase(true) != null) { - - int delay = 3000; - - if (aiAgent.isSiege()) - delay = 11000; - - CombatUtilities.combatCycle(aiAgent, player, true, aiAgent.getWeaponItemBase(true)); - aiAgent.setLastAttackTime(System.currentTimeMillis() + delay); - } else if (aiAgent.getWeaponItemBase(false) != null) { - - int attackDelay = 3000; - - if (aiAgent.isSiege()) - attackDelay = 11000; - if (aiAgent.getMobBase().getFlags().contains(Enum.MobFlagType.CALLSFORHELP)) { - MobCallForHelp(aiAgent); - } - CombatUtilities.combatCycle(aiAgent, player, false, aiAgent.getWeaponItemBase(false)); - aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); - } - return; - } - - if (!MovementUtilities.updateMovementToCharacter(aiAgent, player)) - return; - - if (!MovementUtilities.canMove(aiAgent)) - return; - - //this stops mobs from attempting to move while they are underneath a player. - if (CombatUtilities.inRangeToAttack2D(aiAgent, player)) - return; - //set mob to pursue target - aiAgent.state = STATE.Chase; - } - private static void handleMobAttackForPet(Mob aiAgent, Mob mob) { - - if (!mob.isAlive()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - return; - } - - if (CombatUtilities.inRangeToAttack(aiAgent, mob)) { - //not time to attack yet. - if (System.currentTimeMillis() < aiAgent.getLastAttackTime()) - return; - - if (!CombatUtilities.RunAIRandom()) - return; - - if (aiAgent.getRange() >= 30 && aiAgent.isMoving()) - return; - - //no weapons, defualt mob attack speed 3 seconds. - ItemBase mainHand = aiAgent.getWeaponItemBase(true); - ItemBase offHand = aiAgent.getWeaponItemBase(false); - - if (mainHand == null && offHand == null) { - - CombatUtilities.combatCycle(aiAgent, mob, true, null); - - int delay = 3000; - - if (aiAgent.isSiege()) - delay = 11000; - - aiAgent.setLastAttackTime(System.currentTimeMillis() + delay); - - } else - //TODO set offhand attack time. - if (aiAgent.getWeaponItemBase(true) != null) { - - int attackDelay = 3000; - - if (aiAgent.isSiege()) - attackDelay = 11000; - - CombatUtilities.combatCycle(aiAgent, mob, true, aiAgent.getWeaponItemBase(true)); - aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); - - } else if (aiAgent.getWeaponItemBase(false) != null) { - - int attackDelay = (int) (aiAgent.getSpeedHandTwo() * 100); - - if (aiAgent.isSiege()) - attackDelay = 3000; - - CombatUtilities.combatCycle(aiAgent, mob, false, aiAgent.getWeaponItemBase(false)); - aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); - } - return; - } - - if (!MovementUtilities.updateMovementToCharacter(aiAgent, mob)) - return; - - if (!MovementUtilities.canMove(aiAgent)) - return; - - if (CombatUtilities.inRangeToAttack2D(aiAgent, mob)) - return; - - aiAgent.destination = MovementUtilities.GetDestinationToCharacter(aiAgent, mob); - MovementUtilities.moveToLocation(aiAgent, aiAgent.destination, aiAgent.getRange()); - } - private static void handleMobAttackForMob(Mob aiAgent, Mob mob) { - - - if (!mob.isAlive()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - return; - } - - if (CombatUtilities.inRangeToAttack(aiAgent, mob)) { - //not time to attack yet. - if (System.currentTimeMillis() < aiAgent.getLastAttackTime()) { - return; - } - - if (!CombatUtilities.RunAIRandom()) - return; - - if (aiAgent.getRange() >= 30 && aiAgent.isMoving()) - return; - //no weapons, defualt mob attack speed 3 seconds. - ItemBase mainHand = aiAgent.getWeaponItemBase(true); - ItemBase offHand = aiAgent.getWeaponItemBase(false); + // add timer for last attack. + // player.setTimeStamp("LastCombatPlayer", System.currentTimeMillis()); + ItemBase mainHand = aiAgent.getWeaponItemBase(true); + ItemBase offHand = aiAgent.getWeaponItemBase(false); if (mainHand == null && offHand == null) { - CombatUtilities.combatCycle(aiAgent, mob, true, null); + CombatUtilities.combatCycle(aiAgent, player, true, null); int delay = 3000; if (aiAgent.isSiege()) delay = 11000; aiAgent.setLastAttackTime(System.currentTimeMillis() + delay); + } else //TODO set offhand attack time. if (aiAgent.getWeaponItemBase(true) != null) { - int attackDelay = 3000; + int delay = 3000; if (aiAgent.isSiege()) - attackDelay = 11000; - - CombatUtilities.combatCycle(aiAgent, mob, true, aiAgent.getWeaponItemBase(true)); - aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); + delay = 11000; + CombatUtilities.combatCycle(aiAgent, player, true, aiAgent.getWeaponItemBase(true)); + aiAgent.setLastAttackTime(System.currentTimeMillis() + delay); } else if (aiAgent.getWeaponItemBase(false) != null) { int attackDelay = 3000; if (aiAgent.isSiege()) attackDelay = 11000; - - CombatUtilities.combatCycle(aiAgent, mob, false, aiAgent.getWeaponItemBase(false)); - aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); - } - return; - } - - //use this so mobs dont continue to try to move if they are underneath a flying target. only use 2D range check. - if (CombatUtilities.inRangeToAttack2D(aiAgent, mob)) - return; - - if (!MovementUtilities.updateMovementToCharacter(aiAgent, mob)) - return; - - //out of range to attack move - if (!MovementUtilities.canMove(aiAgent)) - return; - - aiAgent.destination = MovementUtilities.GetDestinationToCharacter(aiAgent, mob); - MovementUtilities.moveToLocation(aiAgent, aiAgent.destination, aiAgent.getRange()); - } - private static void attack(Mob aiAgent, int targetID) { - - //in range to attack, start attacking now! - if (!aiAgent.isAlive()) { - aiAgent.state = STATE.Dead; - return; - } - - PlayerCharacter aggroTarget = PlayerCharacter.getFromCache(targetID); - - if (aggroTarget == null) { - // Logger.error("MobileFSM.aggro", "aggro target with UUID " + targetID + " returned null"); - aiAgent.playerAgroMap.remove(targetID); - aiAgent.setAggroTargetID(0); - aiAgent.state = STATE.Patrol; - return; - } - - if (aiAgent.getMobBase().getSeeInvis() < aggroTarget.getHidden()) { - aiAgent.setAggroTargetID(0); - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Patrol; - return; - } - - if (!aggroTarget.isAlive()) { - aiAgent.setAggroTargetID(0); - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Patrol; - return; - } - - if (!MovementUtilities.inRangeOfBindLocation(aiAgent)) { - aiAgent.setCombatTarget(null); - aiAgent.setAggroTargetID(0); - aiAgent.setWalkingHome(false); - aiAgent.state = STATE.Home; - return; - } - - if (!MovementUtilities.inRangeDropAggro(aiAgent, aggroTarget)) { - aiAgent.setAggroTargetID(0); - aiAgent.setCombatTarget(null); - MovementUtilities.moveToLocation(aiAgent, aiAgent.getTrueBindLoc(), 0); - aiAgent.state = STATE.Awake; - return; - } - - - if (CombatUtilities.inRangeToAttack(aiAgent, aggroTarget)) { - - if (aiAgent.getCombatTarget() == null) - aiAgent.setCombatTarget(aggroTarget); - - if (!CombatUtilities.RunAIRandom()) - return; - - //not time to attack yet. - if (System.currentTimeMillis() < aiAgent.getLastAttackTime()) - return; - - if (aiAgent.getRange() >= 30 && aiAgent.isMoving()) - return; - - //no weapons, defualt mob attack speed 3 seconds. - ItemBase mainHand = aiAgent.getWeaponItemBase(true); - ItemBase offHand = aiAgent.getWeaponItemBase(false); - - if (mainHand == null && offHand == null) { - CombatUtilities.combatCycle(aiAgent, aggroTarget, true, null); - aiAgent.setLastAttackTime(System.currentTimeMillis() + 3000); - } else - //TODO set offhand attack time. - if (aiAgent.getWeaponItemBase(true) != null) { - - int attackDelay = 3000; - - CombatUtilities.combatCycle(aiAgent, aggroTarget, true, aiAgent.getWeaponItemBase(true)); - aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); - } else if (aiAgent.getWeaponItemBase(false) != null) { - - int attackDelay = 3000; - - CombatUtilities.combatCycle(aiAgent, aggroTarget, false, aiAgent.getWeaponItemBase(false)); - aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); - } - return; - } - - //use this so mobs dont continue to try to move if they are underneath a flying target. only use 2D range check. - if (CombatUtilities.inRangeToAttack2D(aiAgent, aggroTarget)) - return; - - if (!MovementUtilities.canMove(aiAgent)) - return; - - if (!MovementUtilities.updateMovementToCharacter(aiAgent, aggroTarget)) - return; - - aiAgent.destination = MovementUtilities.GetDestinationToCharacter(aiAgent, aggroTarget); - MovementUtilities.moveToLocation(aiAgent, aiAgent.destination, aiAgent.getRange()); - } - private static void home(Mob aiAgent, boolean walk) { - - //recall home. - MovementManager.translocate(aiAgent, aiAgent.getBindLoc(), null); - aiAgent.setAggroTargetID(0); - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; - } - private static void recalling(Mob aiAgent) { - //recall home. - if (aiAgent.getLoc() == aiAgent.getBindLoc()) - aiAgent.state = STATE.Awake; - - if (aiAgent.getLoc().distanceSquared2D(aiAgent.getBindLoc()) > sqr(2000)) { - - aiAgent.setWalkingHome(false); - aiAgent.state = STATE.Home; - } - } - private static void patrol(Mob aiAgent) { - - MobBase mobbase = aiAgent.getMobBase(); - - if (mobbase != null && (Enum.MobFlagType.SENTINEL.elementOf(mobbase.getFlags()) || !Enum.MobFlagType.CANROAM.elementOf(mobbase.getFlags()))) { - aiAgent.state = STATE.Awake; - return; - } - - if (MovementUtilities.canMove(aiAgent) && !aiAgent.isMoving()) { - - float patrolRadius = aiAgent.getSpawnRadius(); - - if (patrolRadius > 256) - patrolRadius = 256; - - if (patrolRadius < 60) - patrolRadius = 60; - - MovementUtilities.aiMove(aiAgent, Vector3fImmutable.getRandomPointInCircle(aiAgent.getBindLoc(), patrolRadius), true); - } - aiAgent.state = STATE.Awake; - } - private static void dead(Mob aiAgent) { - //Despawn Timer with Loot currently in inventory. - if (aiAgent.getCharItemManager().getInventoryCount() > 0) { - if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_WITH_LOOT) { - aiAgent.despawn(); - //update time of death after mob despawns so respawn time happens after mob despawns. - aiAgent.setDeathTime(System.currentTimeMillis()); - aiAgent.state = STATE.Respawn; - } - - //No items in inventory. - } else { - //Mob's Loot has been looted. - if (aiAgent.isHasLoot()) { - if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) { - aiAgent.despawn(); - //update time of death after mob despawns so respawn time happens after mob despawns. - aiAgent.setDeathTime(System.currentTimeMillis()); - aiAgent.state = STATE.Respawn; - } - //Mob never had Loot. - } else { - if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER) { - aiAgent.despawn(); - //update time of death after mob despawns so respawn time happens after mob despawns. - aiAgent.setDeathTime(System.currentTimeMillis()); - aiAgent.state = STATE.Respawn; - } - } - } - } - private static void guardAwake(Mob aiAgent) { - - if (!aiAgent.isAlive()) { - aiAgent.state = STATE.Dead; - return; - } - - if (aiAgent.getLoc().distanceSquared2D(aiAgent.getBindLoc()) > sqr(2000)) { - - aiAgent.setWalkingHome(false); - aiAgent.state = STATE.Home; - return; - } - - //Don't attempt to aggro if No aggro is on and aiAgent is not home yet. - - //Mob stopped Moving let's turn aggro back on. - if (aiAgent.isNoAggro()) - aiAgent.setNoAggro(false); - - // do nothing if no players are around. - if (aiAgent.playerAgroMap.isEmpty()) - return; - - //Get the Map for Players that loaded this mob. - - ConcurrentHashMap loadedPlayers = aiAgent.playerAgroMap; - - //no players currently have this mob loaded. return to IDLE. - //aiAgent finished moving home, set aggro on. - - for (Entry playerEntry : loadedPlayers.entrySet()) { - - int playerID = (int) playerEntry.getKey(); - - PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerID); - - //Player is null, let's remove them from the list. - if (loadedPlayer == null) { - // Logger.error("MobileFSM", "Player with UID " + playerID + " returned null in mob.getPlayerAgroMap()"); - loadedPlayers.remove(playerID); - continue; - } - - //Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map. - if (!loadedPlayer.isAlive()) { - loadedPlayers.remove(playerID); - continue; - } - - //Can't see target, skip aggro. - if (!aiAgent.canSee(loadedPlayer)) { - continue; - } - - //Guard aggro check - - boolean aggro = false; - Zone cityZone = aiAgent.getParentZone(); - - if (cityZone != null) { - City city = City.GetCityFromCache(cityZone.getPlayerCityUUID()); - if (city != null) { - - Building tol = city.getTOL(); - - if (tol != null) { - if (tol.reverseKOS) { - - aggro = true; - - for (Condemned condemned : tol.getCondemned().values()) { - switch (condemned.getFriendType()) { - case Condemned.NATION: - if (loadedPlayer.getGuild() != null && loadedPlayer.getGuild().getNation() != null) - if (loadedPlayer.getGuild().getNation().getObjectUUID() == condemned.getGuildUID()) - if (condemned.isActive()) - aggro = false; - break; - case Condemned.GUILD: - if (loadedPlayer.getGuild() != null) - if (loadedPlayer.getGuild().getObjectUUID() == condemned.getGuildUID()) - if (condemned.isActive()) - aggro = false; - break; - case Condemned.INDIVIDUAL: - if (loadedPlayer.getObjectUUID() == condemned.getPlayerUID()) - if (condemned.isActive()) - aggro = false; - break; - } - } - } else { - aggro = false; - - for (Condemned condemned : tol.getCondemned().values()) { - switch (condemned.getFriendType()) { - case Condemned.NATION: - if (loadedPlayer.getGuild() != null && loadedPlayer.getGuild().getNation() != null) - if (loadedPlayer.getGuild().getNation().getObjectUUID() == condemned.getGuildUID()) - if (condemned.isActive()) - aggro = true; - break; - case Condemned.GUILD: - if (loadedPlayer.getGuild() != null) - if (loadedPlayer.getGuild().getObjectUUID() == condemned.getGuildUID()) - if (condemned.isActive()) - aggro = true; - break; - case Condemned.INDIVIDUAL: - if (loadedPlayer.getObjectUUID() == condemned.getPlayerUID()) - if (condemned.isActive()) - aggro = true; - break; - } - } - } + if (aiAgent.BehaviourType.callsForHelp) { + MobCallForHelp(aiAgent); } - } - - if (loadedPlayer.getGuild() != null && loadedPlayer.getGuild().getNation() != null && city.getGuild() != null) - if (Guild.sameGuild(loadedPlayer.getGuild().getNation(), city.getGuild().getNation())) - aggro = false; - - } - - //lets make sure we dont aggro players in the nation. - - if (aggro) { - if (CombatUtilities.inRangeToAttack(aiAgent, loadedPlayer)) { - aiAgent.setAggroTargetID(playerID); - aiAgent.state = STATE.Aggro; - return; - } - - if (MovementUtilities.inRangeToAggro(aiAgent, loadedPlayer)) { - aiAgent.setAggroTargetID(playerID); - aiAgent.state = STATE.Aggro; - return; - } - } - } - - //attempt to patrol even if aiAgent isn't aggresive; - if (aiAgent.isMoving() == false) - aiAgent.state = STATE.Patrol; - } - private static void guardAggro(Mob aiAgent, int targetID) { - - if (!aiAgent.isAlive()) { - aiAgent.state = STATE.Dead; - return; - } - - if (!aiAgent.isCombat()) { - aiAgent.setCombat(true); - UpdateStateMsg rwss = new UpdateStateMsg(); - rwss.setPlayer(aiAgent); - DispatchMessage.sendToAllInRange(aiAgent, rwss); - } - - //a player got in aggro range. Move to player until in range of attack. - PlayerCharacter aggroTarget = PlayerCharacter.getFromCache(targetID); - - if (aggroTarget == null) { - aiAgent.state = STATE.Patrol; + CombatUtilities.combatCycle(aiAgent, player, false, aiAgent.getWeaponItemBase(false)); + aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); + } return; } - if (!aiAgent.canSee(aggroTarget)) { - aiAgent.setCombatTarget(null); - targetID = 0; - aiAgent.state = STATE.Patrol; + if (!MovementUtilities.updateMovementToCharacter(aiAgent, player)) return; - } - if (!aggroTarget.isActive()) { - aiAgent.setCombatTarget(null); - targetID = 0; - aiAgent.state = STATE.Patrol; - return; - } - if (CombatUtilities.inRangeToAttack(aiAgent, aggroTarget)) { - aiAgent.setCombatTarget(aggroTarget); - aiAgent.state = STATE.Attack; - guardAttack(aiAgent); + if (!MovementUtilities.canMove(aiAgent)) return; - } - //use this so mobs dont continue to try to move if they are underneath a flying target. only use 2D range check. - if (CombatUtilities.inRangeToAttack2D(aiAgent, aggroTarget)) + //this stops mobs from attempting to move while they are underneath a player. + if (CombatUtilities.inRangeToAttack2D(aiAgent, player)) return; + } + private static void handleMobAttackForMob(Mob aiAgent, Mob mob) { - if (!MovementUtilities.canMove(aiAgent)) - return; - if (!MovementUtilities.inRangeDropAggro(aiAgent, aggroTarget)) { - aiAgent.setAggroTargetID(0); + if (!mob.isAlive()) { aiAgent.setCombatTarget(null); - MovementUtilities.moveToLocation(aiAgent, aiAgent.getTrueBindLoc(), 0); - aiAgent.state = STATE.Awake; return; } - if (!MovementUtilities.inRangeOfBindLocation(aiAgent)) { - aiAgent.setCombatTarget(null); - aiAgent.setAggroTargetID(0); - aiAgent.setWalkingHome(false); - aiAgent.state = STATE.Home; - return; - } + if (CombatUtilities.inRangeToAttack(aiAgent, mob)) { + //not time to attack yet. + if (System.currentTimeMillis() < aiAgent.getLastAttackTime()) { + return; + } - if (!MovementUtilities.updateMovementToCharacter(aiAgent, aggroTarget)) - return; + if (!CombatUtilities.RunAIRandom()) + return; - //Outside of attack Range, Move to players predicted loc. + if (aiAgent.getRange() >= 30 && aiAgent.isMoving()) + return; + //no weapons, defualt mob attack speed 3 seconds. + ItemBase mainHand = aiAgent.getWeaponItemBase(true); + ItemBase offHand = aiAgent.getWeaponItemBase(false); - if (aiAgent.getLoc().distanceSquared2D(aggroTarget.getLoc()) < aiAgent.getRange() * aiAgent.getRange()) - return; - aiAgent.destination = MovementUtilities.GetDestinationToCharacter(aiAgent, aggroTarget); - MovementUtilities.moveToLocation(aiAgent, aiAgent.destination, aiAgent.getRange()); + if (mainHand == null && offHand == null) { - } - private static void guardPatrol(Mob aiAgent) { + CombatUtilities.combatCycle(aiAgent, mob, true, null); + int delay = 3000; + + if (aiAgent.isSiege()) + delay = 11000; + + aiAgent.setLastAttackTime(System.currentTimeMillis() + delay); + } else + //TODO set offhand attack time. + if (aiAgent.getWeaponItemBase(true) != null) { + + int attackDelay = 3000; + + if (aiAgent.isSiege()) + attackDelay = 11000; + + CombatUtilities.combatCycle(aiAgent, mob, true, aiAgent.getWeaponItemBase(true)); + aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); + + } else if (aiAgent.getWeaponItemBase(false) != null) { + + int attackDelay = 3000; + + if (aiAgent.isSiege()) + attackDelay = 11000; - if (aiAgent.playerAgroMap.isEmpty()) { - aiAgent.state = STATE.Awake; + CombatUtilities.combatCycle(aiAgent, mob, false, aiAgent.getWeaponItemBase(false)); + aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay); + } return; } + //use this so mobs dont continue to try to move if they are underneath a flying target. only use 2D range check. + if (CombatUtilities.inRangeToAttack2D(aiAgent, mob)) + return; + + if (!MovementUtilities.updateMovementToCharacter(aiAgent, mob)) + return; + } + private static void guardPatrol(Mob aiAgent) { if (aiAgent.isCombat() && aiAgent.getCombatTarget() == null) { aiAgent.setCombat(false); UpdateStateMsg rwss = new UpdateStateMsg(); @@ -1464,16 +389,9 @@ public class MobileFSM { rwss.setPlayer(aiAgent); DispatchMessage.sendToAllInRange(aiAgent, rwss); } - - if (aiAgent.isMoving()) { - aiAgent.state = STATE.Awake; - return; - } - Building barrack = aiAgent.building; if (barrack == null) { - aiAgent.state = STATE.Awake; return; } @@ -1485,8 +403,6 @@ public class MobileFSM { MovementUtilities.aiMove(aiAgent, MovementUtilities.randomPatrolLocation(aiAgent, aiAgent.getBindLoc(), buildingHitBox * 2), true); } } - - aiAgent.state = STATE.Awake; return; } @@ -1503,22 +419,18 @@ public class MobileFSM { Building barrack = ((Mob) aiAgent.npcOwner).building; if (barrack == null) { - aiAgent.state = STATE.Awake; return; } if (barrack.getPatrolPoints() == null) { - aiAgent.state = STATE.Awake; return; } if (barrack.getPatrolPoints().isEmpty()) { - aiAgent.state = STATE.Awake; return; } if (aiAgent.isMoving()) { - aiAgent.state = STATE.Awake; return; } @@ -1534,69 +446,10 @@ public class MobileFSM { if (patrolLoc != null) { if (MovementUtilities.canMove(aiAgent)) { MovementUtilities.aiMove(aiAgent, patrolLoc, true); - aiAgent.state = STATE.Awake; } } } } - aiAgent.state = STATE.Awake; - } - private static void guardAttack(Mob aiAgent) { - - if (!aiAgent.isAlive()) { - aiAgent.state = STATE.Dead; - return; - } - - AbstractGameObject target = aiAgent.getCombatTarget(); - - if (target == null) { - aiAgent.state = STATE.Patrol; - return; - } - - switch (target.getObjectType()) { - case PlayerCharacter: - - PlayerCharacter player = (PlayerCharacter) target; - - if (!player.isActive()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Patrol; - return; - } - - if (aiAgent.isNecroPet() && player.inSafeZone()) { - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Idle; - return; - } - if (canCast(aiAgent) == true) { - if (MobCast(aiAgent) == false) { - handlePlayerAttackForMob(aiAgent, player); - } - } else { - handlePlayerAttackForMob(aiAgent, player); - } - break; - case Building: - Logger.info("PLAYER GUARD ATTEMPTING TO ATTACK BUILDING IN " + aiAgent.getParentZone().getName()); - aiAgent.state = STATE.Awake; - break; - case Mob: - Mob mob = (Mob) target; - handleMobAttackForMob(aiAgent, mob); - } - } - private static void guardHome(Mob aiAgent, boolean walk) { - - //recall home. - PowersBase recall = PowersManager.getPowerByToken(-1994153779); - PowersManager.useMobPower(aiAgent, aiAgent, recall, 40); - - aiAgent.setAggroTargetID(0); - aiAgent.setCombatTarget(null); - aiAgent.state = STATE.Awake; } private static void respawn(Mob aiAgent) { @@ -1610,45 +463,25 @@ public class MobileFSM { if (System.currentTimeMillis() > aiAgent.deathTime + spawnTime) { aiAgent.respawn(); - aiAgent.state = STATE.Idle; - } - } - private static void retaliate(Mob aiAgent) { - - if (aiAgent.getCombatTarget() == null) - aiAgent.state = STATE.Awake; - - //out of range to attack move - if (!MovementUtilities.canMove(aiAgent)) { - aiAgent.state = STATE.Attack; - return; + aiAgent.setCombatTarget(null); } - - aiAgent.state = STATE.Attack; - - //lets make mobs ai less twitchy, Don't call another movement until mob reaches it's destination. - if (aiAgent.isMoving()) - return; - - MovementUtilities.moveToLocation(aiAgent, aiAgent.getCombatTarget().getLoc(), aiAgent.getRange()); } public static boolean canCast(Mob mob) { // Performs validation to determine if a // mobile in the proper state to cast. - if(mob == null) + if (mob == null) return false; - if(mob.mobPowers.isEmpty()) + if (mob.mobPowers.isEmpty()) return false; - if(mob.nextCastTime == 0) + if (mob.nextCastTime == 0) mob.nextCastTime = System.currentTimeMillis(); return mob.nextCastTime <= System.currentTimeMillis(); } - public static boolean MobCast(Mob mob) { // Method picks a random spell from a mobile's list of powers @@ -1659,7 +492,7 @@ public class MobileFSM { ArrayList purgeTokens; PlayerCharacter target = (PlayerCharacter) mob.getCombatTarget(); - if (mob.getMobBase().getFlags().contains(Enum.MobFlagType.CALLSFORHELP)) + if (mob.BehaviourType.callsForHelp) MobCallForHelp(mob); // Generate a list of tokens from the mob powers for this mobile. @@ -1670,11 +503,11 @@ public class MobileFSM { // If player has this effect on them currently then remove // this token from our list. - for (int powerToken : powerTokens){ + for (int powerToken : powerTokens) { - PowersBase powerBase= PowersManager.getPowerByToken(powerToken); + PowersBase powerBase = PowersManager.getPowerByToken(powerToken); - for(ActionsBase actionBase : powerBase.getActions()){ + for (ActionsBase actionBase : powerBase.getActions()) { String stackType = actionBase.stackType; @@ -1723,52 +556,203 @@ public class MobileFSM { return true; } - return false; - } - + return false; + } public static void MobCallForHelp(Mob mob) { - if(mob.nextCallForHelp == 0){ + if (mob.nextCallForHelp == 0) { mob.nextCallForHelp = System.currentTimeMillis(); } - if(mob.nextCallForHelp < System.currentTimeMillis()){ + if (mob.nextCallForHelp < System.currentTimeMillis()) { return; } Zone mobCamp = mob.getParentZone(); - for (Mob mob1 : mobCamp.zoneMobSet) { - if (mob1.getMobBase().getFlags().contains(Enum.MobFlagType.RESPONDSTOCALLSFORHELP)) { - if (mob1.state == STATE.Awake) { - if (CombatUtilities.inRange2D(mob, mob1, mob.getAggroRange()) == true) { - MovementUtilities.moveToLocation(mob1, mob.getLoc(), 0); - } - } + for (Mob helper : mobCamp.zoneMobSet) { + if (helper.BehaviourType.respondsToCallForHelp && helper.BehaviourType.BehaviourHelperType.equals(mob.BehaviourType)) { + helper.setCombatTarget(mob.getCombatTarget()); } } //wait 60 seconds to call for help again mob.nextCallForHelp = System.currentTimeMillis() + 60000; } - public static void handleMobChase(Mob mob){ - if (!MovementUtilities.inRangeOfBindLocation(mob)) { - mob.setCombatTarget(null); - mob.setAggroTargetID(0); - mob.setWalkingHome(false); - mob.state = STATE.Home; + public static void run(Mob mob) { + if (mob == null) { + return; + } + if (mob.isAlive() == false) { + //no need to continue if mob is dead, check for respawn and move on + CheckForRespawn(mob); + return; + } + //check to see if mob has wandered too far from his bind loc + CheckToSendMobHome(mob); + //check to see if players have mob loaded + if (mob.playerAgroMap.isEmpty()) { + //no players loaded, no need to proceed + return; + } + //check for players that can be aggroed if mob is agressive and has no target + if (mob.BehaviourType.isAgressive && mob.getCombatTarget() == null) { + CheckForAggro(mob); + } + //check if mob can move for patrol or moving to target + if (mob.BehaviourType.canRoam) { + CheckMobMovement(mob); + } + //check if mob can attack if it isn't wimpy + if (!mob.BehaviourType.isWimpy && !mob.isMoving()) { + CheckForAttack(mob); + } + } + private static void CheckForAggro(Mob aiAgent) { + //looks for and sets mobs combatTarget + if (!aiAgent.isAlive()) { return; } - mob.updateMovementState(); - mob.updateLocation(); - if(CombatUtilities.inRange2D(mob,mob.getCombatTarget(), mob.getRange()) == true) { - MovementUtilities.moveToLocation(mob, mob.getLoc(), 0); - mob.state = STATE.Attack; + ConcurrentHashMap loadedPlayers = aiAgent.playerAgroMap; + for (Entry playerEntry : loadedPlayers.entrySet()) { + int playerID = (int) playerEntry.getKey(); + PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerID); + //Player is null, let's remove them from the list. + if (loadedPlayer == null) { + loadedPlayers.remove(playerID); + continue; + } + //Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map. + if (!loadedPlayer.isAlive()) { + loadedPlayers.remove(playerID); + continue; + } + //Can't see target, skip aggro. + if (!aiAgent.canSee(loadedPlayer)) { + continue; + } + // No aggro for this race type + if(aiAgent.notEnemy.contains(loadedPlayer.getRace().getRaceType())) + continue; + if (MovementUtilities.inRangeToAggro(aiAgent, loadedPlayer)) { + aiAgent.setAggroTargetID(playerID); + return; + } + } + } + private static void CheckMobMovement(Mob mob) { + if (mob.getCombatTarget() == null) { + //patrol + int patrolRandom = ThreadLocalRandom.current().nextInt(1000); + if (patrolRandom <= MBServerStatics.AI_PATROL_DIVISOR) { + if (MovementUtilities.canMove(mob) && !mob.isMoving()) { + if (mob.isPlayerGuard()) { + guardPatrol(mob); + return; + } + float patrolRadius = mob.getSpawnRadius(); + + if (patrolRadius > 256) + patrolRadius = 256; + + if (patrolRadius < 60) + patrolRadius = 60; + + MovementUtilities.aiMove(mob, Vector3fImmutable.getRandomPointInCircle(mob.getBindLoc(), patrolRadius), true); + } else { + //chase target + mob.updateMovementState(); + mob.updateLocation(); + if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mob.getRange()) == false) { + if (mob.getRange() > 15) { + mob.destination = mob.getCombatTarget().getLoc(); + MovementUtilities.moveToLocation(mob, mob.destination, 0); + } else { + mob.destination = MovementUtilities.GetDestinationToCharacter(mob, (AbstractCharacter) mob.getCombatTarget()); + MovementUtilities.moveToLocation(mob, mob.destination, mob.getRange()); + } + } + } + } + } + } + private static void CheckForRespawn(Mob aiAgent) { + //handles checking for respawn of dead mobs even when no players have mob loaded + //Despawn Timer with Loot currently in inventory. + if (aiAgent.getCharItemManager().getInventoryCount() > 0) { + if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_WITH_LOOT) { + aiAgent.despawn(); + //update time of death after mob despawns so respawn time happens after mob despawns. + aiAgent.setDeathTime(System.currentTimeMillis()); + respawn(aiAgent); + } + + //No items in inventory. + } else { + //Mob's Loot has been looted. + if (aiAgent.isHasLoot()) { + if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) { + aiAgent.despawn(); + //update time of death after mob despawns so respawn time happens after mob despawns. + aiAgent.setDeathTime(System.currentTimeMillis()); + respawn(aiAgent); + } + //Mob never had Loot. + } else { + if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER) { + aiAgent.despawn(); + //update time of death after mob despawns so respawn time happens after mob despawns. + aiAgent.setDeathTime(System.currentTimeMillis()); + respawn(aiAgent); + } + } + } + + } + public static void CheckForAttack(Mob mob) { + //checks if mob can attack based on attack timer and range + if (mob.isAlive()) + mob.updateLocation(); + if (!mob.isCombat()) { + mob.setCombat(true); + UpdateStateMsg rwss = new UpdateStateMsg(); + rwss.setPlayer(mob); + DispatchMessage.sendToAllInRange(mob, rwss); + } + mobAttack(mob); + } + private static void CheckToSendMobHome(Mob mob) { + if (mob.getLoc().distanceSquared2D(mob.getBindLoc()) > sqr(2000)) { + PowersBase recall = PowersManager.getPowerByToken(-1994153779); + PowersManager.useMobPower(mob, mob, recall, 40); + mob.setAggroTargetID(0); + mob.setCombatTarget(null); } - else {//if (mob.isMoving() == false){ - if(mob.getRange() > 15) { - mob.destination = mob.getCombatTarget().getLoc(); - MovementUtilities.moveToLocation(mob, mob.destination, 0); - } else{ - mob.destination = MovementUtilities.GetDestinationToCharacter(mob, (AbstractCharacter) mob.getCombatTarget()); - MovementUtilities.moveToLocation(mob, mob.destination, mob.getRange()); + } + public static void dead(Mob aiAgent) { + //Despawn Timer with Loot currently in inventory. + if (aiAgent.getCharItemManager().getInventoryCount() > 0) { + if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_WITH_LOOT) { + aiAgent.despawn(); + //update time of death after mob despawns so respawn time happens after mob despawns. + aiAgent.setDeathTime(System.currentTimeMillis()); + //aiAgent.state = STATE.Respawn; } + //No items in inventory. + } else { + //Mob's Loot has been looted. + if (aiAgent.isHasLoot()) { + if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) { + aiAgent.despawn(); + //update time of death after mob despawns so respawn time happens after mob despawns. + aiAgent.setDeathTime(System.currentTimeMillis()); + //aiAgent.state = STATE.Respawn; + } + //Mob never had Loot. + } else { + if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER) { + aiAgent.despawn(); + //update time of death after mob despawns so respawn time happens after mob despawns. + aiAgent.setDeathTime(System.currentTimeMillis()); + //aiAgent.state = STATE.Respawn; + } + } } } -} +} \ No newline at end of file diff --git a/src/engine/db/handlers/dbMobHandler.java b/src/engine/db/handlers/dbMobHandler.java index fb8bccd1..dfc85902 100644 --- a/src/engine/db/handlers/dbMobHandler.java +++ b/src/engine/db/handlers/dbMobHandler.java @@ -9,7 +9,6 @@ package engine.db.handlers; -import engine.ai.MobileFSM.STATE; import engine.gameManager.NPCManager; import engine.objects.Mob; import engine.objects.Zone; @@ -124,9 +123,8 @@ public class dbMobHandler extends dbHandlerBase { toCreate.setTimeToSpawnSiege(System.currentTimeMillis() + MBServerStatics.FIFTEEN_MINUTES); toCreate.setDeathTime(System.currentTimeMillis()); - toCreate.state = STATE.Respawn; - } + } } diff --git a/src/engine/devcmd/cmds/InfoCmd.java b/src/engine/devcmd/cmds/InfoCmd.java index 4f1642dd..d20aa32a 100644 --- a/src/engine/devcmd/cmds/InfoCmd.java +++ b/src/engine/devcmd/cmds/InfoCmd.java @@ -458,7 +458,7 @@ public class InfoCmd extends AbstractDevCmd { output += StringUtils.addWS("isAlive: " + targetMob.isAlive(), 20); output += newline; - output += "Mob State: " + targetMob.state.name(); + //output += "Mob State: " + targetMob.state.name(); output += newline; output += "Speed : " + targetMob.getSpeed(); diff --git a/src/engine/gameManager/CombatManager.java b/src/engine/gameManager/CombatManager.java index f654af90..97221070 100644 --- a/src/engine/gameManager/CombatManager.java +++ b/src/engine/gameManager/CombatManager.java @@ -9,7 +9,6 @@ package engine.gameManager; import engine.Enum.*; -import engine.ai.MobileFSM.STATE; import engine.exception.MsgSendException; import engine.job.JobContainer; import engine.job.JobScheduler; @@ -183,7 +182,6 @@ public enum CombatManager { //set sources target pet.setCombatTarget(target); - pet.state = STATE.Attack; // setFirstHitCombatTarget(player,target); //put in combat if not already @@ -691,7 +689,6 @@ public enum CombatManager { count++; mob.setCombatTarget(ac); - mob.state = STATE.Attack; } } } @@ -1339,7 +1336,6 @@ public enum CombatManager { Mob pet = ((PlayerCharacter) tarAc).getPet(); if (pet != null && pet.assist() && pet.getCombatTarget() == null) { pet.setCombatTarget(ac); - pet.state = STATE.Retaliate; } } @@ -1351,7 +1347,6 @@ public enum CombatManager { if (ac.getObjectType() == GameObjectType.Mob && retaliater.isSiege()) return; retaliater.setCombatTarget(ac); - retaliater.state = STATE.Retaliate; } } diff --git a/src/engine/gameManager/NPCManager.java b/src/engine/gameManager/NPCManager.java index 7262f2d8..e55a9acb 100644 --- a/src/engine/gameManager/NPCManager.java +++ b/src/engine/gameManager/NPCManager.java @@ -2,7 +2,6 @@ package engine.gameManager; import engine.Enum; import engine.InterestManagement.WorldGrid; -import engine.ai.MobileFSM; import engine.math.Vector3fImmutable; import engine.net.Dispatch; import engine.net.DispatchMessage; @@ -115,8 +114,6 @@ public enum NPCManager { public static void dismissNecroPet(Mob necroPet, boolean updateOwner) { - necroPet.state = MobileFSM.STATE.Disabled; - necroPet.combatTarget = null; necroPet.hasLoot = false; @@ -202,7 +199,6 @@ public enum NPCManager { try { dismissNecroPet(necroPet, true); } catch (Exception e) { - necroPet.state = MobileFSM.STATE.Disabled; Logger.error(e); } } @@ -333,7 +329,6 @@ public enum NPCManager { mob.deathTime = System.currentTimeMillis(); mob.spawnTime = 900; mob.npcOwner = guardCaptain; - mob.state = MobileFSM.STATE.Respawn; return mob; } @@ -342,12 +337,9 @@ public enum NPCManager { for (Mob toRemove : mobile.siegeMinionMap.keySet()) { - toRemove.state = MobileFSM.STATE.Disabled; - if (mobile.isMoving()) { mobile.stopMovement(mobile.getLoc()); - mobile.state = MobileFSM.STATE.Disabled; if (toRemove.parentZone != null) toRemove.parentZone.zoneMobSet.remove(toRemove); @@ -383,7 +375,6 @@ public enum NPCManager { public static boolean removeMobileFromBuilding(Mob mobile, Building building) { // Remove npc from it's building - mobile.state = MobileFSM.STATE.Disabled; try { mobile.clearEffects(); diff --git a/src/engine/net/client/ClientMessagePump.java b/src/engine/net/client/ClientMessagePump.java index 4d715c3c..59cff4e0 100644 --- a/src/engine/net/client/ClientMessagePump.java +++ b/src/engine/net/client/ClientMessagePump.java @@ -12,7 +12,6 @@ package engine.net.client; import engine.Enum.*; import engine.InterestManagement.WorldGrid; -import engine.ai.MobileFSM.STATE; import engine.exception.MsgSendException; import engine.gameManager.*; import engine.job.JobContainer; @@ -2026,7 +2025,6 @@ public class ClientMessagePump implements NetMsgHandler { if (pet.getCombatTarget() == null) return; - pet.state = STATE.Attack; } protected static void petCmd(PetCmdMsg msg, ClientConnection conn) throws MsgSendException { @@ -2044,15 +2042,14 @@ public class ClientMessagePump implements NetMsgHandler { if (!pet.isAlive()) return; - if (pet.state == STATE.Disabled) - return; + //if (pet.state == STATE.Disabled) + // return; int type = msg.getType(); if (type == 1) { //stop attack pet.setCombatTarget(null); pc.setCombat(false); - pet.state = STATE.Awake; } else if (type == 2) { //dismiss diff --git a/src/engine/net/client/handlers/MinionTrainingMsgHandler.java b/src/engine/net/client/handlers/MinionTrainingMsgHandler.java index 558caf1a..291af9b1 100644 --- a/src/engine/net/client/handlers/MinionTrainingMsgHandler.java +++ b/src/engine/net/client/handlers/MinionTrainingMsgHandler.java @@ -3,7 +3,6 @@ package engine.net.client.handlers; import engine.Enum; import engine.Enum.DispatchChannel; import engine.InterestManagement.WorldGrid; -import engine.ai.MobileFSM; import engine.exception.MsgSendException; import engine.gameManager.BuildingManager; import engine.gameManager.DbManager; @@ -67,7 +66,6 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler { if (!npc.getSiegeMinionMap().containsKey(toRemove)) return true; - toRemove.state = MobileFSM.STATE.Disabled; npc.getSiegeMinionMap().remove(toRemove); //toRemove.disableIntelligence(); @@ -160,7 +158,6 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler { toCreate.setSpawnTime(60 * 15); toCreate.setTimeToSpawnSiege(System.currentTimeMillis() + (60 * 15 * 1000)); toCreate.setDeathTime(System.currentTimeMillis()); - toCreate.state = MobileFSM.STATE.Respawn; } } @@ -199,7 +196,6 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler { if (!DbManager.MobQueries.REMOVE_FROM_GUARDS(npc.getObjectUUID(), toRemove.getMobBaseID(), npc.getSiegeMinionMap().get(toRemove))) return true; - toRemove.state = MobileFSM.STATE.Disabled; npc.getSiegeMinionMap().remove(toRemove); //toRemove.disableIntelligence(); @@ -293,7 +289,6 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler { if (toCreate != null) { toCreate.setTimeToSpawnSiege(System.currentTimeMillis() + MBServerStatics.FIFTEEN_MINUTES); toCreate.setDeathTime(System.currentTimeMillis()); - toCreate.state = MobileFSM.STATE.Respawn; } } diff --git a/src/engine/objects/AbstractIntelligenceAgent.java b/src/engine/objects/AbstractIntelligenceAgent.java index ce119020..0ec562b3 100644 --- a/src/engine/objects/AbstractIntelligenceAgent.java +++ b/src/engine/objects/AbstractIntelligenceAgent.java @@ -14,7 +14,6 @@ import engine.Enum.GameObjectType; import engine.Enum.ModType; import engine.Enum.SourceType; import engine.InterestManagement.WorldGrid; -import engine.ai.MobileFSM.STATE; import engine.gameManager.ZoneManager; import engine.math.Vector3fImmutable; import engine.net.Dispatch; @@ -204,7 +203,7 @@ public abstract class AbstractIntelligenceAgent extends AbstractCharacter { WorldGrid.RemoveWorldObject(this); if (this.getObjectType() == GameObjectType.Mob){ - ((Mob)this).state = STATE.Disabled; + //((Mob)this).state = STATE.Disabled; if (((Mob)this).getParentZone() != null) ((Mob)this).getParentZone().zoneMobSet.remove(this); } diff --git a/src/engine/objects/Mob.java b/src/engine/objects/Mob.java index 5eca55b0..e5f519d3 100644 --- a/src/engine/objects/Mob.java +++ b/src/engine/objects/Mob.java @@ -8,13 +8,11 @@ package engine.objects; - import ch.claude_martin.enumbitset.EnumBitSet; import engine.Enum; import engine.Enum.*; import engine.InterestManagement.WorldGrid; import engine.ai.MobileFSM; -import engine.ai.MobileFSM.STATE; import engine.exception.SerializationException; import engine.gameManager.*; import engine.job.JobContainer; @@ -35,7 +33,6 @@ import engine.net.client.msg.PlaceAssetMsg; import engine.server.MBServerStatics; import org.joda.time.DateTime; import org.pmw.tinylog.Logger; - import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; @@ -44,7 +41,6 @@ import java.util.HashSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.locks.ReentrantReadWriteLock; - import static engine.net.client.msg.ErrorPopupMsg.sendErrorPopup; public class Mob extends AbstractIntelligenceAgent { @@ -89,7 +85,6 @@ public class Mob extends AbstractIntelligenceAgent { public AbstractCharacter npcOwner; public Vector3fImmutable inBuildingLoc = null; private boolean noAggro = false; - public STATE state = STATE.Disabled; private int aggroTargetID = 0; private boolean walkingHome = true; private long lastAttackTime = 0; @@ -110,7 +105,7 @@ public class Mob extends AbstractIntelligenceAgent { public EnumBitSet notEnemy; public EnumBitSet enemy; - + public MobileFSM.MobBehaviourType BehaviourType; /** * No Id Constructor */ @@ -122,7 +117,7 @@ public class Mob extends AbstractIntelligenceAgent { walk, combat, bindLoc, currentLoc, faceDir, healthCurrent, manaCurrent, stamCurrent, guild, runningTrains); this.dbID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET; - this.state = STATE.Idle; + //this.state = STATE.Idle; this.loadID = npcType; this.isMob = isMob; this.mobBase = MobBase.getMobBase(loadID); @@ -155,7 +150,7 @@ public class Mob extends AbstractIntelligenceAgent { byte runningTrains, int npcType, boolean isMob, Zone parent, int newUUID, Building building, int contractID) { super(firstName, lastName, statStrCurrent, statDexCurrent, statConCurrent, statIntCurrent, statSpiCurrent, level, exp, sit, walk, combat, bindLoc, currentLoc, faceDir, healthCurrent, manaCurrent, stamCurrent, guild, runningTrains, newUUID); - this.state = STATE.Idle; + //this.state = STATE.Idle; this.dbID = newUUID; this.loadID = npcType; this.isMob = isMob; @@ -178,7 +173,7 @@ public class Mob extends AbstractIntelligenceAgent { */ public Mob(MobBase mobBase, Guild guild, Zone parent, short level, PlayerCharacter owner, int tableID) { super(mobBase.getFirstName(), "", (short) 0, (short) 0, (short) 0, (short) 0, (short) 0, level, 0, false, true, false, owner.getLoc(), owner.getLoc(), owner.getFaceDir(), (short) mobBase.getHealthMax(), (short) 0, (short) 0, guild, (byte) 0, tableID); - this.state = STATE.Idle; + //this.state = STATE.Idle; this.dbID = tableID; this.loadID = mobBase.getObjectUUID(); this.isMob = true; @@ -214,7 +209,7 @@ public class Mob extends AbstractIntelligenceAgent { try { this.dbID = rs.getInt(1); - this.state = STATE.Idle; + //this.state = STATE.Idle; this.loadID = rs.getInt("mob_mobbaseID"); this.gridObjectType = GridObjectType.DYNAMIC; this.spawnRadius = rs.getFloat("mob_spawnRadius"); @@ -298,7 +293,7 @@ public class Mob extends AbstractIntelligenceAgent { this.equipmentSetID = this.contract.getEquipmentSet(); this.nameOverride = rs.getString("mob_name"); - + this.BehaviourType = MobileFSM.MobBehaviourType.valueOf(rs.getString("fsm")); } catch (Exception e) { Logger.error(currentID + ""); } @@ -650,7 +645,7 @@ public class Mob extends AbstractIntelligenceAgent { DbManager.addToCache(mob); mob.setPet(owner, true); mob.setWalkMode(false); - mob.state = STATE.Awake; + //mob.state = STATE.Awake; } catch (Exception e) { Logger.error(e); @@ -717,7 +712,7 @@ public class Mob extends AbstractIntelligenceAgent { //target is mob's combat target, LETS GO. if (source.getHateValue() > target.getHateValue()) { mob.setCombatTarget(source); - MobileFSM.setAggro(mob, source.getObjectUUID()); + //MobileFSM.setAggro(mob, source.getObjectUUID()); } } } @@ -1144,8 +1139,8 @@ public class Mob extends AbstractIntelligenceAgent { if (!this.isMoving()) return; - if (state == STATE.Disabled) - return; + //if (state == STATE.Disabled) + // return; if (this.isAlive() == false || this.getBonuses().getBool(ModType.Stunned, SourceType.None) || this.getBonuses().getBool(ModType.CannotMove, SourceType.None)) { //Target is stunned or rooted. Don't move @@ -1185,7 +1180,8 @@ public class Mob extends AbstractIntelligenceAgent { try { if (this.isSiege) { this.deathTime = System.currentTimeMillis(); - this.state = STATE.Dead; + //this.state = STATE.Dead; + MobileFSM.dead(this); try { this.clearEffects(); } catch (Exception e) { @@ -1211,7 +1207,7 @@ public class Mob extends AbstractIntelligenceAgent { } } else if (this.isPet() || this.isNecroPet()) { - this.state = STATE.Disabled; + //this.state = STATE.Disabled; this.combatTarget = null; this.hasLoot = false; @@ -1248,7 +1244,8 @@ public class Mob extends AbstractIntelligenceAgent { //cleanup effects this.deathTime = System.currentTimeMillis(); - this.state = STATE.Dead; + //this.state = STATE.Dead; + MobileFSM.dead(this); playerAgroMap.clear(); @@ -2037,7 +2034,8 @@ public class Mob extends AbstractIntelligenceAgent { PlayerCharacter player = (PlayerCharacter) ac; if (this.getCombatTarget() == null) { - MobileFSM.setAggro(this, player.getObjectUUID()); + //MobileFSM.setAggro(this, player.getObjectUUID()); + this.combatTarget = ac; return; } @@ -2048,7 +2046,7 @@ public class Mob extends AbstractIntelligenceAgent { if (ac.getHateValue() > ((PlayerCharacter) this.getCombatTarget()).getHateValue()) { this.setCombatTarget(player); - MobileFSM.setAggro(this, player.getObjectUUID()); + //MobileFSM.setAggro(this, player.getObjectUUID()); } } } @@ -2329,7 +2327,7 @@ public class Mob extends AbstractIntelligenceAgent { WorldGrid.RemoveWorldObject(this); DbManager.removeFromCache(this); if (this.getObjectType() == GameObjectType.Mob) { - this.state = STATE.Disabled; + //this.state = STATE.Disabled; if (this.getParentZone() != null) this.getParentZone().zoneMobSet.remove(this); } diff --git a/src/engine/objects/NPC.java b/src/engine/objects/NPC.java index c4b9203e..450d2e4f 100644 --- a/src/engine/objects/NPC.java +++ b/src/engine/objects/NPC.java @@ -12,7 +12,6 @@ package engine.objects; import engine.Enum; import engine.Enum.*; import engine.InterestManagement.WorldGrid; -import engine.ai.MobileFSM.STATE; import engine.exception.SerializationException; import engine.gameManager.*; import engine.job.JobContainer; @@ -790,7 +789,6 @@ public class NPC extends AbstractCharacter { for (Mob toRemove : this.siegeMinionMap.keySet()) { - toRemove.state = STATE.Disabled; try { toRemove.clearEffects(); @@ -1461,7 +1459,6 @@ public class NPC extends AbstractCharacter { mob.setSpawnTime(10); mob.setNpcOwner(this); - mob.state = STATE.Awake; mob.region = AbstractWorldObject.GetRegionByWorldObject(mob); return mob; } diff --git a/src/engine/objects/PlayerCharacter.java b/src/engine/objects/PlayerCharacter.java index bf2ada16..d107d479 100644 --- a/src/engine/objects/PlayerCharacter.java +++ b/src/engine/objects/PlayerCharacter.java @@ -15,7 +15,6 @@ import engine.InterestManagement.HeightMap; import engine.InterestManagement.InterestManager; import engine.InterestManagement.RealmMap; import engine.InterestManagement.WorldGrid; -import engine.ai.MobileFSM.STATE; import engine.db.archive.CharacterRecord; import engine.db.archive.DataWarehouse; import engine.db.archive.PvpRecord; @@ -4580,7 +4579,6 @@ public class PlayerCharacter extends AbstractCharacter { if (!currentPet.isSiege()) { currentPet.setCombatTarget(null); - currentPet.state = STATE.Disabled; if (currentPet.getParentZone() != null) diff --git a/src/engine/powers/poweractions/ApplyEffectPowerAction.java b/src/engine/powers/poweractions/ApplyEffectPowerAction.java index 95c5ae2f..1c0b58b0 100644 --- a/src/engine/powers/poweractions/ApplyEffectPowerAction.java +++ b/src/engine/powers/poweractions/ApplyEffectPowerAction.java @@ -125,7 +125,7 @@ public class ApplyEffectPowerAction extends AbstractPowerAction { if (this.effectID.equals("TAUNT")){ if (awo != null && awo.getObjectType() == GameObjectType.Mob){ - MobileFSM.setAggro((Mob)awo,source.getObjectUUID()); + ((Mob) awo).setCombatTarget(source); ChatSystemMsg msg = ChatManager.CombatInfo(source, awo); DispatchMessage.sendToAllInRange(source, msg); } @@ -252,7 +252,7 @@ public class ApplyEffectPowerAction extends AbstractPowerAction { if (this.effectID.equals("TAUNT")){ if (awo != null && awo.getObjectType() == GameObjectType.Mob){ - MobileFSM.setAggro((Mob)awo,source.getObjectUUID()); + ((Mob) awo).setCombatTarget(source); ChatSystemMsg msg = ChatManager.CombatInfo(source, awo); DispatchMessage.sendToAllInRange(source, msg); } diff --git a/src/engine/powers/poweractions/ClearAggroPowerAction.java b/src/engine/powers/poweractions/ClearAggroPowerAction.java index ce62b610..a21e15b1 100644 --- a/src/engine/powers/poweractions/ClearAggroPowerAction.java +++ b/src/engine/powers/poweractions/ClearAggroPowerAction.java @@ -10,7 +10,6 @@ package engine.powers.poweractions; import engine.Enum.GameObjectType; -import engine.ai.MobileFSM.STATE; import engine.math.Vector3fImmutable; import engine.objects.AbstractCharacter; import engine.objects.AbstractWorldObject; @@ -32,7 +31,6 @@ public class ClearAggroPowerAction extends AbstractPowerAction { protected void _startAction(AbstractCharacter source, AbstractWorldObject awo, Vector3fImmutable targetLoc, int trains, ActionsBase ab, PowersBase pb) { if (awo != null && awo.getObjectType() == GameObjectType.Mob){ ((Mob)awo).setNoAggro(true); - ((Mob)awo).state = STATE.Patrol; } diff --git a/src/engine/powers/poweractions/ClearNearbyAggroPowerAction.java b/src/engine/powers/poweractions/ClearNearbyAggroPowerAction.java index 33ee2f04..af0a0ac7 100644 --- a/src/engine/powers/poweractions/ClearNearbyAggroPowerAction.java +++ b/src/engine/powers/poweractions/ClearNearbyAggroPowerAction.java @@ -10,11 +10,9 @@ package engine.powers.poweractions; import engine.Enum.GameObjectType; -import engine.ai.MobileFSM.STATE; import engine.math.Vector3fImmutable; import engine.objects.AbstractCharacter; import engine.objects.AbstractWorldObject; -import engine.objects.Mob; import engine.powers.ActionsBase; import engine.powers.PowersBase; @@ -31,7 +29,6 @@ public class ClearNearbyAggroPowerAction extends AbstractPowerAction { @Override protected void _startAction(AbstractCharacter source, AbstractWorldObject awo, Vector3fImmutable targetLoc, int trains, ActionsBase ab, PowersBase pb) { if (source.getObjectType() == GameObjectType.Mob){ - ((Mob)source).state = STATE.Patrol; } } diff --git a/src/engine/powers/poweractions/CreateMobPowerAction.java b/src/engine/powers/poweractions/CreateMobPowerAction.java index 0eb499d5..35f894c0 100644 --- a/src/engine/powers/poweractions/CreateMobPowerAction.java +++ b/src/engine/powers/poweractions/CreateMobPowerAction.java @@ -11,7 +11,6 @@ package engine.powers.poweractions; import engine.Enum; import engine.InterestManagement.WorldGrid; -import engine.ai.MobileFSM.STATE; import engine.gameManager.DbManager; import engine.gameManager.NPCManager; import engine.gameManager.ZoneManager; @@ -82,7 +81,6 @@ public class CreateMobPowerAction extends AbstractPowerAction { if(currentPet!= null && !currentPet.isNecroPet() && !currentPet.isSiege()) { DbManager.removeFromCache(currentPet); WorldGrid.RemoveWorldObject(currentPet); - currentPet.state = STATE.Disabled; currentPet.setCombatTarget(null); if (currentPet.getParentZone() != null) @@ -116,7 +114,6 @@ public class CreateMobPowerAction extends AbstractPowerAction { if(!currentPet.isNecroPet() && !currentPet.isSiege()) { DbManager.removeFromCache(currentPet); currentPet.setCombatTarget(null); - currentPet.state = STATE.Disabled; currentPet.setOwner(null); WorldGrid.RemoveWorldObject(currentPet); diff --git a/src/engine/powers/poweractions/MobRecallPowerAction.java b/src/engine/powers/poweractions/MobRecallPowerAction.java index af5a1250..f71ad1b3 100644 --- a/src/engine/powers/poweractions/MobRecallPowerAction.java +++ b/src/engine/powers/poweractions/MobRecallPowerAction.java @@ -41,7 +41,8 @@ public class MobRecallPowerAction extends AbstractPowerAction { MovementManager.translocate(awoac,awoac.getBindLoc(), null); if (awoac.getObjectType() == GameObjectType.Mob){ - MobileFSM.setAwake((Mob)awoac,true); + //MobileFSM.setAwake((Mob)awoac,true); + ((Mob)awoac).setCombatTarget(null); } diff --git a/src/engine/powers/poweractions/RecallPowerAction.java b/src/engine/powers/poweractions/RecallPowerAction.java index 3462a363..16a8bf39 100644 --- a/src/engine/powers/poweractions/RecallPowerAction.java +++ b/src/engine/powers/poweractions/RecallPowerAction.java @@ -67,7 +67,7 @@ public class RecallPowerAction extends AbstractPowerAction { awoac.setBindLoc(MBServerStatics.startX, MBServerStatics.startY, MBServerStatics.startZ); awoac.teleport(awoac.getBindLoc()); if (awoac.getObjectType() == GameObjectType.Mob){ - MobileFSM.setAwake((Mob)awoac,true); + ((Mob)awoac).setCombatTarget(null); if (awoac.isAlive()) WorldGrid.updateObject(awoac); }