diff --git a/src/engine/ai/MobileFSM.java b/src/engine/ai/MobileFSM.java index ab7be602..8d7bb536 100644 --- a/src/engine/ai/MobileFSM.java +++ b/src/engine/ai/MobileFSM.java @@ -17,7 +17,6 @@ import engine.InterestManagement.WorldGrid; import engine.ai.utilities.CombatUtilities; import engine.ai.utilities.MovementUtilities; import engine.gameManager.*; -import engine.math.Vector3f; import engine.math.Vector3fImmutable; import engine.net.DispatchMessage; import engine.net.client.msg.PerformActionMsg; @@ -25,8 +24,6 @@ import engine.net.client.msg.PowerProjectileMsg; import engine.net.client.msg.UpdateStateMsg; import engine.objects.*; import engine.powers.ActionsBase; -import engine.powers.EffectsBase; -import engine.powers.PowerPrereq; import engine.powers.PowersBase; import engine.server.MBServerStatics; import org.pmw.tinylog.Logger; @@ -53,7 +50,8 @@ public class MobileFSM { Home, Dead, Recalling, - Retaliate + Retaliate, + Chase } public static void run(Mob mob) { @@ -116,7 +114,6 @@ public class MobileFSM { rwss.setPlayer(mob); DispatchMessage.sendToAllInRange(mob, rwss); } - if (mob.isPlayerGuard()) guardAttack(mob); else if (mob.isPet() || mob.isSiege()) @@ -144,6 +141,9 @@ public class MobileFSM { case Retaliate: retaliate(mob); break; + case Chase: + handleMobChase(mob); + break; } } @@ -339,8 +339,8 @@ public class MobileFSM { if (!MovementUtilities.canMove(aiAgent)) return; - - if (CombatUtilities.inRangeToAttack2D(aiAgent, mob)) + double WeaponRange = aiAgent.getEquip().get(0).getItemBase().getRange(); + if (CombatUtilities.inRange2D(aiAgent, mob, WeaponRange)) return; @@ -465,11 +465,12 @@ public class MobileFSM { aiAgent.setState(STATE.Patrol); return; } + aiAgent.setCombatTarget(aggroTarget); if (canCast(aiAgent) == true) { if (MobCast(aiAgent) == false) { attack(aiAgent, targetID); } - } else if (CombatUtilities.inRangeToAttack(aiAgent, aggroTarget)) { + } else if (CombatUtilities.inRange2D(aiAgent, aggroTarget, aiAgent.getRange())) { aiAgent.setState(STATE.Attack); attack(aiAgent, targetID); return; @@ -824,18 +825,19 @@ public class MobileFSM { aiAgent.setState(STATE.Awake); return; } - if (CombatUtilities.inRangeToAttack(aiAgent, player)) { + 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; + //if (!CombatUtilities.RunAIRandom()) + // return; // ranged mobs cant attack while running. skip until they finally stop. - if (aiAgent.getRange() >= 30 && aiAgent.isMoving()) + //if (aiAgent.getRange() >= 30 && aiAgent.isMoving()) + if(aiAgent.isMoving()) return; // add timer for last attack. @@ -888,10 +890,8 @@ public class MobileFSM { //this stops mobs from attempting to move while they are underneath a player. if (CombatUtilities.inRangeToAttack2D(aiAgent, player)) return; - - aiAgent.destination = MovementUtilities.GetDestinationToCharacter(aiAgent, player); - MovementUtilities.moveToLocation(aiAgent, aiAgent.destination, aiAgent.getRange()); - + //set mob to pursue target + aiAgent.setState(MobileFSM.STATE.Chase); } private static void handleMobAttackForPet(Mob aiAgent, Mob mob) { @@ -1146,12 +1146,6 @@ public class MobileFSM { aiAgent.setCombatTarget(null); aiAgent.setState(STATE.Awake); } - private static void recall(Mob aiAgent) { - //recall home. - PowersBase recall = PowersManager.getPowerByToken(-1994153779); - PowersManager.useMobPower(aiAgent, aiAgent, recall, 40); - aiAgent.setState(MobileFSM.STATE.Recalling); - } private static void recalling(Mob aiAgent) { //recall home. if (aiAgent.getLoc() == aiAgent.getBindLoc()) @@ -1648,72 +1642,59 @@ public class MobileFSM { return true; } public static boolean MobCast(Mob mob) { - - // Method picks a random spell from a mobile's list of powers - // and casts it on the player. Validation (including empty lists) - // if done previously in canCast(); - - ArrayList powerTokens; - PlayerCharacter target = (PlayerCharacter) mob.getCombatTarget(); - - if (mob.getMobBase().getFlags().contains(Enum.MobFlagType.CALLSFORHELP)) + if (mob.getMobBase().getFlags().contains(Enum.MobFlagType.CALLSFORHELP)) { MobCallForHelp(mob); - - // Generate a list of tokens from the mob powers for this mobile. - - powerTokens = new ArrayList<>(mob.mobPowers.keySet()); - - // If player has this effect on them already then remove the token - // from the list of mob powers - - for (int powerToken : powerTokens){ - - PowersBase pwr= PowersManager.getPowerByToken(powerToken); - + } + PlayerCharacter target = (PlayerCharacter) mob.getCombatTarget(); + HashMap eligiblePowers = mob.mobPowers; + for(Map.Entry power : mob.mobPowers.entrySet()) { + PowersBase pwr= PowersManager.getPowerByToken(power.getKey()); for(ActionsBase act : pwr.getActions()){ - String des = act.stackType; + try { + if (target.getEffects() != null && target.getEffects().containsKey(des) == true) { + eligiblePowers.remove(power.getKey()); + } + }catch(Exception ex){ - if (target.getEffects() != null && target.getEffects().containsKey(des)) - powerTokens.remove(powerToken); + } } - } - - // 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); - - // Cast the spell - - if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mobPower.getRange())) { - PowersManager.useMobPower(mob,(AbstractCharacter)mob.getCombatTarget(),mobPower,powerRank); - PerformActionMsg msg; - - if(mobPower.isHarmful() == false || mobPower.targetSelf == true) - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob); - else - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); - msg.setUnknown04(2); - PowersManager.finishUseMobPower(msg, mob, 0, 0); - - //default minimum seconds between cast = 10 - - long coolDown = mobPower.getCooldown(); - - if(coolDown < 10000) - mob.nextCastTime = System.currentTimeMillis() + 10000 + coolDown; - else - mob.nextCastTime = System.currentTimeMillis() + coolDown; - - return true; + } + int random = ThreadLocalRandom.current().nextInt(eligiblePowers.size()); + int powerToken = 0; + int powerRank = 0; + Map entries = eligiblePowers; + int count = -1; + for (Map.Entry entry : entries.entrySet()) { + count += 1; + if (count == random) { + powerToken = entry.getKey(); + powerRank = entry.getValue(); + PowersBase mobPower = PowersManager.getPowerByToken(powerToken); + if (CombatUtilities.inRange2D(mob, target, mobPower.getRange())) { + PowersManager.useMobPower(mob,(AbstractCharacter)mob.getCombatTarget(),mobPower,powerRank); + PerformActionMsg msg = new PerformActionMsg(); + if(mobPower.isHarmful() == false || mobPower.targetSelf == true){ + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob); + } else { + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); + } + msg.setUnknown04(2); + PowersManager.finishUseMobPower(msg, mob, 0, 0); + //default minimum seconds between cast = 10 + long cooldown = mobPower.getCooldown(); + if(cooldown < 10000){ + mob.nextCastTime = System.currentTimeMillis() + 10000 + cooldown; + } else { + mob.nextCastTime = System.currentTimeMillis() + cooldown; + } + return true; } - + } + } return false; } - public static void MobCallForHelp(Mob mob) { if(mob.nextCallForHelp == 0){ mob.nextCallForHelp = System.currentTimeMillis(); @@ -1734,4 +1715,29 @@ public class MobileFSM { //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.setState(STATE.Home); + return; + } + mob.updateMovementState(); + mob.updateLocation(); + if(CombatUtilities.inRange2D(mob,mob.getCombatTarget(), mob.getRange()) == true) { + MovementUtilities.moveToLocation(mob, mob.getLoc(), 0); + mob.setState(STATE.Attack); + } + 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()); + } + + } + } } diff --git a/src/engine/ai/utilities/CombatUtilities.java b/src/engine/ai/utilities/CombatUtilities.java index 68a48a2f..28c8d5b9 100644 --- a/src/engine/ai/utilities/CombatUtilities.java +++ b/src/engine/ai/utilities/CombatUtilities.java @@ -16,6 +16,7 @@ import engine.ai.MobileFSM.STATE; import engine.gameManager.ChatManager; import engine.gameManager.CombatManager; import engine.gameManager.PowersManager; +import engine.math.Vector3f; import engine.math.Vector3fImmutable; import engine.net.DispatchMessage; import engine.net.client.msg.PerformActionMsg; @@ -84,18 +85,7 @@ public class CombatUtilities { } public static boolean inRange2D(AbstractWorldObject entity1, AbstractWorldObject entity2, double range){ - Vector3fImmutable loc1 = entity1.getLoc(); - Vector3fImmutable loc2 = entity2.getLoc(); - double sum = 0; - double x = loc1.x - loc2.x; - sum += x * x; - double z = loc1.z - loc2.z; - sum += z * z; - if(sqrt(sum) <= range){ - return true; - } else { - return false; - } + return entity1.getLoc().distance2D(entity2.getLoc()) < range; } public static void swingIsBlock(Mob agent,AbstractWorldObject target, int animation) { diff --git a/src/engine/objects/AbstractCharacter.java b/src/engine/objects/AbstractCharacter.java index 32e9e6e7..b2f3e5f2 100644 --- a/src/engine/objects/AbstractCharacter.java +++ b/src/engine/objects/AbstractCharacter.java @@ -781,11 +781,22 @@ public abstract class AbstractCharacter extends AbstractWorldObject { // Treb range does not appear to be set here // what gives? + if (this.getObjectType() == GameObjectType.Mob) { Mob mob = (Mob) this; if (mob.isSiege()) { return 300; } + float range = 8; + if(((Mob) this).getEquip().get(1) != null){ + range = ((Mob) this).getEquip().get(1).getItemBase().getRange(); + } else if(((Mob) this).getEquip().get(2) != null){ + range = ((Mob) this).getEquip().get(2).getItemBase().getRange(); + } + if(range > 80){ + range = 80; + } + return range; } if (this.rangeHandOne > this.rangeHandTwo) { return this.rangeHandOne;