Compare commits

...

4 Commits

Author SHA1 Message Date
FatBoy 70e5665633 Ai players 2025-02-25 06:16:36 -06:00
FatBoy f9d96dbbd4 Ai player 2025-02-25 05:30:26 -06:00
FatBoy 071cb87015 Ai player 2025-02-23 21:01:48 -06:00
FatBoy 93d80c0005 split system mob AI 2025-02-23 20:44:56 -06:00
11 changed files with 1717 additions and 10 deletions
+139
View File
@@ -0,0 +1,139 @@
package engine;
import engine.InterestManagement.WorldGrid;
import engine.gameManager.BuildingManager;
import engine.gameManager.ChatManager;
import engine.math.Vector3fImmutable;
import engine.objects.*;
import engine.server.MBServerStatics;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
public class PlayerAi {
public static ArrayList<PlayerCharacter> ai_players = new ArrayList<>();
public static void addPlayer(PlayerCharacter pc){
ai_players.add(pc);
int index = ai_players.indexOf(pc);
pc.setObjectUUID(MBServerStatics.NO_DB_ROW_ASSIGNED_YET - (1 + index));
}
public static void populate_world(){
for(Mine mine : Mine.getMines()){
Building tower = BuildingManager.getBuildingFromCache(mine.getBuildingID());
if(tower != null){
for(int i = 0; i < mine.capSize; i++){
addPlayer(createPlayer(tower));
}
}
}
}
public static PlayerCharacter createPlayer(Building tower){
Vector3fImmutable loc = Vector3fImmutable.getRandomPointOnCircle(tower.loc,40f);
//get random race
Race race = null;
while(race == null) {
int raceId = ThreadLocalRandom.current().nextInt(1999, 2030);
while (raceId == 2021 || raceId == 2020 || raceId == 2019 || raceId == 2018) {
raceId = ThreadLocalRandom.current().nextInt(1999, 2030);
}
race = Race.getRace(raceId);
}
//get random baseClass
BaseClass baseClass = null;
while(baseClass == null) {
int baseId = ThreadLocalRandom.current().nextInt(2499, 2505);
BaseClass temp = BaseClass.getBaseClass(baseId);
if (temp == null || !race.getValidBaseClasses().contains(temp)) {
continue;
}
baseClass = BaseClass.getBaseClass(baseId);
}
PlayerCharacter newPLayer = new PlayerCharacter("", "AI POWERED", (short) 5, (short) 5, (short) 5, (short) 5,
(short) 5, Guild.getGuild(5), (byte) 0, (Account) null, race, baseClass
, (byte) 1, (byte) 1,
(byte) 1, (byte) 1, (byte) 1);
newPLayer.runAfterLoad();
if(newPLayer.isMale()) {
newPLayer.setFirstName(getMaleName());
}else {
newPLayer.setFirstName(getFemaleName());
}
newPLayer.setLevel((short)10);
PromotionClass promo = null;
while(promo == null){
int promoId = ThreadLocalRandom.current().nextInt(2508,2526);
PromotionClass temp = PromotionClass.GetPromtionClassFromCache(promoId);
if(temp == null)
continue;
if(!temp.isAllowedRune(race.getToken()))
continue;
if(!temp.isAllowedRune(baseClass.getToken()))
continue;
promo = PromotionClass.GetPromtionClassFromCache(promoId);
}
newPLayer.setPromotionClass(promo.getObjectUUID());
newPLayer.setLevel((short)75);
newPLayer.setLoc(loc);
newPLayer.setObjectTypeMask(MBServerStatics.MASK_PLAYER);
WorldGrid.addObject(newPLayer,loc.x,loc.z);
return newPLayer;
}
public static void run_ai_players() {
for (PlayerCharacter pc : ai_players) {
}
}
public static String getMaleName(){
String[] maleNames = {
"James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph", "Thomas", "Charles",
"Christopher", "Daniel", "Matthew", "Anthony", "Mark", "Donald", "Steven", "Paul", "Andrew", "Joshua",
"Kenneth", "Kevin", "Brian", "George", "Edward", "Ronald", "Timothy", "Jason", "Jeffrey", "Ryan",
"Jacob", "Gary", "Nicholas", "Eric", "Jonathan", "Stephen", "Larry", "Justin", "Scott", "Brandon",
"Benjamin", "Samuel", "Gregory", "Alexander", "Patrick", "Frank", "Raymond", "Jack", "Dennis", "Jerry",
"Tyler", "Aaron", "Jose", "Adam", "Nathan", "Henry", "Douglas", "Zachary", "Peter", "Kyle",
"Walter", "Ethan", "Jeremy", "Harold", "Keith", "Christian", "Roger", "Noah", "Gerald", "Carl",
"Terry", "Sean", "Austin", "Arthur", "Lawrence", "Jesse", "Dylan", "Bryan", "Joe", "Jordan",
"Billy", "Bruce", "Albert", "Willie", "Gabriel", "Logan", "Alan", "Juan", "Wayne", "Roy",
"Ralph", "Randy", "Eugene", "Vincent", "Russell", "Louis", "Philip", "Bobby", "Johnny", "Bradley"
};
Random random = new Random();
return maleNames[random.nextInt(maleNames.length)];
}
public static String getFemaleName(){
String[] femaleNames = {
"Mary", "Patricia", "Jennifer", "Linda", "Elizabeth", "Barbara", "Susan", "Jessica", "Sarah", "Karen",
"Nancy", "Lisa", "Betty", "Margaret", "Sandra", "Ashley", "Kimberly", "Emily", "Donna", "Michelle",
"Carol", "Amanda", "Melissa", "Deborah", "Stephanie", "Rebecca", "Laura", "Sharon", "Cynthia", "Kathleen",
"Amy", "Shirley", "Angela", "Helen", "Anna", "Brenda", "Pamela", "Nicole", "Samantha", "Katherine",
"Christine", "Debra", "Rachel", "Catherine", "Carolyn", "Janet", "Ruth", "Maria", "Heather", "Diane",
"Virginia", "Julie", "Joyce", "Victoria", "Kelly", "Christina", "Lauren", "Joan", "Evelyn", "Judith",
"Olivia", "Frances", "Martha", "Cheryl", "Megan", "Andrea", "Hannah", "Jacqueline", "Ann", "Gloria",
"Jean", "Kathryn", "Alice", "Teresa", "Sara", "Janice", "Doris", "Madison", "Julia", "Grace",
"Judy", "Abigail", "Marie", "Denise", "Beverly", "Amber", "Theresa", "Marilyn", "Danielle", "Diana",
"Brittany", "Natalie", "Sophia", "Rose", "Isabella", "Alexis", "Kayla", "Charlotte", "Faith", "Alyssa"
};
Random random = new Random();
return femaleNames[random.nextInt(femaleNames.length)];
}
}
+25 -8
View File
@@ -1,8 +1,12 @@
package engine.devcmd.cmds; package engine.devcmd.cmds;
import engine.Enum;
import engine.InterestManagement.WorldGrid;
import engine.PlayerAi;
import engine.devcmd.AbstractDevCmd; import engine.devcmd.AbstractDevCmd;
import engine.objects.AbstractGameObject; import engine.math.Vector3fImmutable;
import engine.objects.PlayerCharacter; import engine.objects.*;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
/** /**
@@ -24,12 +28,25 @@ public class RebootCmd extends AbstractDevCmd {
protected void _doCmd(PlayerCharacter pc, String[] args, protected void _doCmd(PlayerCharacter pc, String[] args,
AbstractGameObject target) { AbstractGameObject target) {
try { //try {
Runtime rt = Runtime.getRuntime(); // Runtime rt = Runtime.getRuntime();
rt.exec("./mbrestart.sh"); // rt.exec("./mbrestart.sh");
} catch (java.io.IOException err) { //} catch (java.io.IOException err) {
Logger.info(err.getMessage()); // Logger.info(err.getMessage());
} //}
PlayerCharacter newPLayer = new PlayerCharacter("AiPlayer", "AI POWERED", (short) 5, (short) 5, (short) 5, (short) 5,
(short) 5, Guild.getErrantGuild(), (byte) 0, (Account) null, Race.getRace(1999), BaseClass.getBaseClass(2500)
, (byte) 1, (byte) 1,
(byte) 1, (byte) 1, (byte) 1);
newPLayer.runAfterLoad();
newPLayer.setLoc(pc.loc);
newPLayer.setObjectTypeMask(MBServerStatics.MASK_PLAYER);
WorldGrid.addObject(newPLayer,pc.loc.x,pc.loc.z);
//WorldGrid.updateObject(newPLayer);
PlayerAi.addPlayer(newPLayer);
} }
@@ -0,0 +1,33 @@
package engine.mobileAI.MobBehaviours;
import engine.gameManager.ZoneManager;
import engine.mobileAI.utilities.MovementUtilities;
import engine.objects.Mob;
import org.pmw.tinylog.Logger;
public class Pet {
public static void run(Mob pet){
try {
if(StaticBehaviours.EarlyExit(pet))
return;
if (pet.getOwner() == null && pet.isNecroPet() == false && pet.isSiege() == false)
if (ZoneManager.getSeaFloor().zoneMobSet.contains(pet))
pet.killCharacter("no owner");
if(!pet.isSiege())
pet.BehaviourType.canRoam = true;
if (MovementUtilities.canMove(pet) && pet.BehaviourType.canRoam)
StaticBehaviours.CheckMobMovement(pet);
StaticBehaviours.CheckForAttack(pet);
} catch (Exception e) {
Logger.info(pet.getObjectUUID() + " " + pet.getName() + " Failed At: PetLogic" + " " + e.getMessage());
}
}
}
@@ -0,0 +1,146 @@
package engine.mobileAI.MobBehaviours;
import engine.Enum;
import engine.objects.AbstractWorldObject;
import engine.objects.Mob;
import engine.objects.PlayerCharacter;
import org.pmw.tinylog.Logger;
public class PlayerGuard {
public static void run(Mob guard) {
if(StaticBehaviours.EarlyExit(guard))
return;
if (guard.mobPowers.isEmpty()) {
//mele
if (guard.BehaviourType.equals(Enum.MobBehaviourType.GuardWallArcher)) {
GuardWallArcherLogic(guard);
} else {
if (guard.BehaviourType.equals(Enum.MobBehaviourType.GuardCaptain)) {
GuardCaptainLogic(guard);
} else if (guard.BehaviourType.equals(Enum.MobBehaviourType.GuardMinion)) {
GuardMinionLogic(guard);
}
}
} else {
//caster
if (guard.BehaviourType.equals(Enum.MobBehaviourType.GuardCaptain)) {
MagisterCaptainLogic(guard);
} else if (guard.BehaviourType.equals(Enum.MobBehaviourType.GuardMinion)) {
MagisterMinionLogic(guard);
}
}
}
public static void GuardCaptainLogic(Mob mob) {
try {
StaticBehaviours.checkToDropGuardAggro(mob);
if (mob.getCombatTarget() == null)
StaticBehaviours.CheckForPlayerGuardAggro(mob);
AbstractWorldObject newTarget = StaticBehaviours.ChangeTargetFromHateValue(mob);
if (newTarget != null) {
if (newTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) {
if (StaticBehaviours.GuardCanAggro(mob, (PlayerCharacter) newTarget))
mob.setCombatTarget(newTarget);
} else
mob.setCombatTarget(newTarget);
}
StaticBehaviours.CheckMobMovement(mob);
StaticBehaviours.CheckForAttack(mob);
} catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardCaptainLogic" + " " + e.getMessage());
}
}
public static void GuardMinionLogic(Mob mob) {
try {
StaticBehaviours.checkToDropGuardAggro(mob);
boolean isComanded = mob.npcOwner.isAlive();
if (!isComanded) {
GuardCaptainLogic(mob);
}else {
if (mob.npcOwner.getCombatTarget() != null)
mob.setCombatTarget(mob.npcOwner.getCombatTarget());
else
if (mob.getCombatTarget() != null)
mob.setCombatTarget(null);
}
StaticBehaviours.CheckMobMovement(mob);
StaticBehaviours.CheckForAttack(mob);
} catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardMinionLogic" + " " + e.getMessage());
}
}
public static void GuardWallArcherLogic(Mob mob) {
try {
StaticBehaviours.checkToDropGuardAggro(mob);
if (mob.getCombatTarget() == null)
StaticBehaviours.CheckForPlayerGuardAggro(mob);
else
StaticBehaviours.CheckForAttack(mob);
} catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardWallArcherLogic" + " " + e.getMessage());
}
}
public static void MagisterCaptainLogic(Mob mob){
try {
StaticBehaviours.checkToDropGuardAggro(mob);
if (mob.getCombatTarget() == null)
StaticBehaviours.CheckForPlayerGuardAggro(mob);
AbstractWorldObject newTarget = StaticBehaviours.ChangeTargetFromHateValue(mob);
if (newTarget != null) {
if (newTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) {
if (StaticBehaviours.GuardCanAggro(mob, (PlayerCharacter) newTarget))
mob.setCombatTarget(newTarget);
} else
mob.setCombatTarget(newTarget);
}
StaticBehaviours.CheckMobMovement(mob);
CheckForCast(mob);
} catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardCaptainLogic" + " " + e.getMessage());
}
}
public static void MagisterMinionLogic(Mob mob){
try {
StaticBehaviours.checkToDropGuardAggro(mob);
boolean isComanded = mob.npcOwner.isAlive();
if (!isComanded) {
MagisterCaptainLogic(mob);
}else {
if (mob.npcOwner.getCombatTarget() != null)
mob.setCombatTarget(mob.npcOwner.getCombatTarget());
else
if (mob.getCombatTarget() != null)
mob.setCombatTarget(null);
}
StaticBehaviours.CheckMobMovement(mob);
CheckForCast(mob);
} catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardMinionLogic" + " " + e.getMessage());
}
}
public static void CheckForCast(Mob mob){
}
}
@@ -0,0 +1,27 @@
package engine.mobileAI.MobBehaviours;
import engine.Enum;
import engine.objects.Mob;
public class SiegeEngine {
public static void run(Mob engine){
if(StaticBehaviours.EarlyExit(engine))
return;
if(engine.getOwner() == null)
return;
if(engine.combatTarget == null)
return;
if(engine.combatTarget.loc.distanceSquared(engine.loc) > engine.getRange() * engine.getRange())
return;
if(!engine.combatTarget.getObjectType().equals(Enum.GameObjectType.Building))
return;
StaticBehaviours.CheckForAttack(engine);
}
}
@@ -0,0 +1,53 @@
package engine.mobileAI.MobBehaviours;
import engine.Enum;
import engine.objects.AbstractWorldObject;
import engine.objects.Mob;
import org.pmw.tinylog.Logger;
public class Standard {
public static void run(Mob mob){
try {
if(StaticBehaviours.EarlyExit(mob))
return;
//check for players that can be aggroed if mob is agressive and has no target
if (mob.getCombatTarget() != null && !mob.playerAgroMap.containsKey(mob.getCombatTarget().getObjectUUID()))
mob.setCombatTarget(null);
if (mob.BehaviourType.isAgressive) {
AbstractWorldObject newTarget = StaticBehaviours.ChangeTargetFromHateValue(mob);
if (newTarget != null)
mob.setCombatTarget(newTarget);
else {
if (mob.getCombatTarget() == null) {
if (mob.BehaviourType == Enum.MobBehaviourType.HamletGuard)
StaticBehaviours.SafeGuardAggro(mob); //safehold guard
else
StaticBehaviours.CheckForAggro(mob); //normal aggro
}
}
}
//check if mob can move for patrol or moving to target
if (mob.BehaviourType.canRoam)
StaticBehaviours.CheckMobMovement(mob);
//check if mob can attack if it isn't wimpy
if (!mob.BehaviourType.isWimpy && mob.getCombatTarget() != null)
StaticBehaviours.CheckForAttack(mob);
} catch (Exception e) {
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: DefaultLogic" + " " + e.getMessage());
}
}
}
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -3,6 +3,7 @@ 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.MobBehaviours.StaticBehaviours;
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,7 +34,8 @@ public class MobAIThread implements Runnable{
for (Mob mob : zone.zoneMobSet) { for (Mob mob : zone.zoneMobSet) {
try { try {
if (mob != null) { if (mob != null) {
MobAI.DetermineAction(mob); //MobAI.DetermineAction(mob);
StaticBehaviours.runBehaviour(mob);
} }
} catch (Exception e) { } catch (Exception e) {
Logger.error("Error processing Mob [Name: {}, UUID: {}]", mob.getName(), mob.getObjectUUID(), e); Logger.error("Error processing Mob [Name: {}, UUID: {}]", mob.getName(), mob.getObjectUUID(), e);
+1 -1
View File
@@ -169,7 +169,7 @@ public abstract class AbstractGameObject {
return this.objectUUID; return this.objectUUID;
} }
protected void setObjectUUID(int objectUUID) { public void setObjectUUID(int objectUUID) {
this.objectUUID = objectUUID; this.objectUUID = objectUUID;
} }
@@ -618,6 +618,8 @@ public abstract class AbstractWorldObject extends AbstractGameObject {
} }
public GridObjectType getGridObjectType() { public GridObjectType getGridObjectType() {
if(gridObjectType == null)
gridObjectType = GridObjectType.DYNAMIC;
return gridObjectType; return gridObjectType;
} }
+3
View File
@@ -17,6 +17,7 @@ import engine.Enum.SupportMsgType;
import engine.InterestManagement.HeightMap; import engine.InterestManagement.HeightMap;
import engine.InterestManagement.RealmMap; import engine.InterestManagement.RealmMap;
import engine.InterestManagement.WorldGrid; import engine.InterestManagement.WorldGrid;
import engine.PlayerAi;
import engine.db.archive.DataWarehouse; import engine.db.archive.DataWarehouse;
import engine.exception.MsgSendException; import engine.exception.MsgSendException;
import engine.gameManager.*; import engine.gameManager.*;
@@ -530,6 +531,8 @@ public class WorldServer {
Logger.info("Starting Player Update Thread"); Logger.info("Starting Player Update Thread");
UpdateThread.startUpdateThread(); UpdateThread.startUpdateThread();
Logger.info("Spawnign AI Players");
PlayerAi.populate_world();
printThreads(); printThreads();
Logger.info("Threads Running:"); Logger.info("Threads Running:");