Browse Source

AI branches initial commit

lakebane-ai
FatBoy-DOTC 1 week ago
parent
commit
2fa9030682
  1. 9
      src/engine/mobileAI/Threads/MobAIThread.java
  2. 259
      src/engine/mobileAI/behaviours/GuardAI.java
  3. 17
      src/engine/mobileAI/behaviours/PetAI.java
  4. 89
      src/engine/mobileAI/behaviours/SiegeEngineAI.java
  5. 10
      src/engine/mobileAI/behaviours/StandardAI.java

9
src/engine/mobileAI/Threads/MobAIThread.java

@ -3,6 +3,8 @@ package engine.mobileAI.Threads;
import engine.gameManager.ConfigManager; import engine.gameManager.ConfigManager;
import engine.mobileAI.MobAI; import engine.mobileAI.MobAI;
import engine.gameManager.ZoneManager; import engine.gameManager.ZoneManager;
import engine.mobileAI.behaviours.GuardAI;
import engine.mobileAI.behaviours.SiegeEngineAI;
import engine.objects.Mob; import engine.objects.Mob;
import engine.objects.Zone; import engine.objects.Zone;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
@ -33,6 +35,13 @@ public class MobAIThread implements Runnable{
for (Mob mob : zone.zoneMobSet) { for (Mob mob : zone.zoneMobSet) {
try { try {
if (mob != null) { if (mob != null) {
if(mob.isSiege()){
SiegeEngineAI.run(mob);
continue;
}else if(mob.isPlayerGuard){
GuardAI.run(mob);
continue;
}
MobAI.DetermineAction(mob); MobAI.DetermineAction(mob);
} }
} catch (Exception e) { } catch (Exception e) {

259
src/engine/mobileAI/behaviours/GuardAI.java

@ -0,0 +1,259 @@
package engine.mobileAI.behaviours;
import engine.Enum;
import engine.gameManager.MovementManager;
import engine.gameManager.PowersManager;
import engine.gameManager.ZoneManager;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.mobileAI.utilities.CombatUtilities;
import engine.mobileAI.utilities.MovementUtilities;
import engine.objects.*;
import engine.powers.MobPowerEntry;
import engine.powers.PowersBase;
import org.pmw.tinylog.Logger;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
public class GuardAI {
public static HashMap<Mob,PowersBase> quedPowerCasts = new HashMap<>();
public static void run(Mob guard){
//1. check for players nearby to aggro to
if(guard.combatTarget == null)
CheckForPlayerGuardAggro(guard);
//2. patrol if no target acquired
if(guard.combatTarget == null) {
patrol(guard);
return;
}
//3. attack based on whether spellcaster, archer or mele
if(guard.mobPowers.isEmpty()){
if(guard.getEquip().get(2) != null && guard.getEquip().get(2).getItemBase().getRange() > 20) {
runArcher(guard);
}else {
runMele(guard);
}
}else{
runCaster(guard);
}
}
public static void runCaster(Mob guard){
}
public static void runMele(Mob guard){
}
public static void runArcher(Mob guard){
}
public static void CheckForPlayerGuardAggro(Mob mob) {
try {
//looks for and sets mobs combatTarget
if (!mob.isAlive())
return;
ConcurrentHashMap<Integer, Boolean> loadedPlayers = mob.playerAgroMap;
for (Map.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 (!mob.canSee(loadedPlayer))
continue;
// No aggro for this player
if (GuardCanAggro(mob, loadedPlayer) == false)
continue;
if (MovementUtilities.inRangeToAggro(mob, loadedPlayer) && mob.getCombatTarget() == null) {
mob.setCombatTarget(loadedPlayer);
return;
}
}
} catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckForPlayerGuardAggro" + e.getMessage());
}
}
public static Boolean GuardCanAggro(Mob mob, PlayerCharacter target) {
try {
if (mob.getGuild().getNation().equals(target.getGuild().getNation()))
return false;
if (mob.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardMinion.ordinal()) {
if (((Mob) mob.npcOwner).building.getCity().cityOutlaws.contains(target.getObjectUUID()) == true) {
return true;
}
} else if (mob.building.getCity().cityOutlaws.contains(target.getObjectUUID()) == true) {
return true;
}
//first check condemn list for aggro allowed (allies button is checked)
if (ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().reverseKOS) {
for (Map.Entry<Integer, Condemned> entry : ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().getCondemned().entrySet()) {
//target is listed individually
if (entry.getValue().getPlayerUID() == target.getObjectUUID() && entry.getValue().isActive())
return false;
//target's guild is listed
if (Guild.getGuild(entry.getValue().getGuildUID()) == target.getGuild())
return false;
//target's nation is listed
if (Guild.getGuild(entry.getValue().getGuildUID()) == target.getGuild().getNation())
return false;
}
return true;
} else {
//allies button is not checked
for (Map.Entry<Integer, Condemned> entry : ZoneManager.getCityAtLocation(mob.getLoc()).getTOL().getCondemned().entrySet()) {
//target is listed individually
if (entry.getValue().getPlayerUID() == target.getObjectUUID() && entry.getValue().isActive())
return true;
//target's guild is listed
if (Guild.getGuild(entry.getValue().getGuildUID()) == target.getGuild())
return true;
//target's nation is listed
if (Guild.getGuild(entry.getValue().getGuildUID()) == target.getGuild().getNation())
return true;
}
}
} catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardCanAggro" + " " + e.getMessage());
}
return false;
}
public static void randomGuardPatrolPoint(Mob mob) {
try {
//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) {
mob.stopPatrolTime = System.currentTimeMillis();
return;
}
//wait between 10 and 15 seconds after reaching patrol point before moving
int patrolDelay = ThreadLocalRandom.current().nextInt(10000) + 5000;
//early exit while waiting to patrol again
if (mob.stopPatrolTime + patrolDelay > System.currentTimeMillis())
return;
float xPoint = ThreadLocalRandom.current().nextInt(400) - 200;
float zPoint = ThreadLocalRandom.current().nextInt(400) - 200;
Vector3fImmutable TreePos = mob.getGuild().getOwnedCity().getLoc();
mob.destination = new Vector3fImmutable(TreePos.x + xPoint, TreePos.y, TreePos.z + zPoint);
MovementUtilities.aiMove(mob, mob.destination, true);
if (mob.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardCaptain.ordinal()) {
for (Map.Entry<Mob, Integer> minion : mob.siegeMinionMap.entrySet()) {
//make sure mob is out of combat stance
if (minion.getKey().despawned == false) {
if (MovementUtilities.canMove(minion.getKey())) {
Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3);
minion.getKey().updateLocation();
Vector3fImmutable formationPatrolPoint = new Vector3fImmutable(mob.destination.x + minionOffset.x, mob.destination.y, mob.destination.z + minionOffset.z);
MovementUtilities.aiMove(minion.getKey(), formationPatrolPoint, true);
}
}
}
}
} catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: randomGuardPatrolPoints" + " " + e.getMessage());
}
}
public static void patrol(Mob guard){
if (!guard.BehaviourType.equals(Enum.MobBehaviourType.GuardCaptain) && guard.npcOwner.isAlive())
return;
//patrol
Building barracks = guard.building;
if (barracks != null && barracks.patrolPoints != null && !barracks.getPatrolPoints().isEmpty()) {
guard.patrolPoints = barracks.patrolPoints;
} else {
randomGuardPatrolPoint(guard);
return;
}
if (guard.lastPatrolPointIndex > guard.patrolPoints.size() - 1)
guard.lastPatrolPointIndex = 0;
guard.destination = guard.patrolPoints.get(guard.lastPatrolPointIndex);
guard.lastPatrolPointIndex += 1;
MovementUtilities.aiMove(guard, guard.destination, true);
if (guard.BehaviourType.equals(Enum.MobBehaviourType.GuardCaptain)) {
for (Map.Entry<Mob, Integer> minion : guard.siegeMinionMap.entrySet())
//make sure mob is out of combat stance
if (!minion.getKey().despawned) {
if (MovementUtilities.canMove(minion.getKey())) {
Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3);
minion.getKey().updateLocation();
Vector3fImmutable formationPatrolPoint = new Vector3fImmutable(guard.destination.x + minionOffset.x, guard.destination.y, guard.destination.z + minionOffset.z);
MovementUtilities.aiMove(minion.getKey(), formationPatrolPoint, true);
}
}
}
}
}

