Compare commits

...

19 Commits

Author SHA1 Message Date
MagicBot 779e3da74e Cleanup of clear minion logic. 2023-09-01 14:33:33 -04:00
MagicBot e358c08773 Removed msg from handler. 2023-09-01 14:23:55 -04:00
MagicBot 2945fa3a47 Class reformat and removal of try block. 2023-09-01 14:17:07 -04:00
MagicBot ab1541e741 Class not needed on login server. 2023-09-01 14:09:48 -04:00
MagicBot 3aeaa709a5 Comment cleanup 2023-09-01 14:07:00 -04:00
MagicBot 91e627df6b AI moved to top of runafterload. 2023-09-01 14:05:50 -04:00
MagicBot d0795e9e1c Rework of agent type init in runafterload. Only used for 2 instances from disk. 2023-09-01 13:57:58 -04:00
MagicBot 0e12dd4874 Contract powers loaded first to preserve ordering. 2023-09-01 12:57:20 -04:00
MagicBot 25c0e48181 Loot bypass now uses agent type. 2023-09-01 12:55:33 -04:00
MagicBot 0d43c3620d Value is set earlier. 2023-09-01 12:50:57 -04:00
MagicBot 2f6137f8df Minion agent type set properly. 2023-09-01 12:38:23 -04:00
FatBoy 2843b86a93 Moved agent type to top of constructor. 2023-09-01 12:29:06 -04:00
MagicBot 8235de07ff Updated output of devcmd. 2023-08-31 14:00:34 -04:00
MagicBot e2f9a4c7f0 Guard minions inherit powers from captain. 2023-08-31 13:57:46 -04:00
MagicBot 55c6e3cf93 Refactored out duplicate power collection. 2023-08-31 13:42:15 -04:00
MagicBot 11c154e564 Assignment fix and comment cleanup. 2023-08-31 08:58:55 -04:00
MagicBot 7fc0d27c3c Siege engine agent type set properly. 2023-08-31 08:31:48 -04:00
MagicBot 1ac76cfcd8 isPlayerguard refactored to derive from agenttype. 2023-08-31 08:13:37 -04:00
MagicBot c8ed04aaaf Refactor to separate persistence and write fsm to table. 2023-08-31 08:03:30 -04:00
11 changed files with 194 additions and 180 deletions
+4 -3
View File
@@ -2877,10 +2877,11 @@ public class Enum {
public enum AIAgentType { public enum AIAgentType {
MOBILE, MOBILE,
GUARDCAPTAIN,
GUARDMINION,
GUARDWALLARCHER,
PET, PET,
CHARMED, CHARMED,
SIEGEENGINE;
SIEGEENGINE,
GUARD;
} }
} }
+2 -1
View File
@@ -33,7 +33,7 @@ public class dbMobHandler extends dbHandlerBase {
Mob mobile = null; Mob mobile = null;
try (Connection connection = DbManager.getConnection(); try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("CALL `mob_CREATE`(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")) { PreparedStatement preparedStatement = connection.prepareStatement("CALL `mob_CREATE`(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")) {
preparedStatement.setLong(1, toAdd.parentZoneUUID); preparedStatement.setLong(1, toAdd.parentZoneUUID);
preparedStatement.setInt(2, toAdd.loadID); preparedStatement.setInt(2, toAdd.loadID);
@@ -48,6 +48,7 @@ public class dbMobHandler extends dbHandlerBase {
preparedStatement.setInt(11, toAdd.buildingUUID); preparedStatement.setInt(11, toAdd.buildingUUID);
preparedStatement.setInt(12, toAdd.level); preparedStatement.setInt(12, toAdd.level);
preparedStatement.setString(13, toAdd.firstName); preparedStatement.setString(13, toAdd.firstName);
preparedStatement.setString(14, toAdd.behaviourType.toString());
ResultSet rs = preparedStatement.executeQuery(); ResultSet rs = preparedStatement.executeQuery();
+3 -2
View File
@@ -15,6 +15,7 @@ import engine.gameManager.PowersManager;
import engine.objects.AbstractGameObject; import engine.objects.AbstractGameObject;
import engine.objects.Mob; import engine.objects.Mob;
import engine.objects.PlayerCharacter; import engine.objects.PlayerCharacter;
import engine.powers.MobPowerEntry;
import java.util.Map; import java.util.Map;
@@ -90,8 +91,8 @@ public class aiInfoCmd extends AbstractDevCmd {
output += "Powers:" + newline; output += "Powers:" + newline;
for (int token : mob.mobPowers.keySet()) for (MobPowerEntry mobPowerEntry : PowersManager.getPowersForMobile(mob))
output += PowersManager.getPowerByToken(token).getName() + newline; output += PowersManager.getPowerByToken(mobPowerEntry.token).getName() + newline;
throwbackInfo(playerCharacter, output); throwbackInfo(playerCharacter, output);
} }
+32 -10
View File
@@ -530,41 +530,63 @@ public enum BuildingManager {
else else
rank = 10; rank = 10;
Mob mob; Mob mobile;
NPC npc; NPC npc;
if (NPC.ISWallArcher(contract)) { if (NPC.ISWallArcher(contract)) {
mob = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, building, contract, pirateName, rank); mobile = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, building, contract, pirateName, rank);
if (mob == null) if (mobile == null)
return false; return false;
mob.setLoc(mob.getLoc()); // Configure AI and write new mobile to disk
mobile.behaviourType = Enum.MobBehaviourType.GuardWallArcher;
mobile = DbManager.MobQueries.PERSIST(mobile);
// Spawn new mobile
mobile.setLoc(mobile.getLoc());
return true; return true;
} }
if (NPC.ISGuardCaptain(contract.getContractID())) { if (NPC.ISGuardCaptain(contract.getContractID())) {
mob = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, building, contract, pirateName, rank); mobile = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, building, contract, pirateName, rank);
if (mob == null) if (mobile == null)
return false; return false;
mob.setLoc(mob.getLoc()); // Configure AI and write new mobile to disk
mobile.behaviourType = Enum.MobBehaviourType.GuardCaptain;
mobile = DbManager.MobQueries.PERSIST(mobile);
// Spawn new mobile
mobile.setLoc(mobile.getLoc());
return true; return true;
} }
if (contract.getContractID() == 910) { if (contract.getContractID() == 910) {
//guard dog //guard dog
mob = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, building, contract, pirateName, rank); mobile = Mob.createMob(contract.getMobbaseID(), Vector3fImmutable.ZERO, contractOwner.getGuild(), zone, building, contract, pirateName, rank);
if (mob == null) if (mobile == null)
return false; return false;
mob.setLoc(mob.getLoc()); // Configure AI and write new mobile to disk
mobile.behaviourType = Enum.MobBehaviourType.GuardCaptain;
mobile = DbManager.MobQueries.PERSIST(mobile);
// Spawn new mobile
mobile.setLoc(mobile.getLoc());
return true; return true;
} }
+1 -8
View File
@@ -30,18 +30,11 @@ public enum NPCManager {
if (mob.runeSet == 0) if (mob.runeSet == 0)
return; return;
//Apply all rune effects.
if (NPCManager._runeSetMap.get(mob.runeSet).contains(252623)) {
mob.isPlayerGuard = true;
}
// Only captains have contracts // Only captains have contracts
if (mob.contract != null || mob.isPlayerGuard) if (mob.contract != null || mob.isPlayerGuard())
applyEffectsForRune(mob, 252621); applyEffectsForRune(mob, 252621);
// Apply effects from RuneSet // Apply effects from RuneSet
if (mob.runeSet != 0) if (mob.runeSet != 0)
+25 -1
View File
@@ -53,7 +53,7 @@ public enum PowersManager {
public static HashMap<Integer, AbstractPowerAction> powerActionsByID = new HashMap<>(); public static HashMap<Integer, AbstractPowerAction> powerActionsByID = new HashMap<>();
public static HashMap<String, Integer> ActionTokenByIDString = new HashMap<>(); public static HashMap<String, Integer> ActionTokenByIDString = new HashMap<>();
public static HashMap<String, Integer> AnimationOverrides = new HashMap<>(); public static HashMap<String, Integer> AnimationOverrides = new HashMap<>();
public static HashMap<Integer, ArrayList<MobPowerEntry>> AllMobPowers; public static HashMap<Integer, ArrayList<MobPowerEntry>> _allMobPowers;
private static JobScheduler js; private static JobScheduler js;
private PowersManager() { private PowersManager() {
@@ -103,6 +103,30 @@ public enum PowersManager {
} }
} }
public static ArrayList<MobPowerEntry> getPowersForMobile(Mob mobile) {
ArrayList<MobPowerEntry> mobPowers = new ArrayList<>();
ArrayList<MobPowerEntry> powerEntries;
if (mobile.agentType.equals(AIAgentType.GUARDMINION))
powerEntries = PowersManager._allMobPowers.get(mobile.guardCaptain.contractUUID);
else
powerEntries = PowersManager._allMobPowers.get(mobile.contractUUID);
if (powerEntries != null)
mobPowers.addAll(powerEntries);
if (mobile.agentType.equals(AIAgentType.GUARDMINION))
powerEntries = PowersManager._allMobPowers.get(((Mob) mobile.guardCaptain).loadID);
else
powerEntries = PowersManager._allMobPowers.get(mobile.loadID);
if (powerEntries != null)
mobPowers.addAll(powerEntries);
return mobPowers;
}
// This pre-loads all powers and effects // This pre-loads all powers and effects
public static void InitializePowers() { public static void InitializePowers() {
+35 -28
View File
@@ -22,6 +22,7 @@ import engine.net.client.msg.PerformActionMsg;
import engine.net.client.msg.PowerProjectileMsg; import engine.net.client.msg.PowerProjectileMsg;
import engine.objects.*; import engine.objects.*;
import engine.powers.ActionsBase; import engine.powers.ActionsBase;
import engine.powers.MobPowerEntry;
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;
@@ -308,7 +309,7 @@ public class MobAI {
if (mob == null) if (mob == null)
return false; return false;
if(mob.isPlayerGuard == true){ if (mob.isPlayerGuard() == true) {
int contractID; int contractID;
@@ -317,11 +318,11 @@ public class MobAI {
else else
contractID = mob.contract.getContractID(); contractID = mob.contract.getContractID();
if(Enum.MinionType.ContractToMinionMap.get(contractID).isMage() == false) if (Enum.MinionType.ContractToMinionMap.get(contractID).isMage() == false)
return false; return false;
} }
if (mob.mobPowers.isEmpty()) if (PowersManager.getPowersForMobile(mob).isEmpty())
return false; return false;
if (!mob.canSee((PlayerCharacter) mob.getCombatTarget())) { if (!mob.canSee((PlayerCharacter) mob.getCombatTarget())) {
@@ -346,8 +347,8 @@ public class MobAI {
// and casts it on the current target (or itself). Validation // and casts it on the current target (or itself). Validation
// (including empty lists) is done previously within canCast(); // (including empty lists) is done previously within canCast();
ArrayList<Integer> powerTokens; ArrayList<MobPowerEntry> powerEntries;
ArrayList<Integer> purgeTokens; ArrayList<MobPowerEntry> purgeEntries;
AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget();
if (mob.behaviourType.callsForHelp) if (mob.behaviourType.callsForHelp)
@@ -355,36 +356,36 @@ public class MobAI {
// Generate a list of tokens from the mob powers for this mobile. // Generate a list of tokens from the mob powers for this mobile.
powerTokens = new ArrayList<>(mob.mobPowers.keySet()); powerEntries = new ArrayList<>(PowersManager.getPowersForMobile(mob));
purgeTokens = new ArrayList<>(); purgeEntries = new ArrayList<>();
// If player has this effect on them currently then remove // If player has this effect on them currently then remove
// this token from our list. // this token from our list.
for (int powerToken : powerTokens) { for (MobPowerEntry mobPowerEntry : powerEntries) {
PowersBase powerBase = PowersManager.getPowerByToken(powerToken); PowersBase powerBase = PowersManager.getPowerByToken(mobPowerEntry.token);
for (ActionsBase actionBase : powerBase.getActions()) { for (ActionsBase actionBase : powerBase.getActions()) {
String stackType = actionBase.stackType; String stackType = actionBase.stackType;
if (target.getEffects() != null && target.getEffects().containsKey(stackType)) if (target.getEffects() != null && target.getEffects().containsKey(stackType))
purgeTokens.add(powerToken); purgeEntries.add(mobPowerEntry);
} }
} }
powerTokens.removeAll(purgeTokens); powerEntries.removeAll(purgeEntries);
// Sanity check // Sanity check
if (powerTokens.isEmpty()) if (powerEntries.isEmpty())
return false; return false;
// Pick random spell from our list of powers // Pick random spell from our list of powers
int powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); int powerToken = powerEntries.get(ThreadLocalRandom.current().nextInt(powerEntries.size())).token;
int powerRank = mob.mobPowers.get(powerToken); int powerRank = powerEntries.get(ThreadLocalRandom.current().nextInt(powerEntries.size())).rank;
PowersBase mobPower = PowersManager.getPowerByToken(powerToken); PowersBase mobPower = PowersManager.getPowerByToken(powerToken);
@@ -429,8 +430,8 @@ public class MobAI {
// and casts it on the current target (or itself). Validation // and casts it on the current target (or itself). Validation
// (including empty lists) is done previously within canCast(); // (including empty lists) is done previously within canCast();
ArrayList<Integer> powerTokens; ArrayList<MobPowerEntry> powerEntries;
ArrayList<Integer> purgeTokens; ArrayList<MobPowerEntry> purgeEntries;
AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget();
if (mob.behaviourType.callsForHelp) if (mob.behaviourType.callsForHelp)
@@ -438,30 +439,36 @@ public class MobAI {
// Generate a list of tokens from the mob powers for this mobile. // Generate a list of tokens from the mob powers for this mobile.
powerTokens = new ArrayList<>(mob.mobPowers.keySet()); powerEntries = PowersManager.getPowersForMobile(mob);
purgeTokens = new ArrayList<>(); purgeEntries = new ArrayList<>();
// If player has this effect on them currently then remove // If player has this effect on them currently then remove
// this token from our list. // this token from our list.
for (int powerToken : powerTokens) { powerEntries = new ArrayList<>(PowersManager.getPowersForMobile(mob));
purgeEntries = new ArrayList<>();
PowersBase powerBase = PowersManager.getPowerByToken(powerToken); // If player has this effect on them currently then remove
// this token from our list.
for (MobPowerEntry mobPowerEntry : powerEntries) {
PowersBase powerBase = PowersManager.getPowerByToken(mobPowerEntry.token);
for (ActionsBase actionBase : powerBase.getActions()) { for (ActionsBase actionBase : powerBase.getActions()) {
String stackType = actionBase.stackType; String stackType = actionBase.stackType;
if (target.getEffects() != null && target.getEffects().containsKey(stackType)) if (target.getEffects() != null && target.getEffects().containsKey(stackType))
purgeTokens.add(powerToken); purgeEntries.add(mobPowerEntry);
} }
} }
powerTokens.removeAll(purgeTokens); powerEntries.removeAll(purgeEntries);
// Sanity check // Sanity check
if (powerTokens.isEmpty()) if (powerEntries.isEmpty())
return false; return false;
int powerToken = 0; int powerToken = 0;
@@ -470,11 +477,11 @@ public class MobAI {
if (nukeRoll < 55) { if (nukeRoll < 55) {
//use direct damage spell //use direct damage spell
powerToken = powerTokens.get(powerTokens.size() - 1); powerToken = powerEntries.get(powerEntries.size() - 1).token;
} else { } else {
//use random spell //use random spell
powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); powerToken = powerEntries.get(ThreadLocalRandom.current().nextInt(powerEntries.size())).token;
} }
int powerRank = 1; int powerRank = 1;
@@ -606,7 +613,7 @@ public class MobAI {
//override for guards //override for guards
if (mob.despawned && mob.isPlayerGuard) { if (mob.despawned && mob.isPlayerGuard()) {
if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion)) { if (mob.behaviourType.equals(Enum.MobBehaviourType.GuardMinion)) {
if (mob.guardCaptain.isAlive() == false || ((Mob) mob.guardCaptain).despawned == true) { if (mob.guardCaptain.isAlive() == false || ((Mob) mob.guardCaptain).despawned == true) {
@@ -1011,14 +1018,14 @@ public class MobAI {
//dont scan self. //dont scan self.
if (mob.equals(awoMob) || (mob.agentType.equals(Enum.AIAgentType.GUARD)) == true) if (mob.equals(awoMob) || (mob.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN)) == true)
continue; continue;
Mob aggroMob = (Mob) awoMob; Mob aggroMob = (Mob) awoMob;
//don't attack other guards //don't attack other guards
if ((aggroMob.agentType.equals(Enum.AIAgentType.GUARD))) if ((aggroMob.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN)))
continue; continue;
if (aggroMob.behaviourType.equals(Enum.MobBehaviourType.Pet1)) if (aggroMob.behaviourType.equals(Enum.MobBehaviourType.Pet1))
@@ -15,9 +15,6 @@ import engine.net.client.msg.*;
import engine.objects.*; import engine.objects.*;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.HashMap;
/* /*
* @Author: * @Author:
* @Summary: Processes application protocol message which * @Summary: Processes application protocol message which
@@ -26,8 +23,6 @@ import java.util.HashMap;
public class MinionTrainingMsgHandler extends AbstractClientMsgHandler { public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
public static HashMap<Integer, ArrayList<Integer>> _minionsByCaptain = null;
public MinionTrainingMsgHandler() { public MinionTrainingMsgHandler() {
super(MinionTrainingMessage.class); super(MinionTrainingMessage.class);
} }
@@ -37,10 +32,11 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
MinionTrainingMessage minionMsg = (MinionTrainingMessage) baseMsg; MinionTrainingMessage minionMsg = (MinionTrainingMessage) baseMsg;
PlayerCharacter player = SessionManager.getPlayerCharacter(origin); PlayerCharacter playerCharacter = SessionManager.getPlayerCharacter(origin);
if (player == null) if (playerCharacter == null)
return true; return true;
if (minionMsg.getNpcType() == Enum.GameObjectType.NPC.ordinal()) { if (minionMsg.getNpcType() == Enum.GameObjectType.NPC.ordinal()) {
NPC npc = NPC.getFromCache(minionMsg.getNpcID()); NPC npc = NPC.getFromCache(minionMsg.getNpcID());
@@ -48,14 +44,15 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
if (npc == null) if (npc == null)
return true; return true;
Building b = BuildingManager.getBuildingFromCache(minionMsg.getBuildingID()); Building building = BuildingManager.getBuildingFromCache(minionMsg.getBuildingID());
if (b == null) if (building == null)
return true; return true;
//clear minion //clear minion
if (npc.minionLock.writeLock().tryLock()) { if (npc.minionLock.writeLock().tryLock()) {
try { try {
if (minionMsg.getType() == 2) { if (minionMsg.getType() == 2) {
@@ -86,23 +83,21 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
} }
} }
// we Found the move to remove, lets break the for loop so it doesnt look for more. ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(playerCharacter, building);
ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(player, b);
mca1.actionType = 3; mca1.actionType = 3;
mca1.setTargetType(b.getObjectType().ordinal()); mca1.setTargetType(building.getObjectType().ordinal());
mca1.setTargetID(b.getObjectUUID()); mca1.setTargetID(building.getObjectUUID());
mca1.setTargetType3(npc.getObjectType().ordinal()); mca1.setTargetType3(npc.getObjectType().ordinal());
mca1.setTargetID3(npc.getObjectUUID()); mca1.setTargetID3(npc.getObjectUUID());
mca1.setAssetName1(b.getName()); mca1.setAssetName1(building.getName());
mca1.setUnknown54(1); mca1.setUnknown54(1);
Dispatch dispatch = Dispatch.borrow(player, mca1); Dispatch dispatch = Dispatch.borrow(playerCharacter, mca1);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
ManageNPCMsg mnm = new ManageNPCMsg(npc); ManageNPCMsg mnm = new ManageNPCMsg(npc);
dispatch = Dispatch.borrow(player, mnm); dispatch = Dispatch.borrow(playerCharacter, mnm);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
//Add Minion //Add Minion
@@ -156,7 +151,7 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
ManageNPCMsg mnm = new ManageNPCMsg(npc); ManageNPCMsg mnm = new ManageNPCMsg(npc);
mnm.setMessageType(1); mnm.setMessageType(1);
Dispatch dispatch = Dispatch.borrow(player, mnm); Dispatch dispatch = Dispatch.borrow(playerCharacter, mnm);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
} finally { } finally {
@@ -199,19 +194,21 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
DbManager.removeFromCache(toRemove); DbManager.removeFromCache(toRemove);
if (toRemove.agentType.equals(Enum.AIAgentType.SIEGEENGINE)) {
PlayerCharacter petOwner = (PlayerCharacter) toRemove.guardCaptain; PlayerCharacter trebOwner = (PlayerCharacter) toRemove.guardCaptain;
if (petOwner != null) { if (trebOwner != null) {
petOwner.setPet(null); trebOwner.setPet(null);
toRemove.guardCaptain = null; toRemove.guardCaptain = null;
PetMsg petMsg = new PetMsg(5, null); PetMsg petMsg = new PetMsg(5, null);
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg); Dispatch dispatch = Dispatch.borrow(trebOwner, petMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
}
} }
ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(player, building); ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(playerCharacter, building);
mca1.actionType = 3; mca1.actionType = 3;
mca1.setTargetType(building.getObjectType().ordinal()); mca1.setTargetType(building.getObjectType().ordinal());
mca1.setTargetID(building.getObjectUUID()); mca1.setTargetID(building.getObjectUUID());
@@ -221,11 +218,11 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
mca1.setAssetName1(building.getName()); mca1.setAssetName1(building.getName());
mca1.setUnknown54(1); mca1.setUnknown54(1);
Dispatch dispatch = Dispatch.borrow(player, mca1); Dispatch dispatch = Dispatch.borrow(playerCharacter, mca1);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
ManageNPCMsg mnm = new ManageNPCMsg(npc); ManageNPCMsg mnm = new ManageNPCMsg(npc);
dispatch = Dispatch.borrow(player, mnm); dispatch = Dispatch.borrow(playerCharacter, mnm);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
//Add Minion //Add Minion
@@ -287,7 +284,7 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
ManageNPCMsg mnm = new ManageNPCMsg(npc); ManageNPCMsg mnm = new ManageNPCMsg(npc);
mnm.setMessageType(1); mnm.setMessageType(1);
Dispatch dispatch = Dispatch.borrow(player, mnm); Dispatch dispatch = Dispatch.borrow(playerCharacter, mnm);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
} catch (Exception e) { } catch (Exception e) {
@@ -32,7 +32,7 @@ public abstract class AbstractIntelligenceAgent extends AbstractCharacter {
protected Vector3fImmutable lastBindLoc; protected Vector3fImmutable lastBindLoc;
public boolean assist = false; public boolean assist = false;
public Enum.AIAgentType agentType = Enum.AIAgentType.MOBILE; public Enum.AIAgentType agentType = Enum.AIAgentType.MOBILE;
public boolean isPlayerGuard = false;
public AbstractCharacter guardCaptain; public AbstractCharacter guardCaptain;
public EnumBitSet<Enum.MonsterType> notEnemy = EnumBitSet.noneOf(Enum.MonsterType.class); public EnumBitSet<Enum.MonsterType> notEnemy = EnumBitSet.noneOf(Enum.MonsterType.class);
public EnumBitSet<Enum.MonsterType> enemy = EnumBitSet.noneOf(Enum.MonsterType.class); public EnumBitSet<Enum.MonsterType> enemy = EnumBitSet.noneOf(Enum.MonsterType.class);
+64 -96
View File
@@ -25,15 +25,14 @@ import engine.net.Dispatch;
import engine.net.DispatchMessage; import engine.net.DispatchMessage;
import engine.net.client.msg.PetMsg; import engine.net.client.msg.PetMsg;
import engine.net.client.msg.PlaceAssetMsg; import engine.net.client.msg.PlaceAssetMsg;
import engine.powers.MobPowerEntry;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -51,7 +50,6 @@ public class Mob extends AbstractIntelligenceAgent {
public ReentrantReadWriteLock minionLock = new ReentrantReadWriteLock(); public ReentrantReadWriteLock minionLock = new ReentrantReadWriteLock();
public boolean despawned = false; public boolean despawned = false;
public Vector3fImmutable destination = Vector3fImmutable.ZERO; public Vector3fImmutable destination = Vector3fImmutable.ZERO;
public LinkedHashMap<Integer, Integer> mobPowers = new LinkedHashMap<>();
public MobBase mobBase; public MobBase mobBase;
public int spawnTime; public int spawnTime;
public Zone parentZone; public Zone parentZone;
@@ -65,12 +63,10 @@ public class Mob extends AbstractIntelligenceAgent {
public float spawnRadius; public float spawnRadius;
//used by static mobs //used by static mobs
public int parentZoneUUID; public int parentZoneUUID;
protected int dbID; //the database ID
private int currentID;
//TODO implement feared object system //TODO implement feared object system
public AbstractWorldObject fearedObject = null; public AbstractWorldObject fearedObject = null;
protected int dbID; //the database ID
private int currentID;
private long lastAttackTime = 0; private long lastAttackTime = 0;
private int lastMobPowerToken = 0; private int lastMobPowerToken = 0;
private HashMap<Integer, MobEquipment> equip = null; private HashMap<Integer, MobEquipment> equip = null;
@@ -105,6 +101,7 @@ public class Mob extends AbstractIntelligenceAgent {
this.dbID = rs.getInt(1); this.dbID = rs.getInt(1);
this.loadID = rs.getInt("mob_mobbaseID"); this.loadID = rs.getInt("mob_mobbaseID");
this.gridObjectType = GridObjectType.DYNAMIC; this.gridObjectType = GridObjectType.DYNAMIC;
this.agentType = AIAgentType.MOBILE;
this.spawnRadius = rs.getFloat("mob_spawnRadius"); this.spawnRadius = rs.getFloat("mob_spawnRadius");
this.spawnTime = rs.getInt("mob_spawnTime"); this.spawnTime = rs.getInt("mob_spawnTime");
@@ -153,7 +150,6 @@ public class Mob extends AbstractIntelligenceAgent {
this.currentID = this.dbID; this.currentID = this.dbID;
this.agentType = AIAgentType.MOBILE;
} catch (Exception e) { } catch (Exception e) {
Logger.error(e + " " + this.dbID); Logger.error(e + " " + this.dbID);
} }
@@ -183,7 +179,7 @@ public class Mob extends AbstractIntelligenceAgent {
} else if (tid == 100962 || tid == 100965) { //Spydraxxx the Mighty, Denigo Tantric } else if (tid == 100962 || tid == 100965) { //Spydraxxx the Mighty, Denigo Tantric
writer.putInt(2); writer.putInt(2);
serializeRune(mob, writer, 5, GameObjectType.NPCClassRuneTwo.ordinal(), 252621); //guard rune serializeRune(mob, writer, 5, GameObjectType.NPCClassRuneTwo.ordinal(), 252621); //guard rune
} else if (mob.contract != null || mob.isPlayerGuard) { } else if (mob.contract != null || mob.isPlayerGuard()) {
writer.putInt(3); writer.putInt(3);
serializeRune(mob, writer, 3, GameObjectType.NPCClassRuneTwo.ordinal(), MobBase.GetClassType(mob.getMobBaseID())); //warrior class serializeRune(mob, writer, 3, GameObjectType.NPCClassRuneTwo.ordinal(), MobBase.GetClassType(mob.getMobBaseID())); //warrior class
serializeRune(mob, writer, 5, GameObjectType.NPCClassRuneThree.ordinal(), 252621); //guard rune serializeRune(mob, writer, 5, GameObjectType.NPCClassRuneThree.ordinal(), 252621); //guard rune
@@ -316,13 +312,13 @@ public class Mob extends AbstractIntelligenceAgent {
writer.put((byte) 1); writer.put((byte) 1);
if ((PlayerCharacter) mob.guardCaptain != null) { if (mob.guardCaptain != null) {
writer.putInt(((PlayerCharacter) mob.guardCaptain).getObjectType().ordinal()); writer.putInt(mob.guardCaptain.getObjectType().ordinal());
writer.putInt(((PlayerCharacter) mob.guardCaptain).getObjectUUID()); writer.putInt(mob.guardCaptain.getObjectUUID());
} else { } else {
writer.putInt(0); //ownerType writer.putInt(0); //ownerType
writer.putInt(0); //ownerID writer.putInt(0); //ownerID
@@ -340,7 +336,7 @@ public class Mob extends AbstractIntelligenceAgent {
writer.putInt(0); writer.putInt(0);
writer.putInt(0); writer.putInt(0);
if (!mob.isAlive() && !mob.isPet() && !mob.isNecroPet() && !mob.behaviourType.equals(MobBehaviourType.SiegeEngine) && !mob.isPlayerGuard) { if (!mob.isAlive() && !mob.isPet() && !mob.isNecroPet() && !mob.behaviourType.equals(MobBehaviourType.SiegeEngine) && !mob.isPlayerGuard()) {
writer.putInt(0); writer.putInt(0);
writer.putInt(0); writer.putInt(0);
} }
@@ -405,6 +401,8 @@ public class Mob extends AbstractIntelligenceAgent {
Mob mobile = new Mob(); Mob mobile = new Mob();
mobile.dbID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET; mobile.dbID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET;
mobile.agentType = AIAgentType.MOBILE;
mobile.behaviourType = MobBehaviourType.None;
mobile.loadID = loadID; mobile.loadID = loadID;
mobile.level = (short) level; mobile.level = (short) level;
@@ -428,18 +426,7 @@ public class Mob extends AbstractIntelligenceAgent {
else else
mobile.contractUUID = contract.getContractID(); mobile.contractUUID = contract.getContractID();
Mob mob; return mobile;
mobile.agentType = AIAgentType.GUARD;
try {
mob = DbManager.MobQueries.PERSIST(mobile);
} catch (Exception e) {
Logger.error("SQLException:" + e.getMessage());
mob = null;
}
return mob;
} }
public static synchronized Mob createGuardMinion(Mob guardCaptain, short level, String minionName) { public static synchronized Mob createGuardMinion(Mob guardCaptain, short level, String minionName) {
@@ -463,8 +450,7 @@ public class Mob extends AbstractIntelligenceAgent {
minionMobile.guardCaptain = guardCaptain; minionMobile.guardCaptain = guardCaptain;
minionMobile.spawnTime = (int) (-2.500 * guardCaptain.building.getRank() + 22.5) * 60; minionMobile.spawnTime = (int) (-2.500 * guardCaptain.building.getRank() + 22.5) * 60;
minionMobile.behaviourType = Enum.MobBehaviourType.GuardMinion; minionMobile.behaviourType = Enum.MobBehaviourType.GuardMinion;
minionMobile.agentType = AIAgentType.GUARD; minionMobile.agentType = AIAgentType.GUARDMINION;
minionMobile.isPlayerGuard = true;
minionMobile.guardedCity = guardCaptain.guardedCity; minionMobile.guardedCity = guardCaptain.guardedCity;
minionMobile.patrolPoints = guardCaptain.building.patrolPoints; minionMobile.patrolPoints = guardCaptain.building.patrolPoints;
@@ -566,6 +552,7 @@ public class Mob extends AbstractIntelligenceAgent {
return petMinion; return petMinion;
} }
public static Mob getMob(int id) { public static Mob getMob(int id) {
if (id == 0) if (id == 0)
@@ -708,7 +695,7 @@ public class Mob extends AbstractIntelligenceAgent {
public Vector3fImmutable getBindLoc() { public Vector3fImmutable getBindLoc() {
if (this.isPet() && !this.behaviourType.equals(MobBehaviourType.SiegeEngine)) if (this.isPet() && !this.behaviourType.equals(MobBehaviourType.SiegeEngine))
return (PlayerCharacter) this.guardCaptain != null ? ((PlayerCharacter) this.guardCaptain).getLoc() : this.getLoc(); return this.guardCaptain != null ? this.guardCaptain.getLoc() : this.getLoc();
else else
return this.bindLoc; return this.bindLoc;
} }
@@ -757,7 +744,7 @@ public class Mob extends AbstractIntelligenceAgent {
// get rune and effect bonuses // get rune and effect bonuses
bonus *= (1 + this.bonuses.getFloatPercentAll(ModType.Speed, SourceType.None)); bonus *= (1 + this.bonuses.getFloatPercentAll(ModType.Speed, SourceType.None));
if (this.isPlayerGuard) if (this.isPlayerGuard())
switch (this.mobBase.getLoadID()) { switch (this.mobBase.getLoadID()) {
case 2111: case 2111:
if (this.isWalk()) if (this.isWalk())
@@ -825,7 +812,7 @@ public class Mob extends AbstractIntelligenceAgent {
Group g = GroupManager.getGroup((PlayerCharacter) attacker); Group g = GroupManager.getGroup((PlayerCharacter) attacker);
// Give XP, now handled inside the Experience Object // Give XP, now handled inside the Experience Object
if (!this.isPet() && !this.isNecroPet() && !(this.agentType.equals(AIAgentType.PET)) && !this.isPlayerGuard) if (!this.isPet() && !this.isNecroPet() && !(this.agentType.equals(AIAgentType.PET)) && !this.isPlayerGuard())
Experience.doExperience((PlayerCharacter) attacker, this, g); Experience.doExperience((PlayerCharacter) attacker, this, g);
} else if (attacker.getObjectType().equals(GameObjectType.Mob)) { } else if (attacker.getObjectType().equals(GameObjectType.Mob)) {
Mob mobAttacker = (Mob) attacker; Mob mobAttacker = (Mob) attacker;
@@ -836,7 +823,7 @@ public class Mob extends AbstractIntelligenceAgent {
PlayerCharacter owner = (PlayerCharacter) mobAttacker.guardCaptain; PlayerCharacter owner = (PlayerCharacter) mobAttacker.guardCaptain;
if (owner != null) if (owner != null)
if (!this.isPet() && !this.isNecroPet() && !(this.agentType.equals(AIAgentType.PET)) && !this.isPlayerGuard) { if (!this.isPet() && !this.isNecroPet() && !(this.agentType.equals(AIAgentType.PET)) && !this.isPlayerGuard()) {
Group g = GroupManager.getGroup(owner); Group g = GroupManager.getGroup(owner);
// Give XP, now handled inside the Experience Object // Give XP, now handled inside the Experience Object
@@ -950,7 +937,7 @@ public class Mob extends AbstractIntelligenceAgent {
playerAgroMap.clear(); playerAgroMap.clear();
if (!this.isPlayerGuard && this.equip != null) if (!this.isPlayerGuard() && this.equip != null)
LootManager.GenerateEquipmentDrop(this); LootManager.GenerateEquipmentDrop(this);
} }
@@ -997,8 +984,7 @@ public class Mob extends AbstractIntelligenceAgent {
else if (this.building != null) else if (this.building != null)
this.region = BuildingManager.GetRegion(this.building, bindLoc.x, bindLoc.y, bindLoc.z); this.region = BuildingManager.GetRegion(this.building, bindLoc.x, bindLoc.y, bindLoc.z);
if (!this.behaviourType.equals(MobBehaviourType.SiegeEngine) && !this.isPlayerGuard && contract == null) this.loadInventory();
loadInventory();
this.updateLocation(); this.updateLocation();
} }
@@ -1036,7 +1022,9 @@ public class Mob extends AbstractIntelligenceAgent {
this.charItemManager.clearInventory(); this.charItemManager.clearInventory();
this.charItemManager.clearEquip(); this.charItemManager.clearEquip();
if (isPlayerGuard) // Only generate loot for mobiles
if (!this.agentType.equals(AIAgentType.MOBILE))
return; return;
LootManager.GenerateMobLoot(this); LootManager.GenerateMobLoot(this);
@@ -1529,49 +1517,33 @@ public class Mob extends AbstractIntelligenceAgent {
@Override @Override
public void runAfterLoad() { public void runAfterLoad() {
this.charItemManager = new CharacterItemManager(this); this.setObjectTypeMask(MBServerStatics.MASK_MOB | this.getTypeMasks());
if (ConfigManager.serverType.equals(ServerType.LOGINSERVER)) if (ConfigManager.serverType.equals(ServerType.LOGINSERVER))
return; return;
this.mobBase = MobBase.getMobBase(loadID); this.charItemManager = new CharacterItemManager(this);
this.setObjectTypeMask(MBServerStatics.MASK_MOB | this.getTypeMasks()); this.mobBase = MobBase.getMobBase(loadID);
this.building = BuildingManager.getBuilding(this.buildingUUID); this.building = BuildingManager.getBuilding(this.buildingUUID);
if (this.contractUUID == 0) // Configure AI related values
this.contract = null;
else
this.contract = DbManager.ContractQueries.GET_CONTRACT(this.contractUUID);
// Setup mobile AI and equipset for contract switch (this.behaviourType) {
case GuardCaptain:
if (this.contract != null) { this.agentType = AIAgentType.GUARDCAPTAIN;
this.spawnTime = 600;
this.equipmentSetID = this.contract.getEquipmentSet();
// Load AI for guard captains
if (NPC.ISGuardCaptain(contract.getContractID()) || this.contract.getContractID() == 910) { // Guard Dog
this.behaviourType = MobBehaviourType.GuardCaptain;
this.spawnTime = 60 * 15;
this.isPlayerGuard = true;
this.guardedCity = ZoneManager.getCityAtLocation(this.building.getLoc()); this.guardedCity = ZoneManager.getCityAtLocation(this.building.getLoc());
} break;
case GuardWallArcher:
// Load AI for wall archers this.agentType = AIAgentType.GUARDWALLARCHER;
if (NPC.ISWallArcher(this.contract)) {
this.gridObjectType = GridObjectType.DYNAMIC;
this.behaviourType = MobBehaviourType.GuardWallArcher;
this.isPlayerGuard = true;
this.spawnTime = 450; this.spawnTime = 450;
this.guardedCity = ZoneManager.getCityAtLocation(this.building.getLoc()); this.guardedCity = ZoneManager.getCityAtLocation(this.building.getLoc());
} break;
} }
// Default to the mobbase for AI if nothing is hte mob field to override. // Default to the mobbase for AI if nothing is in mob field to override.
if (this.behaviourType == null || this.behaviourType.equals(MobBehaviourType.None)) if (this.behaviourType == null || this.behaviourType.equals(MobBehaviourType.None))
this.behaviourType = this.getMobBase().fsm; this.behaviourType = this.getMobBase().fsm;
@@ -1579,6 +1551,18 @@ public class Mob extends AbstractIntelligenceAgent {
if (this.behaviourType == null) if (this.behaviourType == null)
this.behaviourType = MobBehaviourType.None; this.behaviourType = MobBehaviourType.None;
if (this.contractUUID == 0)
this.contract = null;
else
this.contract = DbManager.ContractQueries.GET_CONTRACT(this.contractUUID);
// Setup equipset for contract
if (this.contract != null)
this.equipmentSetID = this.contract.getEquipmentSet();
// Mobiles default to the building guild.
if (this.building != null) if (this.building != null)
this.guild = this.building.getGuild(); this.guild = this.building.getGuild();
else else
@@ -1604,7 +1588,7 @@ public class Mob extends AbstractIntelligenceAgent {
// Don't override level for guard minions or pets // Don't override level for guard minions or pets
if (this.contract == null) if (this.contract == null)
if (!this.agentType.equals(AIAgentType.GUARD) && !this.agentType.equals(AIAgentType.PET)) if (!this.agentType.equals(AIAgentType.GUARDMINION) && !this.agentType.equals(AIAgentType.PET))
this.level = (short) this.mobBase.getLevel(); this.level = (short) this.mobBase.getLevel();
//set bonuses //set bonuses
@@ -1614,8 +1598,8 @@ public class Mob extends AbstractIntelligenceAgent {
//TODO set these correctly later //TODO set these correctly later
this.rangeHandOne = this.mobBase.getAttackRange(); this.rangeHandOne = this.mobBase.getAttackRange();
this.rangeHandTwo = -1; this.rangeHandTwo = -1;
this.minDamageHandOne = (int)this.mobBase.getMinDmg(); this.minDamageHandOne = (int) this.mobBase.getMinDmg();
this.maxDamageHandOne = (int)this.mobBase.getMaxDmg(); this.maxDamageHandOne = (int) this.mobBase.getMaxDmg();
this.minDamageHandTwo = 0; this.minDamageHandTwo = 0;
this.maxDamageHandTwo = 0; this.maxDamageHandTwo = 0;
this.atrHandOne = this.mobBase.getAtr(); this.atrHandOne = this.mobBase.getAtr();
@@ -1664,18 +1648,6 @@ public class Mob extends AbstractIntelligenceAgent {
else else
this.equip = new HashMap<>(); this.equip = new HashMap<>();
// Powers from mobbase
if (PowersManager.AllMobPowers.containsKey(this.getMobBaseID()))
for (MobPowerEntry mobPowerEntry : PowersManager.AllMobPowers.get(this.getMobBaseID()))
mobPowers.put(mobPowerEntry.token, mobPowerEntry.rank);
// Powers from contract
if (this.contract != null && PowersManager.AllMobPowers.containsKey(this.contract.getContractID()))
for (MobPowerEntry mobPowerEntry : PowersManager.AllMobPowers.get(this.contract.getContractID()))
mobPowers.put(mobPowerEntry.token, mobPowerEntry.rank);
if (this.equip == null) { if (this.equip == null) {
Logger.error("Null equipset returned for uuid " + currentID); Logger.error("Null equipset returned for uuid " + currentID);
this.equip = new HashMap<>(0); this.equip = new HashMap<>(0);
@@ -1692,28 +1664,23 @@ public class Mob extends AbstractIntelligenceAgent {
this.enemy.addAll(this.getMobBase().enemy); this.enemy.addAll(this.getMobBase().enemy);
} }
try { NPCManager.applyRuneSetEffects(this);
NPCManager.applyRuneSetEffects(this); recalculateStats();
recalculateStats(); this.setHealth(this.healthMax);
this.setHealth(this.healthMax);
// Set bounds for this mobile // Set bounds for this mobile
Bounds mobBounds = Bounds.borrow(); Bounds mobBounds = Bounds.borrow();
mobBounds.setBounds(this.getLoc()); mobBounds.setBounds(this.getLoc());
this.setBounds(mobBounds); this.setBounds(mobBounds);
//assign 5 random patrol points for regular mobs //assign 5 random patrol points for regular mobs
if (this.agentType.equals(AIAgentType.MOBILE)) { if (this.agentType.equals(AIAgentType.MOBILE))
NPCManager.AssignPatrolPoints(this);
NPCManager.AssignPatrolPoints(this); this.deathTime = 0;
}
this.deathTime = 0;
} catch (Exception e) {
Logger.error(e.getMessage());
}
} }
@Override @Override
@@ -1822,7 +1789,8 @@ public class Mob extends AbstractIntelligenceAgent {
} }
public boolean isPlayerGuard() { public boolean isPlayerGuard() {
return isPlayerGuard;
return EnumSet.of(AIAgentType.GUARDCAPTAIN, AIAgentType.GUARDMINION, AIAgentType.GUARDWALLARCHER).contains(this.agentType);
} }
public int getLastMobPowerToken() { public int getLastMobPowerToken() {
+1 -1
View File
@@ -352,7 +352,7 @@ public class WorldServer {
DbManager.MobBaseQueries.GET_ALL_MOBBASES(); DbManager.MobBaseQueries.GET_ALL_MOBBASES();
Logger.info("Loading Mob Powers"); Logger.info("Loading Mob Powers");
PowersManager.AllMobPowers = dbPowerHandler.LOAD_MOB_POWERS(); PowersManager._allMobPowers = dbPowerHandler.LOAD_MOB_POWERS();
Logger.info("Loading item enchants"); Logger.info("Loading item enchants");
DbManager.LootQueries.LOAD_ENCHANT_VALUES(); DbManager.LootQueries.LOAD_ENCHANT_VALUES();