Browse Source

new mob AI

lakebane-recovery
FatBoy-DOTC 5 days ago
parent
commit
25937cdd97
  1. 24
      src/engine/mobileAI/MobAI.java
  2. 271
      src/engine/mobileAI/MobHandlers/MobHandler.java

24
src/engine/mobileAI/MobAI.java

@ -619,6 +619,30 @@ public class MobAI { @@ -619,6 +619,30 @@ public class MobAI {
public static void DetermineAction(Mob mob) {
try {
boolean override = false;
switch (mob.BehaviourType) {
case GuardCaptain:
case GuardMinion:
case GuardWallArcher:
case Pet1:
case HamletGuard:
override = false;
break;
default:
override = true;
break;
}
if(mob.isSiege())
override = false;
if(mob.isPet())
override = false;
if(override){
SuperSimpleMobAI.run(mob);
return;
}
//always check the respawn que, respawn 1 mob max per second to not flood the client

271
src/engine/mobileAI/MobHandlers/MobHandler.java

@ -1,9 +1,278 @@ @@ -1,9 +1,278 @@
package engine.mobileAI.MobHandlers;
import engine.objects.Mob;
import engine.Enum;
import engine.InterestManagement.InterestManager;
import engine.gameManager.ChatManager;
import engine.gameManager.PowersManager;
import engine.gameManager.ZoneManager;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.mobileAI.Threads.MobAIThread;
import engine.mobileAI.utilities.CombatUtilities;
import engine.mobileAI.utilities.MovementUtilities;
import engine.objects.*;
import engine.powers.PowersBase;
import engine.server.MBServerStatics;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
public class MobHandler {
public static void run(Mob mob){
if (!mob.isAlive()) {
CheckForRespawn(mob);
return;
}
if(mob.playerAgroMap.isEmpty())
return;
CheckToSendMobHome(mob);
if(mob.combatTarget == null || !mob.combatTarget.isAlive()){
CheckForAggro(mob);
return;
}
if(mob.combatTarget != null)
CheckToDropAggro(mob);
if(MovementUtilities.canMove(mob))
CheckMobMovement(mob);
if(mob.combatTarget != null && CombatUtilities.inRangeToAttack(mob,mob.combatTarget))
CheckToAttack(mob);
}
public static void CheckToDropAggro(Mob mob){
if(mob.loc.distanceSquared(mob.combatTarget.loc) > (64f * 64f))
mob.setCombatTarget(null);
}
public static void CheckForRespawn(Mob mob){
try {
if (mob.deathTime == 0) {
mob.setDeathTime(System.currentTimeMillis());
return;
}
//handles checking for respawn of dead mobs even when no players have mob loaded
//Despawn Timer with Loot currently in inventory.
if (!mob.despawned) {
if (mob.getCharItemManager().getInventoryCount() > 0) {
if (System.currentTimeMillis() > mob.deathTime + MBServerStatics.DESPAWN_TIMER_WITH_LOOT) {
mob.despawn();
mob.deathTime = System.currentTimeMillis();
return;
}
//No items in inventory.
} else if (mob.isHasLoot()) {
if (System.currentTimeMillis() > mob.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) {
mob.despawn();
mob.deathTime = System.currentTimeMillis();
return;
}
//Mob never had Loot.
} else {
if (System.currentTimeMillis() > mob.deathTime + MBServerStatics.DESPAWN_TIMER) {
mob.despawn();
mob.deathTime = System.currentTimeMillis();
return;
}
}
return;
}
if(Mob.discDroppers.contains(mob))
return;
if (mob.despawned && System.currentTimeMillis() > (mob.deathTime + (mob.spawnTime * 1000L))) {
if (!Zone.respawnQue.contains(mob)) {
Zone.respawnQue.add(mob);
}
}
} catch (Exception e) {
//(aiAgent.getObjectUUID() + " " + aiAgent.getName() + " Failed At: CheckForRespawn" + " " + e.getMessage());
}
}
public static void CheckForAggro(Mob mob){
PlayerCharacter tar = null;
for(int id : mob.playerAgroMap.keySet()){
PlayerCharacter target = PlayerCharacter.getFromCache(id);
if(tar == null || mob.loc.distanceSquared(tar.loc) < mob.loc.distanceSquared(target.loc))
if(MobCanAggro(mob,target))
tar = target;
}
}
public static Boolean MobCanAggro(Mob mob, PlayerCharacter loadedPlayer){
if (loadedPlayer == null)
return false;
//Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map.
if (!loadedPlayer.isAlive())
return false;
//Can't see target, skip aggro.
if (!mob.canSee(loadedPlayer))
return false;
// No aggro for this race type
if (mob.notEnemy != null && mob.notEnemy.size() > 0 && mob.notEnemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType()))
return false;
//mob has enemies and this player race is not it
if (mob.enemy != null && mob.enemy.size() > 0 && !mob.enemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType()))
return false;
return true;
}
public static void CheckMobMovement(Mob mob){
if(!mob.isAlive())
return;
if(mob.combatTarget == null){
//patrol
Patrol(mob);
}else{
//combat movement
if(CombatUtilities.inRangeToAttack(mob,mob.combatTarget))
return;
else
MovementUtilities.aiMove(mob,mob.combatTarget.loc,false);
}
}
public static void CheckToAttack(Mob mob){
try {
PlayerCharacter target = (PlayerCharacter) mob.combatTarget;
if (!mob.canSee(target)) {
mob.setCombatTarget(null);
return;
}
if (mob.BehaviourType.callsForHelp)
MobCallForHelp(mob);
if (mob.isMoving() && mob.getRange() > 20)
return;
if(target.combatStats == null)
target.combatStats = new PlayerCombatStats(target);
ItemBase mainHand = mob.getWeaponItemBase(true);
ItemBase offHand = mob.getWeaponItemBase(false);
if (mainHand == null && offHand == null) {
CombatUtilities.combatCycle(mob, target, true, null);
int delay = 3000;
mob.setLastAttackTime(System.currentTimeMillis() + delay);
} else if (mob.getWeaponItemBase(true) != null) {
int delay = 3000;
CombatUtilities.combatCycle(mob, target, true, mob.getWeaponItemBase(true));
mob.setLastAttackTime(System.currentTimeMillis() + delay);
} else if (mob.getWeaponItemBase(false) != null) {
int attackDelay = 3000;
CombatUtilities.combatCycle(mob, target, false, mob.getWeaponItemBase(false));
mob.setLastAttackTime(System.currentTimeMillis() + attackDelay);
}
if (target.getPet() != null)
if (target.getPet().getCombatTarget() == null && target.getPet().assist)
target.getPet().setCombatTarget(mob);
} catch (Exception e) {
////(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackPlayer" + " " + e.getMessage());
}
}
public static void MobCallForHelp(Mob mob) {
try {
boolean callGotResponse = false;
if (mob.nextCallForHelp == 0)
mob.nextCallForHelp = System.currentTimeMillis();
if (mob.nextCallForHelp < System.currentTimeMillis())
return;
//mob sends call for help message
ChatManager.chatSayInfo(null, mob.getName() + " calls for help!");
Zone mobCamp = mob.getParentZone();
for (Mob helper : mobCamp.zoneMobSet) {
if (helper.BehaviourType.respondsToCallForHelp && helper.BehaviourType.BehaviourHelperType.equals(mob.BehaviourType)) {
helper.setCombatTarget(mob.getCombatTarget());
callGotResponse = true;
}
}
//wait 60 seconds to call for help again
if (callGotResponse)
mob.nextCallForHelp = System.currentTimeMillis() + 60000;
} catch (Exception e) {
//(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCallForHelp" + " " + e.getMessage());
}
}
private static void Patrol(Mob mob) {
try {
//make sure mob is out of combat stance
int patrolDelay = ThreadLocalRandom.current().nextInt((int) (MobAIThread.AI_PATROL_DIVISOR * 0.5f), MobAIThread.AI_PATROL_DIVISOR) + MobAIThread.AI_PATROL_DIVISOR;
//early exit while waiting to patrol again
if (mob.stopPatrolTime + (patrolDelay * 1000) > System.currentTimeMillis())
return;
if (mob.lastPatrolPointIndex > mob.patrolPoints.size() - 1)
mob.lastPatrolPointIndex = 0;
mob.destination = mob.patrolPoints.get(mob.lastPatrolPointIndex);
mob.lastPatrolPointIndex += 1;
MovementUtilities.aiMove(mob, mob.destination, true);
} catch (Exception e) {
////(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackTarget" + " " + e.getMessage());
}
}
private static void CheckToSendMobHome(Mob mob) {
if(mob.isNecroPet())
return;
try {
if (!MovementUtilities.inRangeOfBindLocation(mob)) {
PowersBase recall = PowersManager.getPowerByToken(-1994153779);
PowersManager.useMobPower(mob, mob, recall, 40);
for (Map.Entry playerEntry : mob.playerAgroMap.entrySet())
PlayerCharacter.getFromCache((int) playerEntry.getKey()).setHateValue(0);
mob.setCombatTarget(null);
}
} catch (Exception e) {
//(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckToSendMobHome" + " " + e.getMessage());
}
}
}

Loading…
Cancel
Save