17
src/engine/mobileAI/behaviours/PetAI.java

@ -0,0 +1,17 @@
package engine.mobileAI.behaviours;
import engine.objects.Mob;
public class PetAI {
public static void run(Mob pet){
//1. check for combat
//2. check for distance from player
//3. follow player
//4. chase combat target
}
}

89
src/engine/mobileAI/behaviours/SiegeEngineAI.java

@ -0,0 +1,89 @@
package engine.mobileAI.behaviours;
import engine.Enum;
import engine.gameManager.BuildingManager;
import engine.gameManager.CombatManager;
import engine.gameManager.MovementManager;
import engine.gameManager.ZoneManager;
import engine.mobileAI.utilities.CombatUtilities;
import engine.objects.Building;
import engine.objects.City;
import engine.objects.Mob;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
public class SiegeEngineAI {
public static void run(Mob engine) {
//1. check to respawn if engine is dead or initially spawning
if (!engine.isAlive() || engine.despawned) {
if (System.currentTimeMillis() - engine.deathTime > MBServerStatics.FIFTEEN_MINUTES) {
engine.respawn();
return;
}
}
//2. early exit if owner is null, siege engines cannot act with player intervention
if (engine.getOwner() == null)
return;
//3. early exit if target is null, siege engines have no purpose without a target
if (engine.combatTarget == null)
return;
//4. early exit if target is not a building, siege engines can only attack buildings
if (!engine.combatTarget.getObjectType().equals(Enum.GameObjectType.Building)) {
engine.setCombatTarget(null);
return;
}
//5. early exit if target is out of range, engines don't move and neither do buildings, avoid infinite loop
if(CombatManager.NotInRange(engine,engine.combatTarget,engine.getRange())) {
engine.setCombatTarget(null);
return;
}
//6. attack target, sanity checks passed, attack target
AttackBuilding(engine,(Building) engine.combatTarget);
}
public static void AttackBuilding(Mob engine, Building target) {
try {
if (engine == null || target == null)
return;
if (target.getRank() == -1 || !target.isVulnerable() || BuildingManager.getBuildingFromCache(target.getObjectUUID()) == null) {
engine.setCombatTarget(null);
return;
}
City playercity = ZoneManager.getCityAtLocation(engine.getLoc());
if (playercity != null)
for (Mob guard : playercity.getParent().zoneMobSet)
if (guard.BehaviourType != null && guard.BehaviourType.equals(Enum.MobBehaviourType.GuardCaptain))
if (guard.getCombatTarget() == null && guard.getGuild() != null && engine.getGuild() != null && !guard.getGuild().equals(engine.getGuild()))
guard.setCombatTarget(engine);
MovementManager.sendRWSSMsg(engine);
CombatUtilities.combatCycle(engine, target, true, null);
int delay = 15000;
engine.setLastAttackTime(System.currentTimeMillis() + delay);
//if (mob.isSiege()) {
// PowerProjectileMsg ppm = new PowerProjectileMsg(mob, target);
// ppm.setRange(50);
// DispatchMessage.dispatchMsgToInterestArea(mob, ppm, DispatchChannel.SECONDARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
//}
} catch (Exception e) {
Logger.info(engine.getObjectUUID() + " " + engine.getName() + " Failed At: AttackBuilding" + " " + e.getMessage());
}
}
}

10
src/engine/mobileAI/behaviours/StandardAI.java

@ -0,0 +1,10 @@
package engine.mobileAI.behaviours;
import engine.objects.Mob;
public class StandardAI {
public static void run(Mob mob){
}
}
Loading…
Cancel
Save