Owner death, logout or invisibility dismissed a commanded siege engine by clearing its target and marking it dead. Released engines now revert to MOBILE in place, stay alive and keep their current target so any nation member can re-command them with a Rod of Command. Commanding an engine no longer clears the target of the old or new engine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
211 lines
7.3 KiB
Java
211 lines
7.3 KiB
Java
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
|
// Magicbane Emulator Project © 2013 - 2026
|
|
// https://www.magicbane.com
|
|
|
|
|
|
package engine.objects;
|
|
|
|
import engine.InterestManagement.WorldGrid;
|
|
import engine.gameManager.DispatchManager;
|
|
import engine.gameManager.ZoneManager;
|
|
import engine.math.Vector3fImmutable;
|
|
import engine.mbEnums;
|
|
import engine.mbEnums.GameObjectType;
|
|
import engine.mbEnums.ModType;
|
|
import engine.mbEnums.SourceType;
|
|
import engine.mobileAI.Threads.MobAIThread;
|
|
import engine.net.Dispatch;
|
|
import engine.net.client.msg.PetMsg;
|
|
import engine.server.MBServerStatics;
|
|
|
|
import java.sql.ResultSet;
|
|
import java.sql.SQLException;
|
|
import java.util.ArrayList;
|
|
import java.util.EnumSet;
|
|
|
|
|
|
public abstract class AbstractIntelligenceAgent extends AbstractCharacter {
|
|
protected Vector3fImmutable lastBindLoc;
|
|
public boolean assist = false;
|
|
public mbEnums.AIAgentType agentType = mbEnums.AIAgentType.MOBILE;
|
|
|
|
public AbstractCharacter guardCaptain;
|
|
public EnumSet<mbEnums.MonsterType> notEnemy = EnumSet.noneOf(mbEnums.MonsterType.class);
|
|
public EnumSet<mbEnums.MonsterType> enemy = EnumSet.noneOf(mbEnums.MonsterType.class);
|
|
;
|
|
public mbEnums.MobBehaviourType behaviourType;
|
|
public ArrayList<Vector3fImmutable> patrolPoints;
|
|
public int lastPatrolPointIndex = 0;
|
|
public long stopPatrolTime = 0;
|
|
public City guardedCity;
|
|
|
|
public AbstractIntelligenceAgent() {
|
|
super();
|
|
}
|
|
|
|
public AbstractIntelligenceAgent(ResultSet rs) throws SQLException {
|
|
super(rs);
|
|
}
|
|
|
|
public AbstractIntelligenceAgent(String firstName,
|
|
String lastName, short statStrCurrent, short statDexCurrent,
|
|
short statConCurrent, short statIntCurrent, short statSpiCurrent,
|
|
short level, int exp, boolean sit, boolean walk, boolean combat,
|
|
Vector3fImmutable bindLoc, Vector3fImmutable currentLoc, Vector3fImmutable faceDir,
|
|
short healthCurrent, short manaCurrent, short stamCurrent,
|
|
Guild guild, byte runningTrains) {
|
|
super(firstName, lastName, statStrCurrent, statDexCurrent, statConCurrent,
|
|
statIntCurrent, statSpiCurrent, level, exp, bindLoc,
|
|
faceDir, guild,
|
|
runningTrains);
|
|
}
|
|
|
|
public AbstractIntelligenceAgent(String firstName,
|
|
String lastName, short statStrCurrent, short statDexCurrent,
|
|
short statConCurrent, short statIntCurrent, short statSpiCurrent,
|
|
short level, int exp, boolean sit, boolean walk, boolean combat,
|
|
Vector3fImmutable bindLoc, Vector3fImmutable currentLoc, Vector3fImmutable faceDir,
|
|
short healthCurrent, short manaCurrent, short stamCurrent,
|
|
Guild guild, byte runningTrains, int newUUID) {
|
|
super(firstName, lastName, statStrCurrent, statDexCurrent, statConCurrent,
|
|
statIntCurrent, statSpiCurrent, level, exp, bindLoc,
|
|
currentLoc, faceDir, guild,
|
|
runningTrains, newUUID);
|
|
}
|
|
|
|
@Override
|
|
public void setObjectTypeMask(int mask) {
|
|
mask |= MBServerStatics.MASK_IAGENT;
|
|
super.setObjectTypeMask(mask);
|
|
}
|
|
|
|
/* AI Job Management */
|
|
|
|
public MobBase getMobBase() {
|
|
|
|
if (this.getObjectType().equals(GameObjectType.Mob))
|
|
return this.getMobBase();
|
|
|
|
return null;
|
|
}
|
|
|
|
public void setPet(PlayerCharacter owner, boolean summoned) {
|
|
|
|
if (summoned)
|
|
this.agentType = mbEnums.AIAgentType.PET; //summoned
|
|
else
|
|
this.agentType = mbEnums.AIAgentType.CHARMED;
|
|
|
|
if (this.getObjectType().equals(GameObjectType.Mob)) {
|
|
|
|
((Mob) this).guardCaptain = owner;
|
|
}
|
|
}
|
|
|
|
|
|
public boolean isPet() {
|
|
|
|
return (this.agentType.equals(mbEnums.AIAgentType.PET) ||
|
|
this.agentType.equals(mbEnums.AIAgentType.CHARMED));
|
|
}
|
|
|
|
public void toggleAssist() {
|
|
this.assist = !this.assist;
|
|
}
|
|
|
|
public int getDBID() {
|
|
|
|
if (this.getObjectType().equals(GameObjectType.Mob))
|
|
return this.getDBID();
|
|
|
|
return 0;
|
|
}
|
|
|
|
public boolean getSafeZone() {
|
|
|
|
ArrayList<Zone> allIn = ZoneManager.getAllZonesIn(this.getLoc());
|
|
|
|
for (Zone zone : allIn)
|
|
if (zone.peace_zone == (byte) 1)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
public float getAggroRange() {
|
|
|
|
float ret = MobAIThread.AI_BASE_AGGRO_RANGE;
|
|
|
|
if (this.bonuses != null)
|
|
ret *= (1 + this.bonuses.getFloatPercentAll(ModType.ScanRange, SourceType.None));
|
|
|
|
return ret;
|
|
}
|
|
|
|
public void dismiss() {
|
|
|
|
boolean isSiegeEngine;
|
|
|
|
isSiegeEngine = this.getObjectType() == GameObjectType.Mob && ((Mob) this).isSiege();
|
|
|
|
if (this.isPet()) {
|
|
|
|
if (isSiegeEngine) {
|
|
|
|
// Released siege engines stay in place, alive, and keep firing at
|
|
// their current target until a Rod of Command takes them again.
|
|
|
|
this.agentType = mbEnums.AIAgentType.MOBILE;
|
|
|
|
} else if ((this.agentType.equals(mbEnums.AIAgentType.PET))) { //delete summoned pet
|
|
|
|
WorldGrid.RemoveWorldObject(this);
|
|
|
|
if (this.getObjectType() == GameObjectType.Mob) {
|
|
if (((Mob) this).getParentZone() != null) {
|
|
((Mob) this).getParentZone().zoneMobSet.remove(this);
|
|
}
|
|
}
|
|
|
|
} else { //revert charmed pet
|
|
this.agentType = mbEnums.AIAgentType.MOBILE;
|
|
this.setCombatTarget(null);
|
|
}
|
|
|
|
// clear owner and set not alive
|
|
|
|
if (!isSiegeEngine)
|
|
this.isAlive.set(false);
|
|
|
|
PlayerCharacter owner = (PlayerCharacter) this.guardCaptain;
|
|
|
|
//close pet window
|
|
|
|
if (owner != null) {
|
|
|
|
Mob pet = owner.getPet();
|
|
|
|
PetMsg petMsg = new PetMsg(5, null);
|
|
Dispatch dispatch = Dispatch.borrow(owner, petMsg);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY);
|
|
|
|
if (pet != null && pet.getObjectUUID() == this.getObjectUUID())
|
|
owner.setPet(null);
|
|
|
|
if (this.getObjectType().equals(GameObjectType.Mob))
|
|
this.guardCaptain = null;
|
|
}
|
|
|
|
if (isSiegeEngine && this.isAlive())
|
|
WorldGrid.updateObject(this);
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|