Merge branch 'new-mob-ai' of http://repo.magicbane.com/MagicBane/Server into new-mob-ai
Conflicts: src/engine/ai/MobileFSM.java
This commit is contained in:
@@ -17,7 +17,6 @@ import engine.InterestManagement.WorldGrid;
|
|||||||
import engine.ai.utilities.CombatUtilities;
|
import engine.ai.utilities.CombatUtilities;
|
||||||
import engine.ai.utilities.MovementUtilities;
|
import engine.ai.utilities.MovementUtilities;
|
||||||
import engine.gameManager.*;
|
import engine.gameManager.*;
|
||||||
import engine.math.Vector3f;
|
|
||||||
import engine.math.Vector3fImmutable;
|
import engine.math.Vector3fImmutable;
|
||||||
import engine.net.DispatchMessage;
|
import engine.net.DispatchMessage;
|
||||||
import engine.net.client.msg.PerformActionMsg;
|
import engine.net.client.msg.PerformActionMsg;
|
||||||
@@ -25,8 +24,6 @@ import engine.net.client.msg.PowerProjectileMsg;
|
|||||||
import engine.net.client.msg.UpdateStateMsg;
|
import engine.net.client.msg.UpdateStateMsg;
|
||||||
import engine.objects.*;
|
import engine.objects.*;
|
||||||
import engine.powers.ActionsBase;
|
import engine.powers.ActionsBase;
|
||||||
import engine.powers.EffectsBase;
|
|
||||||
import engine.powers.PowerPrereq;
|
|
||||||
import engine.powers.PowersBase;
|
import engine.powers.PowersBase;
|
||||||
import engine.server.MBServerStatics;
|
import engine.server.MBServerStatics;
|
||||||
import org.pmw.tinylog.Logger;
|
import org.pmw.tinylog.Logger;
|
||||||
@@ -53,7 +50,8 @@ public class MobileFSM {
|
|||||||
Home,
|
Home,
|
||||||
Dead,
|
Dead,
|
||||||
Recalling,
|
Recalling,
|
||||||
Retaliate
|
Retaliate,
|
||||||
|
Chase
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void run(Mob mob) {
|
public static void run(Mob mob) {
|
||||||
@@ -116,7 +114,6 @@ public class MobileFSM {
|
|||||||
rwss.setPlayer(mob);
|
rwss.setPlayer(mob);
|
||||||
DispatchMessage.sendToAllInRange(mob, rwss);
|
DispatchMessage.sendToAllInRange(mob, rwss);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mob.isPlayerGuard())
|
if (mob.isPlayerGuard())
|
||||||
guardAttack(mob);
|
guardAttack(mob);
|
||||||
else if (mob.isPet() || mob.isSiege())
|
else if (mob.isPet() || mob.isSiege())
|
||||||
@@ -144,6 +141,9 @@ public class MobileFSM {
|
|||||||
case Retaliate:
|
case Retaliate:
|
||||||
retaliate(mob);
|
retaliate(mob);
|
||||||
break;
|
break;
|
||||||
|
case Chase:
|
||||||
|
handleMobChase(mob);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,8 +339,8 @@ public class MobileFSM {
|
|||||||
if (!MovementUtilities.canMove(aiAgent))
|
if (!MovementUtilities.canMove(aiAgent))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
double WeaponRange = aiAgent.getEquip().get(0).getItemBase().getRange();
|
||||||
if (CombatUtilities.inRangeToAttack2D(aiAgent, mob))
|
if (CombatUtilities.inRange2D(aiAgent, mob, WeaponRange))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
@@ -465,11 +465,12 @@ public class MobileFSM {
|
|||||||
aiAgent.setState(STATE.Patrol);
|
aiAgent.setState(STATE.Patrol);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
aiAgent.setCombatTarget(aggroTarget);
|
||||||
if (canCast(aiAgent) == true) {
|
if (canCast(aiAgent) == true) {
|
||||||
if (MobCast(aiAgent) == false) {
|
if (MobCast(aiAgent) == false) {
|
||||||
attack(aiAgent, targetID);
|
attack(aiAgent, targetID);
|
||||||
}
|
}
|
||||||
} else if (CombatUtilities.inRangeToAttack(aiAgent, aggroTarget)) {
|
} else if (CombatUtilities.inRange2D(aiAgent, aggroTarget, aiAgent.getRange())) {
|
||||||
aiAgent.setState(STATE.Attack);
|
aiAgent.setState(STATE.Attack);
|
||||||
attack(aiAgent, targetID);
|
attack(aiAgent, targetID);
|
||||||
return;
|
return;
|
||||||
@@ -824,18 +825,19 @@ public class MobileFSM {
|
|||||||
aiAgent.setState(STATE.Awake);
|
aiAgent.setState(STATE.Awake);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (CombatUtilities.inRangeToAttack(aiAgent, player)) {
|
if (CombatUtilities.inRange2D(aiAgent, player, aiAgent.getRange())) {
|
||||||
|
|
||||||
//no weapons, defualt mob attack speed 3 seconds.
|
//no weapons, defualt mob attack speed 3 seconds.
|
||||||
|
|
||||||
if (System.currentTimeMillis() < aiAgent.getLastAttackTime())
|
if (System.currentTimeMillis() < aiAgent.getLastAttackTime())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!CombatUtilities.RunAIRandom())
|
//if (!CombatUtilities.RunAIRandom())
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
// ranged mobs cant attack while running. skip until they finally stop.
|
// 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;
|
return;
|
||||||
|
|
||||||
// add timer for last attack.
|
// 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.
|
//this stops mobs from attempting to move while they are underneath a player.
|
||||||
if (CombatUtilities.inRangeToAttack2D(aiAgent, player))
|
if (CombatUtilities.inRangeToAttack2D(aiAgent, player))
|
||||||
return;
|
return;
|
||||||
|
//set mob to pursue target
|
||||||
aiAgent.destination = MovementUtilities.GetDestinationToCharacter(aiAgent, player);
|
aiAgent.setState(MobileFSM.STATE.Chase);
|
||||||
MovementUtilities.moveToLocation(aiAgent, aiAgent.destination, aiAgent.getRange());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
private static void handleMobAttackForPet(Mob aiAgent, Mob mob) {
|
private static void handleMobAttackForPet(Mob aiAgent, Mob mob) {
|
||||||
|
|
||||||
@@ -1146,12 +1146,6 @@ public class MobileFSM {
|
|||||||
aiAgent.setCombatTarget(null);
|
aiAgent.setCombatTarget(null);
|
||||||
aiAgent.setState(STATE.Awake);
|
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) {
|
private static void recalling(Mob aiAgent) {
|
||||||
//recall home.
|
//recall home.
|
||||||
if (aiAgent.getLoc() == aiAgent.getBindLoc())
|
if (aiAgent.getLoc() == aiAgent.getBindLoc())
|
||||||
@@ -1648,72 +1642,59 @@ public class MobileFSM {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public static boolean MobCast(Mob mob) {
|
public static boolean MobCast(Mob mob) {
|
||||||
|
if (mob.getMobBase().getFlags().contains(Enum.MobFlagType.CALLSFORHELP)) {
|
||||||
// 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<Integer> powerTokens;
|
|
||||||
PlayerCharacter target = (PlayerCharacter) mob.getCombatTarget();
|
|
||||||
|
|
||||||
if (mob.getMobBase().getFlags().contains(Enum.MobFlagType.CALLSFORHELP))
|
|
||||||
MobCallForHelp(mob);
|
MobCallForHelp(mob);
|
||||||
|
}
|
||||||
// Generate a list of tokens from the mob powers for this mobile.
|
PlayerCharacter target = (PlayerCharacter) mob.getCombatTarget();
|
||||||
|
HashMap<Integer,Integer> eligiblePowers = mob.mobPowers;
|
||||||
powerTokens = new ArrayList<>(mob.mobPowers.keySet());
|
for(Map.Entry<Integer,Integer> power : mob.mobPowers.entrySet()) {
|
||||||
|
PowersBase pwr= PowersManager.getPowerByToken(power.getKey());
|
||||||
// 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);
|
|
||||||
|
|
||||||
for(ActionsBase act : pwr.getActions()){
|
for(ActionsBase act : pwr.getActions()){
|
||||||
|
|
||||||
String des = act.stackType;
|
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);
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
int random = ThreadLocalRandom.current().nextInt(eligiblePowers.size());
|
||||||
|
int powerToken = 0;
|
||||||
|
int powerRank = 0;
|
||||||
|
Map<Integer, Integer> entries = eligiblePowers;
|
||||||
|
int count = -1;
|
||||||
|
for (Map.Entry<Integer, Integer> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void MobCallForHelp(Mob mob) {
|
public static void MobCallForHelp(Mob mob) {
|
||||||
if(mob.nextCallForHelp == 0){
|
if(mob.nextCallForHelp == 0){
|
||||||
mob.nextCallForHelp = System.currentTimeMillis();
|
mob.nextCallForHelp = System.currentTimeMillis();
|
||||||
@@ -1734,4 +1715,29 @@ public class MobileFSM {
|
|||||||
//wait 60 seconds to call for help again
|
//wait 60 seconds to call for help again
|
||||||
mob.nextCallForHelp = System.currentTimeMillis() + 60000;
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import engine.ai.MobileFSM.STATE;
|
|||||||
import engine.gameManager.ChatManager;
|
import engine.gameManager.ChatManager;
|
||||||
import engine.gameManager.CombatManager;
|
import engine.gameManager.CombatManager;
|
||||||
import engine.gameManager.PowersManager;
|
import engine.gameManager.PowersManager;
|
||||||
|
import engine.math.Vector3f;
|
||||||
import engine.math.Vector3fImmutable;
|
import engine.math.Vector3fImmutable;
|
||||||
import engine.net.DispatchMessage;
|
import engine.net.DispatchMessage;
|
||||||
import engine.net.client.msg.PerformActionMsg;
|
import engine.net.client.msg.PerformActionMsg;
|
||||||
@@ -84,18 +85,7 @@ public class CombatUtilities {
|
|||||||
|
|
||||||
}
|
}
|
||||||
public static boolean inRange2D(AbstractWorldObject entity1, AbstractWorldObject entity2, double range){
|
public static boolean inRange2D(AbstractWorldObject entity1, AbstractWorldObject entity2, double range){
|
||||||
Vector3fImmutable loc1 = entity1.getLoc();
|
return entity1.getLoc().distance2D(entity2.getLoc()) < range;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public static void swingIsBlock(Mob agent,AbstractWorldObject target, int animation) {
|
public static void swingIsBlock(Mob agent,AbstractWorldObject target, int animation) {
|
||||||
|
|
||||||
|
|||||||
@@ -781,11 +781,22 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
|||||||
// Treb range does not appear to be set here
|
// Treb range does not appear to be set here
|
||||||
// what gives?
|
// what gives?
|
||||||
|
|
||||||
|
|
||||||
if (this.getObjectType() == GameObjectType.Mob) {
|
if (this.getObjectType() == GameObjectType.Mob) {
|
||||||
Mob mob = (Mob) this;
|
Mob mob = (Mob) this;
|
||||||
if (mob.isSiege()) {
|
if (mob.isSiege()) {
|
||||||
return 300;
|
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) {
|
if (this.rangeHandOne > this.rangeHandTwo) {
|
||||||
return this.rangeHandOne;
|
return this.rangeHandOne;
|
||||||
|
|||||||
Reference in New Issue
Block a user