diff --git a/src/engine/mobileAI/MobAI.java b/src/engine/mobileAI/MobAI.java index 571532a0..a9c8b992 100644 --- a/src/engine/mobileAI/MobAI.java +++ b/src/engine/mobileAI/MobAI.java @@ -18,17 +18,16 @@ import engine.mobileAI.Threads.MobAIThread; import engine.mobileAI.utilities.CombatUtilities; import engine.mobileAI.utilities.MovementUtilities; import engine.net.DispatchMessage; -import engine.net.client.msg.PerformActionMsg; import engine.net.client.msg.PowerProjectileMsg; +import engine.net.client.msg.UpdateStateMsg; 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.Map.Entry; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; @@ -54,18 +53,6 @@ public class MobAI { return; } } - if (target.getObjectType() == Enum.GameObjectType.PlayerCharacter && canCast(mob)) { - - if (mob.isPlayerGuard() == false && MobCast(mob)) { - mob.updateLocation(); - return; - } - - if (mob.isPlayerGuard() == true && GuardCast(mob)) { - mob.updateLocation(); - return; - } - } if (!CombatUtilities.inRangeToAttack(mob, target)) return; @@ -85,8 +72,6 @@ public class MobAI { break; } - mob.updateLocation(); - } catch (Exception e) { Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackTarget" + " " + e.getMessage()); } @@ -148,7 +133,7 @@ public class MobAI { } if (target.getPet() != null) - if (target.getPet().getCombatTarget() == null && target.getPet().assist == true) + if (target.getPet().getCombatTarget() == null && target.getPet().assist) target.getPet().setCombatTarget(mob); } catch (Exception e) { @@ -251,7 +236,7 @@ public class MobAI { if(target.isAlive()) target.setCombatTarget(mob); - if(target.isPet() && target.isAlive() == false && target.guardCaptain.isAlive() == true){ + if(target.isPet() && !target.isAlive() && target.guardCaptain.isAlive()){ mob.setCombatTarget(target.guardCaptain); } if(mob.isPet()){ @@ -272,7 +257,7 @@ public class MobAI { //early exit while waiting to patrol again - if (mob.stopPatrolTime + (patrolDelay * 1000) > System.currentTimeMillis()) + if (mob.stopPatrolTime + (patrolDelay * 1000L) > System.currentTimeMillis()) return; //guard captains inherit barracks patrol points dynamically @@ -302,7 +287,7 @@ public class MobAI { //make sure mob is out of combat stance - if (minion.getKey().despawned == false) { + if (!minion.getKey().despawned) { if (MovementUtilities.canMove(minion.getKey())) { Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3); minion.getKey().updateLocation(); @@ -315,253 +300,6 @@ public class MobAI { } } - public static boolean canCast(Mob mob) { - return false; - //try { - - // Performs validation to determine if a - // mobile in the proper state to cast. - - //if (mob == null) - // return false; - - //if(mob.isPlayerGuard == true){ - - /// int contractID; - - // if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion)) - // contractID = mob.guardCaptain.contract.getContractID(); - // else - // contractID = mob.contract.getContractID(); - - // if(Enum.MinionType.ContractToMinionMap.get(contractID).isMage() == false) - // return false; - //} - - //if (mob.mobPowers.isEmpty()) - // return false; - - //if (!mob.canSee((PlayerCharacter) mob.getCombatTarget())) { - // mob.setCombatTarget(null); - // return false; - // } - // if (mob.nextCastTime == 0) - // mob.nextCastTime = System.currentTimeMillis(); - - // return mob.nextCastTime >= System.currentTimeMillis(); - - //} catch (Exception e) { - // Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: canCast" + " " + e.getMessage()); - //} - //return false; - } - - public static boolean MobCast(Mob mob) { - - try { - // Method picks a random spell from a mobile's list of powers - // and casts it on the current target (or itself). Validation - // (including empty lists) is done previously within canCast(); - - ArrayList powerTokens; - ArrayList purgeTokens; - AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); - - if (mob.behaviourType.callsForHelp) - MobCallForHelp(mob); - - // Generate a list of tokens from the mob powers for this mobile. - - powerTokens = new ArrayList<>(mob.mobPowers.keySet()); - purgeTokens = new ArrayList<>(); - - // If player has this effect on them currently then remove - // this token from our list. - - for (int powerToken : powerTokens) { - - PowersBase powerBase = PowersManager.getPowerByToken(powerToken); - - for (ActionsBase actionBase : powerBase.getActions()) { - - String stackType = actionBase.stackType; - - if (target.getEffects() != null && target.getEffects().containsKey(stackType)) - purgeTokens.add(powerToken); - } - } - - powerTokens.removeAll(purgeTokens); - - // Sanity check - - if (powerTokens.isEmpty()) - return false; - - // Pick random spell from our list of powers - - int powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); - int powerRank = mob.mobPowers.get(powerToken); - - PowersBase mobPower = PowersManager.getPowerByToken(powerToken); - - //check for hit-roll - - if (mobPower.requiresHitRoll) - if (CombatUtilities.triggerDefense(mob, mob.getCombatTarget())) - return false; - - // Cast the spell - - if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mobPower.getRange())) { - - PerformActionMsg msg; - - if (!mobPower.isHarmful() || mobPower.targetSelf) { - PowersManager.useMobPower(mob, mob, mobPower, powerRank); - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob); - } else { - PowersManager.useMobPower(mob, target, mobPower, powerRank); - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); - } - - msg.setUnknown04(2); - - PowersManager.finishUseMobPower(msg, mob, 0, 0); - long randomCooldown = (long)((ThreadLocalRandom.current().nextInt(10,15) * 1000) * MobAIThread.AI_CAST_FREQUENCY); - - mob.nextCastTime = System.currentTimeMillis() + randomCooldown; - return true; - } - } catch (Exception e) { - Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCast" + " " + e.getMessage()); - } - return false; - } - - public static boolean GuardCast(Mob mob) { - - try { - // Method picks a random spell from a mobile's list of powers - // and casts it on the current target (or itself). Validation - // (including empty lists) is done previously within canCast(); - - ArrayList powerTokens; - ArrayList purgeTokens; - AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); - - if (mob.behaviourType.callsForHelp) - MobCallForHelp(mob); - - // Generate a list of tokens from the mob powers for this mobile. - - powerTokens = new ArrayList<>(mob.mobPowers.keySet()); - purgeTokens = new ArrayList<>(); - - // If player has this effect on them currently then remove - // this token from our list. - - for (int powerToken : powerTokens) { - - PowersBase powerBase = PowersManager.getPowerByToken(powerToken); - - for (ActionsBase actionBase : powerBase.getActions()) { - - String stackType = actionBase.stackType; - - if (target.getEffects() != null && target.getEffects().containsKey(stackType)) - purgeTokens.add(powerToken); - } - } - - powerTokens.removeAll(purgeTokens); - - // Sanity check - - if (powerTokens.isEmpty()) - return false; - - int powerToken = 0; - int nukeRoll = ThreadLocalRandom.current().nextInt(1,100); - - if (nukeRoll < 55) { - - //use direct damage spell - powerToken = powerTokens.get(powerTokens.size() - 1); - - } else { - //use random spell - powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); - } - - int powerRank = 1; - - switch(mob.getRank()){ - case 1: - powerRank = 10; - break; - case 2: - powerRank = 15; - break; - case 3: - powerRank = 20; - break; - case 4: - powerRank = 25; - break; - case 5: - powerRank = 30; - break; - case 6: - powerRank = 35; - break; - case 7: - powerRank = 40; - break; - } - - PowersBase mobPower = PowersManager.getPowerByToken(powerToken); - - //check for hit-roll - - if (mobPower.requiresHitRoll) - if (CombatUtilities.triggerDefense(mob, mob.getCombatTarget())) - return false; - - // Cast the spell - - if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mobPower.getRange())) { - - PerformActionMsg msg; - - if (!mobPower.isHarmful() || mobPower.targetSelf) { - - if (mobPower.category.equals("DISPEL")) { - PowersManager.useMobPower(mob, target, mobPower, powerRank); - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); - } else { - PowersManager.useMobPower(mob, mob, mobPower, powerRank); - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob); - } - } else { - PowersManager.useMobPower(mob, target, mobPower, powerRank); - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); - } - - msg.setUnknown04(2); - - PowersManager.finishUseMobPower(msg, mob, 0, 0); - - long randomCooldown = (long)((ThreadLocalRandom.current().nextInt(10,15) * 1000) * MobAIThread.AI_CAST_FREQUENCY); - mob.nextCastTime = System.currentTimeMillis() + randomCooldown; - return true; - } - } catch (Exception e) { - Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCast" + " " + e.getMessage()); - } - return false; - } - public static void MobCallForHelp(Mob mob) { try { @@ -606,7 +344,7 @@ public class MobAI { if (mob == null) return; - if (mob.getTimestamps().containsKey("lastExecution") == false) + if (!mob.getTimestamps().containsKey("lastExecution")) mob.getTimestamps().put("lastExecution", System.currentTimeMillis()); if (System.currentTimeMillis() < mob.getTimeStamp("lastExecution")) @@ -626,11 +364,11 @@ public class MobAI { if (mob.despawned && mob.isPlayerGuard) { if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion)) { - if (mob.guardCaptain.isAlive() == false || ((Mob) mob.guardCaptain).despawned == true) { + if (!mob.guardCaptain.isAlive() || ((Mob) mob.guardCaptain).despawned) { //minions don't respawn while guard captain is dead - if (mob.isAlive() == false) { + if (!mob.isAlive()) { mob.deathTime = System.currentTimeMillis(); return; } @@ -642,7 +380,7 @@ public class MobAI { //check to send mob home for player guards to prevent exploit of dragging guards away and then teleporting - if (mob.behaviourType.equals(Enum.MobBehaviourType.Pet1) == false) + if (!mob.behaviourType.equals(Enum.MobBehaviourType.Pet1)) CheckToSendMobHome(mob); return; @@ -662,7 +400,7 @@ public class MobAI { HashSet players = WorldGrid.getObjectsInRangePartial(mob.loc, mob.getAggroRange(), MBServerStatics.MASK_PLAYER); if(players.size() > 0){ for(AbstractWorldObject player : players){ - if(mob.playerAgroMap.containsKey(player.getObjectUUID()) == false) { + if(!mob.playerAgroMap.containsKey(player.getObjectUUID())) { PlayerCharacter pc = (PlayerCharacter) player; mob.playerAgroMap.put(pc.getObjectUUID(), 0.0f); } @@ -674,12 +412,12 @@ public class MobAI { return; } - if (mob.behaviourType.equals(Enum.MobBehaviourType.Pet1) == false) + if (!mob.behaviourType.equals(Enum.MobBehaviourType.Pet1)) CheckToSendMobHome(mob); if (mob.getCombatTarget() != null) { - if (mob.getCombatTarget().isAlive() == false) { + if (!mob.getCombatTarget().isAlive()) { mob.setCombatTarget(null); return; } @@ -688,18 +426,35 @@ public class MobAI { PlayerCharacter target = (PlayerCharacter) mob.getCombatTarget(); - if (mob.playerAgroMap.containsKey(target.getObjectUUID()) == false) { + if (!mob.playerAgroMap.containsKey(target.getObjectUUID())) { mob.setCombatTarget(null); return; } - if (mob.canSee((PlayerCharacter) mob.getCombatTarget()) == false) { + if (!mob.canSee((PlayerCharacter) mob.getCombatTarget())) { mob.setCombatTarget(null); return; } } } + if (mob.isMoving()) { + mob.updateLocation(); + } + boolean combatState = mob.isCombat(); + mob.setCombat(mob.combatTarget != null); + if(combatState != mob.isCombat()){ + //send message to update combat state + UpdateStateMsg rwss = new UpdateStateMsg(); + rwss.setPlayer(mob); + DispatchMessage.sendToAllInRange(mob, rwss); + } + boolean walking = mob.isWalk(); + mob.setWalkMode(mob.combatTarget == null); + if(walking != mob.isWalk()){ + //send message to update run/walk state + MovementManager.sendRWSSMsg(mob); + } switch (mob.behaviourType) { case GuardCaptain: @@ -738,22 +493,21 @@ public class MobAI { if(!pets) { ConcurrentHashMap loadedPlayers = aiAgent.playerAgroMap; - for (Entry playerEntry : loadedPlayers.entrySet()) { + for (Integer playerEntry : loadedPlayers.keySet()) { - int playerID = (int) playerEntry.getKey(); - PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerID); + PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerEntry); //Player is null, let's remove them from the list. if (loadedPlayer == null) { - loadedPlayers.remove(playerID); + loadedPlayers.remove(playerEntry); continue; } //Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map. if (!loadedPlayer.isAlive() || loadedPlayer.getHidden() > 0) { - loadedPlayers.remove(playerID); + loadedPlayers.remove(playerEntry); continue; } @@ -764,12 +518,12 @@ public class MobAI { // No aggro for this race type - if (aiAgent.notEnemy.size() > 0 && aiAgent.notEnemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType()) == true) + if (aiAgent.notEnemy.size() > 0 && aiAgent.notEnemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType())) continue; //mob has enemies and this player race is not it - if (aiAgent.enemy.size() > 0 && aiAgent.enemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType()) == false) + if (aiAgent.enemy.size() > 0 && !aiAgent.enemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType())) continue; if (MovementUtilities.inRangeToAggro(aiAgent, loadedPlayer)) { @@ -806,27 +560,27 @@ public class MobAI { return; try { + if(mob == null) + return; if (!MovementUtilities.canMove(mob)) return; - mob.updateLocation(); - switch (mob.behaviourType) { case Pet1: - if ((PlayerCharacter) mob.guardCaptain == null) + if (mob.guardCaptain == null) return; - if (!mob.playerAgroMap.containsKey(((PlayerCharacter) mob.guardCaptain).getObjectUUID())) { + if (!mob.playerAgroMap.containsKey(mob.guardCaptain.getObjectUUID())) { //mob no longer has its owner loaded, translocate pet to owner - MovementManager.translocate(mob, ((PlayerCharacter) mob.guardCaptain).getLoc(), null); + MovementManager.translocate(mob, mob.guardCaptain.getLoc(), null); return; } if (mob.getCombatTarget() == null) { @@ -834,11 +588,11 @@ public class MobAI { //move back to owner - if (CombatUtilities.inRange2D(mob, (PlayerCharacter) mob.guardCaptain, 6)) + if (CombatUtilities.inRange2D(mob, mob.guardCaptain, 6)) return; - mob.destination = ((PlayerCharacter) mob.guardCaptain).getLoc(); + mob.destination = mob.guardCaptain.getLoc(); MovementUtilities.moveToLocation(mob, mob.destination, 5); } else chaseTarget(mob); @@ -886,7 +640,6 @@ public class MobAI { if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_WITH_LOOT) { aiAgent.despawn(); aiAgent.deathTime = System.currentTimeMillis(); - return; } //No items in inventory. } else { @@ -895,14 +648,12 @@ public class MobAI { if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) { aiAgent.despawn(); aiAgent.deathTime = System.currentTimeMillis(); - return; } //Mob never had Loot. } else { if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER) { aiAgent.despawn(); aiAgent.deathTime = System.currentTimeMillis(); - return; } } } @@ -922,14 +673,14 @@ public class MobAI { //checks if mob can attack based on attack timer and range - if (mob.isAlive() == false) + if (!mob.isAlive()) return; if (mob.getCombatTarget() == null) return; - if (mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter) && MovementUtilities.inRangeDropAggro(mob, (PlayerCharacter) mob.getCombatTarget()) == false && - mob.behaviourType.equals(Enum.MobBehaviourType.Pet1) == false) { + if (mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter) && !MovementUtilities.inRangeDropAggro(mob, (PlayerCharacter) mob.getCombatTarget()) && + !mob.behaviourType.equals(Enum.MobBehaviourType.Pet1)) { mob.setCombatTarget(null); return; @@ -955,14 +706,11 @@ public class MobAI { } } - //if (mob.getCombatTarget() != null && CombatUtilities.inRange2D(mob, mob.getCombatTarget(), MobAIThread.AI_BASE_AGGRO_RANGE * 0.5f)) - //return; - if (mob.isPlayerGuard() && !mob.despawned) { City current = ZoneManager.getCityAtLocation(mob.getLoc()); - if (current == null || current.equals(mob.getGuild().getOwnedCity()) == false) { + if (current == null || !current.equals(mob.getGuild().getOwnedCity())) { PowersBase recall = PowersManager.getPowerByToken(-1994153779); PowersManager.useMobPower(mob, mob, recall, 40); @@ -978,14 +726,13 @@ public class MobAI { } } } - } else if (MovementUtilities.inRangeOfBindLocation(mob) == false) { + } else if (!MovementUtilities.inRangeOfBindLocation(mob)) { PowersBase recall = PowersManager.getPowerByToken(-1994153779); PowersManager.useMobPower(mob, mob, recall, 40); mob.setCombatTarget(null); - for (Integer playerEntry : mob.playerAgroMap.keySet()) - mob.playerAgroMap.put(playerEntry,0f); + mob.playerAgroMap.replaceAll((e, v) -> 0f); } } catch (Exception e) { Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckToSendMobHome" + " " + e.getMessage()); @@ -1004,10 +751,10 @@ public class MobAI { float rangeSquared = mob.getRange() * mob.getRange(); float distanceSquared = mob.getLoc().distanceSquared2D(mob.getCombatTarget().getLoc()); - if(mob.isMoving() == true && distanceSquared < rangeSquared - 50) { + if(mob.isMoving() && distanceSquared < rangeSquared - 50) { mob.destination = mob.getLoc(); MovementUtilities.moveToLocation(mob, mob.destination, 0); - } else if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mob.getRange()) == false) { + } else if (!CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mob.getRange())) { if (mob.getRange() > 15) { mob.destination = mob.getCombatTarget().getLoc(); MovementUtilities.moveToLocation(mob, mob.destination, 0); @@ -1029,7 +776,6 @@ public class MobAI { } } mob.updateMovementState(); - mob.updateLocation(); } catch (Exception e) { Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: chaseTarget" + " " + e.getMessage()); } @@ -1044,7 +790,7 @@ public class MobAI { //dont scan self. - if (mob.equals(awoMob) || (mob.agentType.equals(Enum.AIAgentType.GUARD)) == true || awoMob.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) + if (mob.equals(awoMob) || (mob.agentType.equals(Enum.AIAgentType.GUARD)) || awoMob.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) continue; Mob aggroMob = (Mob) awoMob; @@ -1073,18 +819,6 @@ public class MobAI { if (mob.getCombatTarget() == null) CheckForPlayerGuardAggro(mob); - AbstractWorldObject newTarget = ChangeTargetFromHateValue(mob); - - if (newTarget != null) { - - if (newTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) { - if (GuardCanAggro(mob, (PlayerCharacter) newTarget)) - mob.setCombatTarget(newTarget); - } else - mob.setCombatTarget(newTarget); - - } - CheckMobMovement(mob); CheckForAttack(mob); } catch (Exception e) { @@ -1099,19 +833,6 @@ public class MobAI { if (mob.getCombatTarget() == null) { CheckForPlayerGuardAggro(mob); - } else { - - AbstractWorldObject newTarget = ChangeTargetFromHateValue(mob); - - if (newTarget != null) { - - if (newTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) { - if (GuardCanAggro(mob, (PlayerCharacter) newTarget)) - mob.setCombatTarget(newTarget); - } else - mob.setCombatTarget(newTarget); - - } } }else { if (mob.guardCaptain.getCombatTarget() != null) @@ -1143,7 +864,7 @@ public class MobAI { try { - if (mob.guardCaptain == null && mob.isNecroPet() == false && mob.isSiege() == false) + if (mob.guardCaptain == null && !mob.isNecroPet() && !mob.isSiege()) if (ZoneManager.getSeaFloor().zoneMobSet.contains(mob)) mob.killCharacter("no owner"); @@ -1154,7 +875,7 @@ public class MobAI { //recover health - if (mob.getTimestamps().containsKey("HEALTHRECOVERED") == false) + if (!mob.getTimestamps().containsKey("HEALTHRECOVERED")) mob.getTimestamps().put("HEALTHRECOVERED", System.currentTimeMillis()); if (mob.isSit() && mob.getTimeStamp("HEALTHRECOVERED") < System.currentTimeMillis() + 3000) @@ -1179,7 +900,7 @@ public class MobAI { if (mob.getCombatTarget() == null) SafeGuardAggro(mob); - else if (mob.getCombatTarget().isAlive() == false) + else if (!mob.getCombatTarget().isAlive()) SafeGuardAggro(mob); CheckForAttack(mob); @@ -1194,7 +915,7 @@ public class MobAI { if(mob.combatTarget != null && mob.combatTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)){ PlayerCharacter tar = (PlayerCharacter)mob.combatTarget; - if (mob.canSee(tar) == false) { + if (!mob.canSee(tar)) { mob.setCombatTarget(null); } } @@ -1245,22 +966,21 @@ public class MobAI { ConcurrentHashMap loadedPlayers = mob.playerAgroMap; - for (Entry playerEntry : loadedPlayers.entrySet()) { + for (Integer playerEntry : loadedPlayers.keySet()) { - int playerID = (int) playerEntry.getKey(); - PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerID); + PlayerCharacter loadedPlayer = PlayerCharacter.getFromCache(playerEntry); //Player is null, let's remove them from the list. if (loadedPlayer == null) { - loadedPlayers.remove(playerID); + loadedPlayers.remove(playerEntry); continue; } //Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map. if (!loadedPlayer.isAlive()) { - loadedPlayers.remove(playerID); + loadedPlayers.remove(playerEntry); continue; } @@ -1271,7 +991,7 @@ public class MobAI { // No aggro for this player - if (GuardCanAggro(mob, loadedPlayer) == false) + if (!GuardCanAggro(mob, loadedPlayer)) continue; if (MovementUtilities.inRangeToAggro(mob, loadedPlayer) && mob.getCombatTarget() == null) { @@ -1292,17 +1012,17 @@ public class MobAI { return false; if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion)) { - if (((Mob) mob.guardCaptain).building.getCity().cityOutlaws.contains(target.getObjectUUID()) == true) { + if (Objects.requireNonNull(mob.guardCaptain.building.getCity()).cityOutlaws.contains(target.getObjectUUID())) { return true; } - } else if (mob.building.getCity().cityOutlaws.contains(target.getObjectUUID()) == true) { + } else if (Objects.requireNonNull(mob.building.getCity()).cityOutlaws.contains(target.getObjectUUID())) { return true; } //first check condemn list for aggro allowed (allies button is checked) - if (ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().reverseKOS) { - for (Entry entry : ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().getCondemned().entrySet()) { + if (Objects.requireNonNull(ZoneManager.getCityAtLocation(mob.getLoc())).getTOL().reverseKOS) { + for (Entry entry : Objects.requireNonNull(ZoneManager.getCityAtLocation(mob.getLoc())).getTOL().getCondemned().entrySet()) { //target is listed individually @@ -1324,7 +1044,7 @@ public class MobAI { //allies button is not checked - for (Entry entry : ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().getCondemned().entrySet()) { + for (Entry entry : Objects.requireNonNull(ZoneManager.getCityAtLocation(mob.getLoc())).getTOL().getCondemned().entrySet()) { //target is listed individually @@ -1355,7 +1075,7 @@ public class MobAI { //early exit for a mob who is already moving to a patrol point //while mob moving, update lastPatrolTime so that when they stop moving the 10 second timer can begin - if (mob.isMoving() == true) { + if (mob.isMoving()) { mob.stopPatrolTime = System.currentTimeMillis(); return; } @@ -1381,7 +1101,7 @@ public class MobAI { //make sure mob is out of combat stance - if (minion.getKey().despawned == false) { + if (!minion.getKey().despawned) { if (MovementUtilities.canMove(minion.getKey())) { Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3); minion.getKey().updateLocation(); @@ -1395,40 +1115,4 @@ public class MobAI { Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: randomGuardPatrolPoints" + " " + e.getMessage()); } } - - public static AbstractWorldObject ChangeTargetFromHateValue(Mob mob) { - - if(mob.combatTarget != null) - return mob.combatTarget; - //try { - - // float CurrentHateValue = 0; - // if (mob.getCombatTarget() != null && mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.Mob)){ - // return mob.getCombatTarget(); - // } - - // if (mob.getCombatTarget() != null && mob.getCombatTarget().getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) - // CurrentHateValue = mob.playerAgroMap.get(mob.combatTarget.getObjectUUID()).floatValue(); - - // AbstractWorldObject mostHatedTarget = null; - - // for (Entry playerEntry : mob.playerAgroMap.entrySet()) { - - // PlayerCharacter potentialTarget = PlayerCharacter.getFromCache((int) playerEntry.getKey()); - - // if (potentialTarget.equals(mob.getCombatTarget())) - // continue; - - // if (potentialTarget != null && mob.playerAgroMap.get(potentialTarget.getObjectUUID()).floatValue() > CurrentHateValue && MovementUtilities.inRangeToAggro(mob, potentialTarget)) { - // CurrentHateValue = mob.playerAgroMap.get(potentialTarget.getObjectUUID()).floatValue(); - // mostHatedTarget = potentialTarget; - // } - - // } - // return mostHatedTarget; - //} catch (Exception e) { - // Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: ChangeTargetFromMostHated" + " " + e.getMessage()); - //} - return null; - } } \ No newline at end of file diff --git a/src/engine/mobileAI/utilities/CombatUtilities.java b/src/engine/mobileAI/utilities/CombatUtilities.java index 021082cd..29021e50 100644 --- a/src/engine/mobileAI/utilities/CombatUtilities.java +++ b/src/engine/mobileAI/utilities/CombatUtilities.java @@ -12,13 +12,20 @@ package engine.mobileAI.utilities; import engine.Enum.*; import engine.gameManager.ChatManager; import engine.gameManager.CombatManager; +import engine.gameManager.PowersManager; import engine.math.Vector3fImmutable; +import engine.mobileAI.MobAI; +import engine.mobileAI.Threads.MobAIThread; import engine.net.DispatchMessage; +import engine.net.client.msg.PerformActionMsg; import engine.net.client.msg.TargetedActionMsg; 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.concurrent.ThreadLocalRandom; import static engine.math.FastMath.sqr; @@ -513,4 +520,209 @@ public class CombatUtilities { return agent.getMaxDamageHandOne(); } + public static boolean MobCast(Mob mob) { + + try { + // Method picks a random spell from a mobile's list of powers + // and casts it on the current target (or itself). Validation + // (including empty lists) is done previously within canCast(); + + ArrayList powerTokens; + ArrayList purgeTokens; + AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); + + if (mob.behaviourType.callsForHelp) + MobAI.MobCallForHelp(mob); + + // Generate a list of tokens from the mob powers for this mobile. + + powerTokens = new ArrayList<>(mob.mobPowers.keySet()); + purgeTokens = new ArrayList<>(); + + // If player has this effect on them currently then remove + // this token from our list. + + for (int powerToken : powerTokens) { + + PowersBase powerBase = PowersManager.getPowerByToken(powerToken); + + for (ActionsBase actionBase : powerBase.getActions()) { + + String stackType = actionBase.stackType; + + if (target.getEffects() != null && target.getEffects().containsKey(stackType)) + purgeTokens.add(powerToken); + } + } + + powerTokens.removeAll(purgeTokens); + + // Sanity check + + if (powerTokens.isEmpty()) + return false; + + // Pick random spell from our list of powers + + int powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); + int powerRank = mob.mobPowers.get(powerToken); + + PowersBase mobPower = PowersManager.getPowerByToken(powerToken); + + //check for hit-roll + + if (mobPower.requiresHitRoll) + if (triggerDefense(mob, mob.getCombatTarget())) + return false; + + // Cast the spell + + if (inRange2D(mob, mob.getCombatTarget(), mobPower.getRange())) { + + PerformActionMsg msg; + + if (!mobPower.isHarmful() || mobPower.targetSelf) { + PowersManager.useMobPower(mob, mob, mobPower, powerRank); + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob); + } else { + PowersManager.useMobPower(mob, target, mobPower, powerRank); + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); + } + + msg.setUnknown04(2); + + PowersManager.finishUseMobPower(msg, mob, 0, 0); + long randomCooldown = (long)((ThreadLocalRandom.current().nextInt(10,15) * 1000L) * MobAIThread.AI_CAST_FREQUENCY); + + mob.nextCastTime = System.currentTimeMillis() + randomCooldown; + return true; + } + } catch (Exception e) { + Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCast" + " " + e.getMessage()); + } + return false; + } + + public static boolean GuardCast(Mob mob) { + + try { + // Method picks a random spell from a mobile's list of powers + // and casts it on the current target (or itself). Validation + // (including empty lists) is done previously within canCast(); + + ArrayList powerTokens; + ArrayList purgeTokens; + AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); + + if (mob.behaviourType.callsForHelp) + MobAI.MobCallForHelp(mob); + + // Generate a list of tokens from the mob powers for this mobile. + + powerTokens = new ArrayList<>(mob.mobPowers.keySet()); + purgeTokens = new ArrayList<>(); + + // If player has this effect on them currently then remove + // this token from our list. + + for (int powerToken : powerTokens) { + + PowersBase powerBase = PowersManager.getPowerByToken(powerToken); + + for (ActionsBase actionBase : powerBase.getActions()) { + + String stackType = actionBase.stackType; + + if (target.getEffects() != null && target.getEffects().containsKey(stackType)) + purgeTokens.add(powerToken); + } + } + + powerTokens.removeAll(purgeTokens); + + // Sanity check + + if (powerTokens.isEmpty()) + return false; + + int powerToken; + int nukeRoll = ThreadLocalRandom.current().nextInt(1,100); + + if (nukeRoll < 55) { + + //use direct damage spell + powerToken = powerTokens.get(powerTokens.size() - 1); + + } else { + //use random spell + powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); + } + + int powerRank = 1; + + switch(mob.getRank()){ + case 1: + powerRank = 10; + break; + case 2: + powerRank = 15; + break; + case 3: + powerRank = 20; + break; + case 4: + powerRank = 25; + break; + case 5: + powerRank = 30; + break; + case 6: + powerRank = 35; + break; + case 7: + powerRank = 40; + break; + } + + PowersBase mobPower = PowersManager.getPowerByToken(powerToken); + + //check for hit-roll + + if (mobPower.requiresHitRoll) + if (triggerDefense(mob, mob.getCombatTarget())) + return false; + + // Cast the spell + + if (inRange2D(mob, mob.getCombatTarget(), mobPower.getRange())) { + + PerformActionMsg msg; + + if (!mobPower.isHarmful() || mobPower.targetSelf) { + + if (mobPower.category.equals("DISPEL")) { + PowersManager.useMobPower(mob, target, mobPower, powerRank); + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); + } else { + PowersManager.useMobPower(mob, mob, mobPower, powerRank); + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob); + } + } else { + PowersManager.useMobPower(mob, target, mobPower, powerRank); + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); + } + + msg.setUnknown04(2); + + PowersManager.finishUseMobPower(msg, mob, 0, 0); + + long randomCooldown = (long)((ThreadLocalRandom.current().nextInt(10,15) * 1000L) * MobAIThread.AI_CAST_FREQUENCY); + mob.nextCastTime = System.currentTimeMillis() + randomCooldown; + return true; + } + } catch (Exception e) { + Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCast" + " " + e.getMessage()); + } + return false; + } } diff --git a/src/engine/mobileAI/utilities/MovementUtilities.java b/src/engine/mobileAI/utilities/MovementUtilities.java index 8d78b817..088c2a2e 100644 --- a/src/engine/mobileAI/utilities/MovementUtilities.java +++ b/src/engine/mobileAI/utilities/MovementUtilities.java @@ -143,15 +143,6 @@ public class MovementUtilities { public static void aiMove(Mob agent, Vector3fImmutable vect, boolean isWalking) { - //update our walk/run state. - if (isWalking && !agent.isWalk()) { - agent.setWalkMode(true); - MovementManager.sendRWSSMsg(agent); - } else if (!isWalking && agent.isWalk()) { - agent.setWalkMode(false); - MovementManager.sendRWSSMsg(agent); - } - MoveToPointMsg msg = new MoveToPointMsg(); diff --git a/src/engine/objects/AbstractCharacter.java b/src/engine/objects/AbstractCharacter.java index b65e07a5..be10959a 100644 --- a/src/engine/objects/AbstractCharacter.java +++ b/src/engine/objects/AbstractCharacter.java @@ -1113,23 +1113,6 @@ public abstract class AbstractCharacter extends AbstractWorldObject { } public final void setCombatTarget(final AbstractWorldObject value) { - if(this.getObjectTypeMask() == 2050) {//MOB? - if (value == null) { - if (this.isCombat()) { - this.setCombat(false); - UpdateStateMsg rwss = new UpdateStateMsg(); - rwss.setPlayer(this); - DispatchMessage.sendToAllInRange(this, rwss); - } - }else { - if (!this.isCombat()) { - this.setCombat(true); - UpdateStateMsg rwss = new UpdateStateMsg(); - rwss.setPlayer(this); - DispatchMessage.sendToAllInRange(this, rwss); - } - } - } this.combatTarget = value; }