forked from MagicBane/Server
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3012 lines
76 KiB
3012 lines
76 KiB
3 years ago
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||
|
// Magicbane Emulator Project © 2013 - 2022
|
||
|
// www.magicbane.com
|
||
|
|
||
|
|
||
|
package engine.objects;
|
||
|
|
||
|
import engine.Enum;
|
||
|
import engine.Enum.*;
|
||
|
import engine.InterestManagement.HeightMap;
|
||
|
import engine.InterestManagement.WorldGrid;
|
||
|
import engine.ai.MobileFSM;
|
||
|
import engine.ai.MobileFSM.STATE;
|
||
|
import engine.exception.SerializationException;
|
||
|
import engine.gameManager.*;
|
||
|
import engine.job.JobContainer;
|
||
|
import engine.job.JobScheduler;
|
||
|
import engine.jobs.DeferredPowerJob;
|
||
|
import engine.jobs.UpgradeNPCJob;
|
||
|
import engine.math.Bounds;
|
||
|
import engine.math.Vector3fImmutable;
|
||
|
import engine.net.ByteBufferWriter;
|
||
|
import engine.net.Dispatch;
|
||
|
import engine.net.DispatchMessage;
|
||
|
import engine.net.client.ClientConnection;
|
||
|
import engine.net.client.msg.ErrorPopupMsg;
|
||
|
import engine.net.client.msg.ManageCityAssetsMsg;
|
||
|
import engine.net.client.msg.PetMsg;
|
||
|
import engine.net.client.msg.PlaceAssetMsg;
|
||
|
import engine.powers.EffectsBase;
|
||
|
import engine.server.MBServerStatics;
|
||
|
import engine.server.world.WorldServer;
|
||
|
import org.joda.time.DateTime;
|
||
|
import org.pmw.tinylog.Logger;
|
||
|
|
||
|
import java.sql.ResultSet;
|
||
|
import java.sql.SQLException;
|
||
|
import java.util.ArrayList;
|
||
|
import java.util.HashMap;
|
||
|
import java.util.HashSet;
|
||
|
import java.util.concurrent.ConcurrentHashMap;
|
||
|
import java.util.concurrent.ThreadLocalRandom;
|
||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||
|
|
||
|
import static engine.net.client.msg.ErrorPopupMsg.sendErrorPopup;
|
||
|
|
||
|
public class Mob extends AbstractIntelligenceAgent {
|
||
|
|
||
|
protected int dbID; //the database ID
|
||
|
protected int loadID;
|
||
|
protected boolean isMob;
|
||
|
protected MobBase mobBase;
|
||
|
|
||
|
//mob specific
|
||
|
|
||
|
protected float spawnRadius;
|
||
|
protected int spawnTime;
|
||
|
|
||
|
//used by static mobs
|
||
|
protected int parentZoneID;
|
||
|
protected Zone parentZone;
|
||
|
protected float statLat;
|
||
|
protected float statLon;
|
||
|
protected float statAlt;
|
||
|
protected Building building;
|
||
|
protected Contract contract;
|
||
|
private static ReentrantReadWriteLock createLock = new ReentrantReadWriteLock();
|
||
|
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||
|
|
||
|
// Variables NOT to be stored in db
|
||
|
private static int staticID = 0;
|
||
|
private int currentID;
|
||
|
private int ownerUID = 0; //only used by pets
|
||
|
private boolean hasLoot = false;
|
||
|
private static ConcurrentHashMap<Integer, Mob> mobMapByDBID = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
|
||
|
private AbstractWorldObject fearedObject = null;
|
||
|
private int buildingID;
|
||
|
private boolean isSiege = false;
|
||
|
private boolean isPlayerGuard = false;
|
||
|
private long timeToSpawnSiege;
|
||
|
private AbstractCharacter npcOwner;
|
||
|
private Vector3fImmutable inBuildingLoc = null;
|
||
|
private final ConcurrentHashMap<Integer, Boolean> playerAgroMap = new ConcurrentHashMap<>();
|
||
|
private boolean noAggro = false;
|
||
|
private STATE state = STATE.Disabled;
|
||
|
private int aggroTargetID = 0;
|
||
|
private boolean walkingHome = true;
|
||
|
private long lastAttackTime = 0;
|
||
|
private long deathTime = 0;
|
||
|
private ConcurrentHashMap<Mob, Integer> siegeMinionMap = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
|
||
|
public ReentrantReadWriteLock minionLock = new ReentrantReadWriteLock();
|
||
|
private int patrolPointIndex = 0;
|
||
|
private int lastMobPowerToken = 0;
|
||
|
private HashMap<Integer, MobEquipment> equip = null;
|
||
|
private String nameOverride = "";
|
||
|
private Regions lastRegion = null;
|
||
|
private long despawnTime = 0;
|
||
|
private DeferredPowerJob weaponPower;
|
||
|
private DateTime upgradeDateTime = null;
|
||
|
private boolean lootSync = false;
|
||
|
private int fidalityID = 0;
|
||
|
private int equipmentSetID = 0;
|
||
|
private int lootSet = 0;
|
||
|
private boolean isGuard;
|
||
|
private ArrayList<Integer> fidelityRunes = null;
|
||
|
|
||
|
public boolean despawned = false;
|
||
|
public Vector3fImmutable destination = Vector3fImmutable.ZERO;
|
||
|
public Vector3fImmutable localLoc = Vector3fImmutable.ZERO;
|
||
|
|
||
|
/**
|
||
|
* No Id Constructor
|
||
|
*/
|
||
|
public Mob(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 npcType, boolean isMob, Zone parent,Building building, int contractID) {
|
||
|
super( firstName, lastName, statStrCurrent, statDexCurrent, statConCurrent, statIntCurrent, statSpiCurrent, level, exp, sit,
|
||
|
walk, combat, bindLoc, currentLoc, faceDir, healthCurrent, manaCurrent, stamCurrent, guild, runningTrains);
|
||
|
|
||
|
this.dbID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET;
|
||
|
this.state = STATE.Idle;
|
||
|
this.loadID = npcType;
|
||
|
this.isMob = isMob;
|
||
|
this.mobBase = MobBase.getMobBase(loadID);
|
||
|
this.currentID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET;
|
||
|
this.parentZone = parent;
|
||
|
this.parentZoneID = (parent != null) ? parent.getObjectUUID() : 0;
|
||
|
this.building = building;
|
||
|
|
||
|
if (building != null)
|
||
|
this.buildingID = building.getObjectUUID();
|
||
|
else this.buildingID = 0;
|
||
|
|
||
|
if (contractID == 0)
|
||
|
this.contract = null;
|
||
|
else
|
||
|
this.contract = DbManager.ContractQueries.GET_CONTRACT(contractID);
|
||
|
|
||
|
if (this.contract != null)
|
||
|
this.level = 10;
|
||
|
|
||
|
//initializeMob(false, false);
|
||
|
clearStatic();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Normal Constructor
|
||
|
*/
|
||
|
public Mob(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 npcType, boolean isMob, Zone parent, int newUUID, Building building, int contractID) {
|
||
|
super( firstName, lastName, statStrCurrent, statDexCurrent, statConCurrent, statIntCurrent, statSpiCurrent, level, exp, sit,
|
||
|
walk, combat, bindLoc, currentLoc, faceDir, healthCurrent, manaCurrent, stamCurrent, guild, runningTrains, newUUID);
|
||
|
this.state = STATE.Idle;
|
||
|
this.dbID = newUUID;
|
||
|
this.loadID = npcType;
|
||
|
this.isMob = isMob;
|
||
|
|
||
|
if (contractID == 0)
|
||
|
this.contract = null;
|
||
|
else
|
||
|
this.contract = DbManager.ContractQueries.GET_CONTRACT(contractID);
|
||
|
|
||
|
this.mobBase = MobBase.getMobBase(loadID);
|
||
|
this.parentZone = parent;
|
||
|
this.parentZoneID = (parent != null) ? parent.getObjectUUID() : 0;
|
||
|
this.building = building;
|
||
|
initializeMob(false,false,false);
|
||
|
clearStatic();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Pet Constructor
|
||
|
*/
|
||
|
public Mob( MobBase mobBase, Guild guild, Zone parent, short level, PlayerCharacter owner, int tableID) {
|
||
|
super(mobBase.getFirstName(), "", (short) 0, (short) 0, (short) 0, (short) 0, (short) 0, level, 0, false, true, false, owner.getLoc(), owner.getLoc(), owner.getFaceDir(), (short) mobBase.getHealthMax(), (short) 0, (short) 0, guild, (byte) 0, tableID);
|
||
|
this.state = STATE.Idle;
|
||
|
this.dbID = tableID;
|
||
|
this.loadID = mobBase.getObjectUUID();
|
||
|
this.isMob = true;
|
||
|
this.mobBase = mobBase;
|
||
|
this.parentZone = parent;
|
||
|
this.parentZoneID = (parent != null) ? parent.getObjectUUID() : 0;
|
||
|
this.ownerUID = owner.getObjectUUID();
|
||
|
initializeMob(true,false,false);
|
||
|
clearStatic();
|
||
|
}
|
||
|
//SIEGE CONSTRUCTOR
|
||
|
public Mob( MobBase mobBase, Guild guild, Zone parent, short level, Vector3fImmutable loc, int tableID,boolean isPlayerGuard) {
|
||
|
super( mobBase.getFirstName(), "", (short) 0, (short) 0, (short) 0, (short) 0, (short) 0, level, 0, false, true, false, loc, loc, Vector3fImmutable.ZERO, (short) mobBase.getHealthMax(), (short) 0, (short) 0, guild, (byte) 0, tableID);
|
||
|
this.dbID = tableID;
|
||
|
this.loadID = mobBase.getObjectUUID();
|
||
|
this.isMob = true;
|
||
|
this.mobBase = mobBase;
|
||
|
this.parentZone = parent;
|
||
|
this.parentZoneID = (parent != null) ? parent.getObjectUUID() : 0;
|
||
|
this.ownerUID = 0;
|
||
|
this.equip = new HashMap<>();
|
||
|
initializeMob(false,true, isPlayerGuard);
|
||
|
clearStatic();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ResultSet Constructor
|
||
|
*/
|
||
|
public Mob(ResultSet rs) throws SQLException {
|
||
|
|
||
|
super(rs);
|
||
|
|
||
|
try{
|
||
|
this.dbID = rs.getInt(1);
|
||
|
this.state = STATE.Idle;
|
||
|
this.loadID = rs.getInt("mob_mobbaseID");
|
||
|
this.gridObjectType = GridObjectType.DYNAMIC;
|
||
|
this.spawnRadius = rs.getFloat("mob_spawnRadius");
|
||
|
this.spawnTime = rs.getInt("mob_spawnTime");
|
||
|
this.isMob = true;
|
||
|
this.parentZone = null;
|
||
|
this.statLat = rs.getFloat("mob_spawnX");
|
||
|
this.statAlt = rs.getFloat("mob_spawnY");
|
||
|
this.statLon = rs.getFloat("mob_spawnZ");
|
||
|
|
||
|
this.localLoc = new Vector3fImmutable(this.statLat,this.statAlt,this.statLon);
|
||
|
|
||
|
this.parentZoneID = rs.getInt("parent");
|
||
|
this.level = (short) rs.getInt("mob_level");
|
||
|
int buildingID = rs.getInt("mob_buildingID");
|
||
|
|
||
|
try {
|
||
|
this.building = BuildingManager.getBuilding(buildingID);
|
||
|
}catch(Exception e){
|
||
|
this.building = null;
|
||
|
Logger.error(e.getMessage());
|
||
|
}
|
||
|
|
||
|
int contractID = rs.getInt("mob_contractID");
|
||
|
|
||
|
if (contractID == 0)
|
||
|
this.contract = null;
|
||
|
else
|
||
|
this.contract = DbManager.ContractQueries.GET_CONTRACT(contractID);
|
||
|
|
||
|
if (this.contract != null)
|
||
|
if (NPC.ISGuardCaptain(contract.getContractID())){
|
||
|
this.spawnTime = 60*15;
|
||
|
this.isPlayerGuard = true;
|
||
|
this.nameOverride = contract.getName();
|
||
|
}
|
||
|
|
||
|
int guildID = rs.getInt("mob_guildUID");
|
||
|
|
||
|
|
||
|
if (this.fidalityID != 0){
|
||
|
if (this.building != null)
|
||
|
this.guild = this.building.getGuild();
|
||
|
else
|
||
|
this.guild = Guild.getGuild(guildID);
|
||
|
}else
|
||
|
if (this.building != null)
|
||
|
this.guild = this.building.getGuild();
|
||
|
else
|
||
|
this.guild = Guild.getGuild(guildID);
|
||
|
|
||
|
if (this.guild == null)
|
||
|
this.guild = Guild.getErrantGuild();
|
||
|
|
||
|
java.util.Date sqlDateTime;
|
||
|
sqlDateTime = rs.getTimestamp("upgradeDate");
|
||
|
|
||
|
if (sqlDateTime != null)
|
||
|
upgradeDateTime = new DateTime(sqlDateTime);
|
||
|
else
|
||
|
upgradeDateTime = null;
|
||
|
|
||
|
// Submit upgrade job if NPC is currently set to rank.
|
||
|
|
||
|
if (this.upgradeDateTime != null)
|
||
|
Mob.submitUpgradeJob(this);
|
||
|
|
||
|
this.mobBase = MobBase.getMobBase(loadID);
|
||
|
|
||
|
this.setObjectTypeMask(MBServerStatics.MASK_MOB | this.getTypeMasks());
|
||
|
|
||
|
if (this.mobBase != null && this.spawnTime == 0)
|
||
|
this.spawnTime = this.mobBase.getSpawnTime();
|
||
|
|
||
|
this.bindLoc = new Vector3fImmutable(this.statLat, this.statAlt,this.statLon);
|
||
|
|
||
|
this.setParentZone(ZoneManager.getZoneByUUID(this.parentZoneID));
|
||
|
|
||
|
|
||
|
this.fidalityID = rs.getInt("fidalityID");
|
||
|
|
||
|
this.equipmentSetID = rs.getInt("equipmentSet");
|
||
|
|
||
|
if (this.contract != null)
|
||
|
this.equipmentSetID = this.contract.getEquipmentSet();
|
||
|
|
||
|
this.lootSet = (rs.getInt("lootSet"));
|
||
|
|
||
|
if (this.fidalityID != 0)
|
||
|
this.nameOverride = rs.getString("mob_name");
|
||
|
|
||
|
if (this.fidalityID != 0){
|
||
|
|
||
|
Zone parentZone = ZoneManager.getZoneByUUID(this.parentZoneID);
|
||
|
if (parentZone != null){
|
||
|
this.fidelityRunes = WorldServer.ZoneFidelityMobRunes.get(parentZone.getLoadNum()).get(this.fidalityID);
|
||
|
|
||
|
if (this.fidelityRunes != null)
|
||
|
for (Integer runeID : this.fidelityRunes){
|
||
|
if (runeID == 252623 ){
|
||
|
this.isGuard = true;
|
||
|
this.noAggro = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} catch(Exception e){
|
||
|
Logger.error( currentID + "");
|
||
|
}
|
||
|
|
||
|
try{
|
||
|
initializeMob(false,false,this.isPlayerGuard);
|
||
|
} catch(Exception e){
|
||
|
Logger.error(e);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
private void clearStatic() {
|
||
|
|
||
|
if (this.parentZone != null)
|
||
|
this.parentZone.zoneMobSet.remove(this);
|
||
|
|
||
|
this.parentZone = null;
|
||
|
this.statLat = 0f;
|
||
|
this.statLon = 0f;
|
||
|
this.statAlt = 0f;
|
||
|
}
|
||
|
|
||
|
private void initializeMob(boolean isPet, boolean isSiege, boolean isGuard) {
|
||
|
|
||
|
if (this.mobBase != null) {
|
||
|
|
||
|
this.gridObjectType = GridObjectType.DYNAMIC;
|
||
|
this.healthMax = this.mobBase.getHealthMax();
|
||
|
this.manaMax = 0;
|
||
|
this.staminaMax = 0;
|
||
|
this.setHealth(this.healthMax);
|
||
|
this.mana.set(this.manaMax);
|
||
|
this.stamina.set(this.staminaMax);
|
||
|
|
||
|
if(!this.nameOverride.isEmpty())
|
||
|
this.firstName = this.nameOverride;
|
||
|
else
|
||
|
this.firstName = this.mobBase.getFirstName();
|
||
|
if (isPet) {
|
||
|
this.setObjectTypeMask(MBServerStatics.MASK_PET | this.getTypeMasks());
|
||
|
if (ConfigManager.serverType.equals(ServerType.LOGINSERVER))
|
||
|
this.setLoc(this.getLoc());
|
||
|
}
|
||
|
if (!isPet && this.contract == null) {
|
||
|
this.level = (short) this.mobBase.getLevel();
|
||
|
}
|
||
|
|
||
|
} else
|
||
|
this.level = 1;
|
||
|
|
||
|
//add this npc to building
|
||
|
if (this.building != null && this.loadID != 0 && this.fidalityID == 0) {
|
||
|
|
||
|
int maxSlots;
|
||
|
maxSlots = building.getBlueprint().getSlotsForRank(this.building.getRank());
|
||
|
|
||
|
for (int slot = 1; slot < maxSlots + 1; slot++) {
|
||
|
if (!this.building.getHirelings().containsValue(slot)) {
|
||
|
this.building.getHirelings().put(this, slot);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//set bonuses
|
||
|
this.bonuses = new PlayerBonuses(this);
|
||
|
|
||
|
//TODO set these correctly later
|
||
|
this.rangeHandOne = 8;
|
||
|
this.rangeHandTwo = -1;
|
||
|
this.minDamageHandOne = 0;
|
||
|
this.maxDamageHandOne = 0;
|
||
|
this.minDamageHandTwo = 1;
|
||
|
this.maxDamageHandTwo = 4;
|
||
|
this.atrHandOne = 300;
|
||
|
this.atrHandOne = 300;
|
||
|
this.defenseRating = (short) this.mobBase.getDefenseRating();
|
||
|
this.isActive = true;
|
||
|
|
||
|
this.charItemManager.load();
|
||
|
|
||
|
//load AI for general mobs.
|
||
|
|
||
|
if (isPet || isSiege || (isGuard && this.contract == null))
|
||
|
this.currentID = (--Mob.staticID);
|
||
|
else
|
||
|
this.currentID = this.dbID;
|
||
|
|
||
|
if (!isPet && !isSiege && !this.isPlayerGuard)
|
||
|
loadInventory();
|
||
|
|
||
|
//store mobs by Database ID
|
||
|
|
||
|
if (!isPet && !isSiege)
|
||
|
Mob.mobMapByDBID.put(this.dbID, this);
|
||
|
}
|
||
|
|
||
|
private void initializeSkills() {
|
||
|
|
||
|
if (this.mobBase.getMobBaseStats() == null)
|
||
|
return;
|
||
|
|
||
|
long skillVector = this.mobBase.getMobBaseStats().getSkillSet();
|
||
|
int skillValue = this.mobBase.getMobBaseStats().getSkillValue();
|
||
|
|
||
|
if (this.mobBase.getObjectUUID() >= 17233) {
|
||
|
for (CharacterSkills cs : CharacterSkills.values()) {
|
||
|
SkillsBase sb = DbManager.SkillsBaseQueries.GET_BASE_BY_TOKEN(cs.getToken());
|
||
|
CharacterSkill css = new CharacterSkill(sb, this, 50);
|
||
|
this.skills.put(sb.getName(), css);
|
||
|
}
|
||
|
} else {
|
||
|
for (CharacterSkills cs : CharacterSkills.values()) {
|
||
|
if ((skillVector & cs.getFlag()) != 0) {
|
||
|
SkillsBase sb = DbManager.SkillsBaseQueries.GET_BASE_BY_TOKEN(cs.getToken());
|
||
|
CharacterSkill css = new CharacterSkill(sb, this, skillValue);
|
||
|
this.skills.put(sb.getName(), css);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void initializeStaticEffects() {
|
||
|
|
||
|
EffectsBase eb = null;
|
||
|
for (MobBaseEffects mbe : this.mobBase.getRaceEffectsList()) {
|
||
|
|
||
|
eb = PowersManager.getEffectByToken(mbe.getToken());
|
||
|
|
||
|
if (eb == null) {
|
||
|
Logger.info( "EffectsBase Null for Token " + mbe.getToken());
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//check to upgrade effects if needed.
|
||
|
if (this.effects.containsKey(Integer.toString(eb.getUUID()))) {
|
||
|
if (mbe.getReqLvl() > (int) this.level)
|
||
|
continue;
|
||
|
|
||
|
Effect eff = this.effects.get(Integer.toString(eb.getUUID()));
|
||
|
|
||
|
if (eff == null)
|
||
|
continue;
|
||
|
|
||
|
if (eff.getTrains() > mbe.getRank())
|
||
|
continue;
|
||
|
|
||
|
//new effect is of a higher rank. remove old effect and apply new one.
|
||
|
eff.cancelJob();
|
||
|
this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true);
|
||
|
} else {
|
||
|
if (mbe.getReqLvl() > (int) this.level)
|
||
|
continue;
|
||
|
|
||
|
this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Apply all rune effects.
|
||
|
// Only Captains have contracts
|
||
|
if (contract != null || this.isPlayerGuard){
|
||
|
RuneBase guardRune = RuneBase.getRuneBase(252621);
|
||
|
for (MobBaseEffects mbe : guardRune.getEffectsList()) {
|
||
|
|
||
|
eb = PowersManager.getEffectByToken(mbe.getToken());
|
||
|
|
||
|
if (eb == null) {
|
||
|
Logger.info( "EffectsBase Null for Token " + mbe.getToken());
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//check to upgrade effects if needed.
|
||
|
if (this.effects.containsKey(Integer.toString(eb.getUUID()))) {
|
||
|
|
||
|
if (mbe.getReqLvl() > (int) this.level)
|
||
|
continue;
|
||
|
|
||
|
Effect eff = this.effects.get(Integer.toString(eb.getUUID()));
|
||
|
|
||
|
if (eff == null)
|
||
|
continue;
|
||
|
|
||
|
//Current effect is a higher rank, dont apply.
|
||
|
if (eff.getTrains() > mbe.getRank())
|
||
|
continue;
|
||
|
|
||
|
//new effect is of a higher rank. remove old effect and apply new one.
|
||
|
eff.cancelJob();
|
||
|
this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true);
|
||
|
} else {
|
||
|
|
||
|
if (mbe.getReqLvl() > (int) this.level)
|
||
|
continue;
|
||
|
|
||
|
this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RuneBase WarriorRune = RuneBase.getRuneBase(2518);
|
||
|
for (MobBaseEffects mbe : WarriorRune.getEffectsList()) {
|
||
|
|
||
|
eb = PowersManager.getEffectByToken(mbe.getToken());
|
||
|
|
||
|
if (eb == null) {
|
||
|
Logger.info( "EffectsBase Null for Token " + mbe.getToken());
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//check to upgrade effects if needed.
|
||
|
if (this.effects.containsKey(Integer.toString(eb.getUUID()))) {
|
||
|
|
||
|
if (mbe.getReqLvl() > (int) this.level)
|
||
|
continue;
|
||
|
|
||
|
Effect eff = this.effects.get(Integer.toString(eb.getUUID()));
|
||
|
|
||
|
if (eff == null)
|
||
|
continue;
|
||
|
|
||
|
//Current effect is a higher rank, dont apply.
|
||
|
if (eff.getTrains() > mbe.getRank())
|
||
|
continue;
|
||
|
|
||
|
//new effect is of a higher rank. remove old effect and apply new one.
|
||
|
eff.cancelJob();
|
||
|
this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true);
|
||
|
} else {
|
||
|
|
||
|
if (mbe.getReqLvl() > (int) this.level)
|
||
|
continue;
|
||
|
|
||
|
this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (this.fidelityRunes != null){
|
||
|
|
||
|
for (int fidelityRune : this.fidelityRunes) {
|
||
|
|
||
|
RuneBase rune = RuneBase.getRuneBase(fidelityRune);
|
||
|
|
||
|
if (rune != null)
|
||
|
for (MobBaseEffects mbe : rune.getEffectsList()) {
|
||
|
|
||
|
eb = PowersManager.getEffectByToken(mbe.getToken());
|
||
|
if (eb == null) {
|
||
|
Logger.info("EffectsBase Null for Token " + mbe.getToken());
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//check to upgrade effects if needed.
|
||
|
if (this.effects.containsKey(Integer.toString(eb.getUUID()))) {
|
||
|
if (mbe.getReqLvl() > (int) this.level)
|
||
|
continue;
|
||
|
|
||
|
Effect eff = this.effects.get(Integer.toString(eb.getUUID()));
|
||
|
|
||
|
if (eff == null)
|
||
|
continue;
|
||
|
|
||
|
//Current effect is a higher rank, dont apply.
|
||
|
if (eff.getTrains() > mbe.getRank())
|
||
|
continue;
|
||
|
|
||
|
//new effect is of a higher rank. remove old effect and apply new one.
|
||
|
eff.cancelJob();
|
||
|
this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
if (mbe.getReqLvl() > (int) this.level)
|
||
|
continue;
|
||
|
|
||
|
this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}else
|
||
|
for (RuneBase rune : this.mobBase.getRunes()) {
|
||
|
for (MobBaseEffects mbe : rune.getEffectsList()) {
|
||
|
|
||
|
eb = PowersManager.getEffectByToken(mbe.getToken());
|
||
|
if (eb == null) {
|
||
|
Logger.info( "EffectsBase Null for Token " + mbe.getToken());
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//check to upgrade effects if needed.
|
||
|
if (this.effects.containsKey(Integer.toString(eb.getUUID()))) {
|
||
|
if (mbe.getReqLvl() > (int) this.level)
|
||
|
continue;
|
||
|
|
||
|
Effect eff = this.effects.get(Integer.toString(eb.getUUID()));
|
||
|
|
||
|
if (eff == null)
|
||
|
continue;
|
||
|
|
||
|
//Current effect is a higher rank, dont apply.
|
||
|
if (eff.getTrains() > mbe.getRank())
|
||
|
continue;
|
||
|
|
||
|
//new effect is of a higher rank. remove old effect and apply new one.
|
||
|
eff.cancelJob();
|
||
|
this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true);
|
||
|
} else {
|
||
|
|
||
|
if (mbe.getReqLvl() > (int) this.level)
|
||
|
continue;
|
||
|
|
||
|
this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Getters
|
||
|
*/
|
||
|
@Override
|
||
|
public int getDBID() {
|
||
|
return this.dbID;
|
||
|
}
|
||
|
|
||
|
public int getLoadID() {
|
||
|
return loadID;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int getObjectUUID() {
|
||
|
return currentID;
|
||
|
}
|
||
|
|
||
|
public float getSpawnX() {
|
||
|
return this.statLat;
|
||
|
}
|
||
|
|
||
|
public float getSpawnY() {
|
||
|
return this.statAlt;
|
||
|
}
|
||
|
|
||
|
public float getSpawnZ() {
|
||
|
return this.statLon;
|
||
|
}
|
||
|
|
||
|
public float getSpawnRadius() {
|
||
|
return this.spawnRadius;
|
||
|
}
|
||
|
|
||
|
public int getSpawnTime() {
|
||
|
|
||
|
if (this.spawnTime == 0)
|
||
|
return MBServerStatics.RESPAWN_TIMER;
|
||
|
else
|
||
|
return this.spawnTime * 1000;
|
||
|
}
|
||
|
|
||
|
//use getSpawnTime instead. This is just for init tables
|
||
|
public int getTrueSpawnTime() {
|
||
|
return this.spawnTime;
|
||
|
}
|
||
|
|
||
|
public String getSpawnTimeAsString() {
|
||
|
if (this.spawnTime == 0)
|
||
|
return MBServerStatics.DEFAULT_SPAWN_TIME_MS / 1000 + " seconds (Default)";
|
||
|
else
|
||
|
return this.spawnTime + " seconds";
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
public void setSpawnTime(int value) {
|
||
|
this.spawnTime = value;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public MobBase getMobBase() {
|
||
|
return this.mobBase;
|
||
|
}
|
||
|
|
||
|
public int getMobBaseID() {
|
||
|
|
||
|
if (this.mobBase != null)
|
||
|
return this.mobBase.getObjectUUID();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
public Vector3fImmutable getTrueBindLoc() {
|
||
|
return this.bindLoc;
|
||
|
}
|
||
|
|
||
|
public Zone getParentZone() {
|
||
|
return this.parentZone;
|
||
|
}
|
||
|
|
||
|
public int getParentZoneID() {
|
||
|
|
||
|
if (this.parentZone != null)
|
||
|
return this.parentZone.getObjectUUID();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int getGuildUUID() {
|
||
|
|
||
|
if (this.guild == null)
|
||
|
return 0;
|
||
|
|
||
|
return this.guild.getObjectUUID();
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public PlayerCharacter getOwner() {
|
||
|
|
||
|
if (!this.isPet())
|
||
|
return null;
|
||
|
|
||
|
if (this.ownerUID == 0)
|
||
|
return null;
|
||
|
|
||
|
return PlayerCharacter.getFromCache(this.ownerUID);
|
||
|
}
|
||
|
|
||
|
public void setOwner(PlayerCharacter value) {
|
||
|
|
||
|
if (value == null)
|
||
|
this.ownerUID = 0;
|
||
|
else
|
||
|
this.ownerUID = value.getObjectUUID();
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public AbstractWorldObject getFearedObject() {
|
||
|
return this.fearedObject;
|
||
|
}
|
||
|
|
||
|
public void setFearedObject(AbstractWorldObject awo) {
|
||
|
this.fearedObject = awo;
|
||
|
}
|
||
|
|
||
|
public void setParentZone(Zone zone) {
|
||
|
|
||
|
if (this.parentZone == null){
|
||
|
zone.zoneMobSet.add(this);
|
||
|
this.parentZone = zone;
|
||
|
}
|
||
|
|
||
|
this.bindLoc = Mob.GetSpawnRadiusLocation(this);
|
||
|
this.lastBindLoc = bindLoc;
|
||
|
this.setLoc(bindLoc);
|
||
|
this.stopMovement(bindLoc);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public Vector3fImmutable getBindLoc() {
|
||
|
|
||
|
if(this.isPet() && !this.isSiege)
|
||
|
return this.getOwner() != null? this.getOwner().getLoc() : this.getLoc();
|
||
|
return this.bindLoc;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Serialization
|
||
|
*/
|
||
|
|
||
|
public static void __serializeForClientMsg(Mob mob,ByteBufferWriter writer) throws SerializationException {
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
public static void serializeMobForClientMsgOtherPlayer(Mob mob,ByteBufferWriter writer, boolean hideAsciiLastName)
|
||
|
throws SerializationException {
|
||
|
Mob.serializeForClientMsgOtherPlayer(mob,writer);
|
||
|
}
|
||
|
|
||
|
|
||
|
public static void serializeForClientMsgOtherPlayer(Mob mob, ByteBufferWriter writer)
|
||
|
throws SerializationException {
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
|
||
|
int tid = (mob.mobBase != null) ? mob.mobBase.getLoadID() : 0;
|
||
|
int classID = MobBase.GetClassType(mob.mobBase.getObjectUUID());
|
||
|
if (mob.isPet()) {
|
||
|
writer.putInt(2);
|
||
|
writer.putInt(3);
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(2522);
|
||
|
writer.putInt(GameObjectType.NPCClassRune.ordinal());
|
||
|
writer.putInt(mob.currentID);
|
||
|
} else if (tid == 100570) { //kur'adar
|
||
|
writer.putInt(3);
|
||
|
Mob.serializeRune(mob,writer, 3, GameObjectType.NPCClassRuneTwo.ordinal(), 2518); //warrior class
|
||
|
serializeRune(mob,writer, 5, GameObjectType.NPCClassRuneThree.ordinal(), 252621); //guard rune
|
||
|
} else if (tid == 100962 || tid == 100965) { //Spydraxxx the Mighty, Denigo Tantric
|
||
|
writer.putInt(2);
|
||
|
serializeRune(mob,writer, 5, GameObjectType.NPCClassRuneTwo.ordinal(), 252621); //guard rune
|
||
|
}else if (mob.contract != null || mob.isPlayerGuard){
|
||
|
writer.putInt(3);
|
||
|
serializeRune(mob,writer, 3, GameObjectType.NPCClassRuneTwo.ordinal(),MobBase.GetClassType(mob.getMobBaseID())); //warrior class
|
||
|
serializeRune(mob,writer, 5, GameObjectType.NPCClassRuneThree.ordinal(), 252621); //guard rune
|
||
|
}else {
|
||
|
|
||
|
writer.putInt(1);
|
||
|
}
|
||
|
|
||
|
//Generate Race Rune
|
||
|
writer.putInt(1);
|
||
|
writer.putInt(0);
|
||
|
|
||
|
if (mob.mobBase != null)
|
||
|
writer.putInt(mob.mobBase.getLoadID());
|
||
|
else
|
||
|
writer.putInt(mob.loadID);
|
||
|
|
||
|
writer.putInt(mob.getObjectType().ordinal());
|
||
|
writer.putInt(mob.currentID);
|
||
|
|
||
|
//Send Stats
|
||
|
writer.putInt(5);
|
||
|
writer.putInt(0x8AC3C0E6); //Str
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0xACB82E33); //Dex
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0xB15DC77E); //Con
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0xE07B3336); //Int
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0xFF665EC3); //Spi
|
||
|
writer.putInt(0);
|
||
|
|
||
|
if (!mob.nameOverride.isEmpty()){
|
||
|
writer.putString(mob.nameOverride);
|
||
|
writer.putInt(0);
|
||
|
} else {
|
||
|
writer.putString(mob.firstName);
|
||
|
writer.putString(mob.lastName);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
|
||
|
writer.put((byte) 0);
|
||
|
writer.putInt(mob.getObjectType().ordinal());
|
||
|
writer.putInt(mob.currentID);
|
||
|
|
||
|
if (mob.mobBase != null) {
|
||
|
writer.putFloat(mob.mobBase.getScale());
|
||
|
writer.putFloat(mob.mobBase.getScale());
|
||
|
writer.putFloat(mob.mobBase.getScale());
|
||
|
} else {
|
||
|
writer.putFloat(1.0f);
|
||
|
writer.putFloat(1.0f);
|
||
|
writer.putFloat(1.0f);
|
||
|
}
|
||
|
|
||
|
//Believe this is spawn loc, ignore for now
|
||
|
writer.putVector3f(mob.getLoc());
|
||
|
|
||
|
//Rotation
|
||
|
writer.putFloat(mob.getRot().y);
|
||
|
|
||
|
//Inventory Stuff
|
||
|
writer.putInt(0);
|
||
|
|
||
|
// get a copy of the equipped items.
|
||
|
|
||
|
|
||
|
if (mob.equip != null){
|
||
|
|
||
|
writer.putInt(mob.equip.size());
|
||
|
|
||
|
for (MobEquipment me:mob.equip.values()){
|
||
|
MobEquipment.serializeForClientMsg(me,writer);
|
||
|
}
|
||
|
}else{
|
||
|
writer.putInt(0);
|
||
|
}
|
||
|
|
||
|
writer.putInt(mob.getRank());
|
||
|
writer.putInt(mob.getLevel());
|
||
|
writer.putInt(mob.getIsSittingAsInt()); //Standing
|
||
|
writer.putInt(mob.getIsWalkingAsInt()); //Walking
|
||
|
writer.putInt(mob.getIsCombatAsInt()); //Combat
|
||
|
writer.putInt(2); //Unknown
|
||
|
writer.putInt(1); //Unknown - Headlights?
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
writer.put((byte) 0);
|
||
|
writer.put((byte) 0);
|
||
|
writer.put((byte) 0);
|
||
|
writer.putInt(0);
|
||
|
|
||
|
if (mob.contract != null && mob.npcOwner == null){
|
||
|
writer.put((byte) 1);
|
||
|
writer.putLong(0);
|
||
|
writer.putLong(0);
|
||
|
|
||
|
if (mob.contract != null)
|
||
|
writer.putInt(mob.contract.getIconID());
|
||
|
else
|
||
|
writer.putInt(0); //npc icon ID
|
||
|
|
||
|
} else
|
||
|
writer.put((byte)0);
|
||
|
|
||
|
|
||
|
if (mob.npcOwner != null){
|
||
|
writer.put((byte) 1);
|
||
|
writer.putInt(GameObjectType.PlayerCharacter.ordinal());
|
||
|
writer.putInt(131117009);
|
||
|
writer.putInt(mob.npcOwner.getObjectType().ordinal());
|
||
|
writer.putInt(mob.npcOwner.getObjectUUID());
|
||
|
writer.putInt(8);
|
||
|
}else
|
||
|
writer.put((byte)0);
|
||
|
|
||
|
if (mob.isPet()) {
|
||
|
|
||
|
writer.put((byte) 1);
|
||
|
|
||
|
if (mob.getOwner() != null) {
|
||
|
writer.putInt(mob.getOwner().getObjectType().ordinal());
|
||
|
writer.putInt(mob.getOwner().getObjectUUID());
|
||
|
} else {
|
||
|
writer.putInt(0); //ownerType
|
||
|
writer.putInt(0); //ownerID
|
||
|
}
|
||
|
} else {
|
||
|
writer.put((byte) 0);
|
||
|
}
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
|
||
|
if (!mob.isAlive() && !mob.isPet() && !mob.isNecroPet() && !mob.isSiege && !mob.isPlayerGuard) {
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(0);
|
||
|
}
|
||
|
|
||
|
writer.put((byte) 0);
|
||
|
Guild._serializeForClientMsg(mob.getGuild(),writer);
|
||
|
// writer.putInt(0);
|
||
|
// writer.putInt(0);
|
||
|
if (mob.mobBase != null && mob.mobBase.getObjectUUID() == 100570) {
|
||
|
writer.putInt(2);
|
||
|
writer.putInt(0x00008A2E);
|
||
|
writer.putInt(0x1AB84003);
|
||
|
} else if (mob.isSiege) {
|
||
|
writer.putInt(1);
|
||
|
writer.putInt(74620179);
|
||
|
} else
|
||
|
writer.putInt(0);
|
||
|
|
||
|
// writer.putInt(1);
|
||
|
// writer.putInt(0); //0xAC13C5E9 - alternate textures
|
||
|
writer.putInt(0); //0xB8400300
|
||
|
writer.putInt(0);
|
||
|
|
||
|
//TODO Guard
|
||
|
writer.put((byte) 0);
|
||
|
// writer.put((byte)0); //Is guard..
|
||
|
|
||
|
writer.putFloat(mob.healthMax);
|
||
|
writer.putFloat(mob.health.get());
|
||
|
|
||
|
//TODO Peace Zone
|
||
|
writer.put((byte) 1); //0=show tags, 1=don't
|
||
|
|
||
|
//DON't LOAD EFFECTS FOR DEAD MOBS.
|
||
|
|
||
|
if (!mob.isAlive())
|
||
|
writer.putInt(0);
|
||
|
else{
|
||
|
int indexPosition = writer.position();
|
||
|
writer.putInt(0); //placeholder for item cnt
|
||
|
int total = 0;
|
||
|
|
||
|
// Logger.info("",""+ mob.getEffects().size());
|
||
|
for (Effect eff : mob.getEffects().values()) {
|
||
|
if (eff.isStatic())
|
||
|
continue;
|
||
|
if ( !eff.serializeForLoad(writer))
|
||
|
continue;
|
||
|
++total;
|
||
|
}
|
||
|
|
||
|
writer.putIntAt(total, indexPosition);
|
||
|
}
|
||
|
|
||
|
// // Effects
|
||
|
writer.put((byte) 0);
|
||
|
}
|
||
|
|
||
|
private static void serializeRune(Mob mob,ByteBufferWriter writer, int type, int objectType, int runeID) {
|
||
|
writer.putInt(type);
|
||
|
writer.putInt(0);
|
||
|
writer.putInt(runeID);
|
||
|
writer.putInt(objectType);
|
||
|
writer.putInt(mob.currentID);
|
||
|
}
|
||
|
|
||
|
|
||
|
public void calculateModifiedStats() {
|
||
|
|
||
|
float strVal = this.mobBase.getMobBaseStats().getBaseStr();
|
||
|
float dexVal = this.mobBase.getMobBaseStats().getBaseDex();
|
||
|
float conVal = 0; // I believe this will desync the Mobs Health if we call it.
|
||
|
float intVal = this.mobBase.getMobBaseStats().getBaseInt();
|
||
|
float spiVal = this.mobBase.getMobBaseStats().getBaseSpi();
|
||
|
|
||
|
// TODO modify for equipment
|
||
|
if (this.bonuses != null) {
|
||
|
// modify for effects
|
||
|
strVal += this.bonuses.getFloat(ModType.Attr, SourceType.Strength);
|
||
|
dexVal += this.bonuses.getFloat(ModType.Attr, SourceType.Dexterity);
|
||
|
conVal += this.bonuses.getFloat(ModType.Attr, SourceType.Constitution);
|
||
|
intVal += this.bonuses.getFloat(ModType.Attr, SourceType.Intelligence);
|
||
|
spiVal += this.bonuses.getFloat(ModType.Attr, SourceType.Spirit);
|
||
|
|
||
|
// apply dex penalty for armor
|
||
|
// modify percent amounts. DO THIS LAST!
|
||
|
strVal *= (1+this.bonuses.getFloatPercentAll(ModType.Attr, SourceType.Strength));
|
||
|
dexVal *= (1+this.bonuses.getFloatPercentAll(ModType.Attr, SourceType.Dexterity));
|
||
|
conVal *= (1+this.bonuses.getFloatPercentAll(ModType.Attr, SourceType.Constitution));
|
||
|
intVal *= (1+this.bonuses.getFloatPercentAll(ModType.Attr, SourceType.Intelligence));
|
||
|
spiVal *= (1+this.bonuses.getFloatPercentAll(ModType.Attr, SourceType.Spirit));
|
||
|
} else {
|
||
|
// apply dex penalty for armor
|
||
|
}
|
||
|
|
||
|
// Set current stats
|
||
|
this.statStrCurrent = (strVal < 1) ? (short) 1 : (short) strVal;
|
||
|
this.statDexCurrent = (dexVal < 1) ? (short) 1 : (short) dexVal;
|
||
|
this.statConCurrent = (conVal < 1) ? (short) 1 : (short) conVal;
|
||
|
this.statIntCurrent = (intVal < 1) ? (short) 1 : (short) intVal;
|
||
|
this.statSpiCurrent = (spiVal < 1) ? (short) 1 : (short) spiVal;
|
||
|
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public float getSpeed() {
|
||
|
float bonus = 1;
|
||
|
if (this.bonuses != null)
|
||
|
// get rune and effect bonuses
|
||
|
bonus *= (1 + this.bonuses.getFloatPercentAll(ModType.Speed, SourceType.None));
|
||
|
|
||
|
if (this.isPlayerGuard){
|
||
|
switch (this.mobBase.getLoadID()){
|
||
|
case 2111:
|
||
|
if (this.isWalk())
|
||
|
if (this.isCombat())
|
||
|
return Enum.Guards.HumanArcher.getWalkCombatSpeed() * bonus;
|
||
|
else return Enum.Guards.HumanArcher.getWalkSpeed() * bonus;
|
||
|
else
|
||
|
return Enum.Guards.HumanArcher.getRunSpeed() * bonus;
|
||
|
|
||
|
case 14103:
|
||
|
if (this.isWalk())
|
||
|
if (this.isCombat())
|
||
|
return Enum.Guards.UndeadArcher.getWalkCombatSpeed() * bonus;
|
||
|
else return Enum.Guards.UndeadArcher.getWalkSpeed() * bonus;
|
||
|
else
|
||
|
return Enum.Guards.UndeadArcher.getRunSpeed() * bonus;
|
||
|
}
|
||
|
}
|
||
|
//return combat speeds
|
||
|
if (this.isCombat()){
|
||
|
if (this.isWalk()){
|
||
|
if (this.mobBase.getWalkCombat() <= 0)
|
||
|
return MBServerStatics.MOB_SPEED_WALKCOMBAT * bonus;
|
||
|
return this.mobBase.getWalkCombat() * bonus;
|
||
|
}else{
|
||
|
if (this.mobBase.getRunCombat() <= 0)
|
||
|
return MBServerStatics.MOB_SPEED_RUNCOMBAT * bonus;
|
||
|
return this.mobBase.getRunCombat() * bonus;
|
||
|
}
|
||
|
//not combat return normal speeds
|
||
|
}else{
|
||
|
if (this.isWalk()){
|
||
|
if (this.mobBase.getWalk() <= 0)
|
||
|
return MBServerStatics.MOB_SPEED_WALK * bonus;
|
||
|
return this.mobBase.getWalk() * bonus;
|
||
|
}else{
|
||
|
if (this.mobBase.getRun() <= 0)
|
||
|
return MBServerStatics.MOB_SPEED_RUN * bonus;
|
||
|
return this.mobBase.getRun() * bonus;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public float getPassiveChance(String type, int AttackerLevel, boolean fromCombat) {
|
||
|
//TODO add this later for dodge
|
||
|
return 0f;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @ Kill this Character
|
||
|
*/
|
||
|
@Override
|
||
|
public void killCharacter(AbstractCharacter attacker) {
|
||
|
|
||
|
|
||
|
this.stopMovement(this.getMovementLoc());
|
||
|
|
||
|
if (attacker != null){
|
||
|
|
||
|
if (attacker.getObjectType() == GameObjectType.PlayerCharacter) {
|
||
|
Group g = GroupManager.getGroup((PlayerCharacter) attacker);
|
||
|
|
||
|
// Give XP, now handled inside the Experience Object
|
||
|
if (!this.isPet() && !this.isNecroPet() && !this.isSummonedPet() && !this.isPlayerGuard)
|
||
|
Experience.doExperience((PlayerCharacter) attacker, this, g);
|
||
|
} else if (attacker.getObjectType().equals(GameObjectType.Mob)){
|
||
|
Mob mobAttacker = (Mob)attacker;
|
||
|
|
||
|
if (mobAttacker.isPet()){
|
||
|
|
||
|
PlayerCharacter owner = mobAttacker.getOwner();
|
||
|
|
||
|
if (owner != null){
|
||
|
|
||
|
if (!this.isPet() && !this.isNecroPet() && !this.isSummonedPet() && !this.isPlayerGuard){
|
||
|
Group g = GroupManager.getGroup(owner);
|
||
|
|
||
|
// Give XP, now handled inside the Experience Object
|
||
|
Experience.doExperience(owner, this, g);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
killCleanup();
|
||
|
}
|
||
|
|
||
|
public void updateLocation(){
|
||
|
|
||
|
if (!this.isMoving())
|
||
|
return;
|
||
|
|
||
|
if (state == STATE.Disabled)
|
||
|
return;
|
||
|
|
||
|
if ( this.isAlive() == false || this.getBonuses().getBool(ModType.Stunned, SourceType.None) || this.getBonuses().getBool(ModType.CannotMove, SourceType.None)) {
|
||
|
//Target is stunned or rooted. Don't move
|
||
|
|
||
|
this.stopMovement(this.getMovementLoc());
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Vector3fImmutable newLoc = this.getMovementLoc();
|
||
|
|
||
|
if (newLoc.equals(this.getEndLoc())){
|
||
|
this.stopMovement(newLoc);
|
||
|
return;
|
||
|
//Next upda
|
||
|
}
|
||
|
|
||
|
setLoc(newLoc);
|
||
|
//Next update will be end Loc, lets stop him here.
|
||
|
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void killCharacter(String reason) {
|
||
|
killCleanup();
|
||
|
}
|
||
|
|
||
|
private void killCleanup() {
|
||
|
Dispatch dispatch;
|
||
|
|
||
|
try {
|
||
|
if (this.isSiege) {
|
||
|
this.deathTime = System.currentTimeMillis();
|
||
|
this.state = STATE.Dead;
|
||
|
try {
|
||
|
this.clearEffects();
|
||
|
}catch(Exception e){
|
||
|
Logger.error( e.getMessage());
|
||
|
}
|
||
|
this.combatTarget = null;
|
||
|
this.hasLoot = false;
|
||
|
this.playerAgroMap.clear();
|
||
|
|
||
|
this.timeToSpawnSiege = System.currentTimeMillis() + 60 * 15 * 1000;
|
||
|
|
||
|
if (this.isPet()) {
|
||
|
|
||
|
PlayerCharacter petOwner = this.getOwner();
|
||
|
|
||
|
if (petOwner != null){
|
||
|
this.setOwner(null);
|
||
|
petOwner.setPet(null);
|
||
|
PetMsg petMsg = new PetMsg(5, null);
|
||
|
dispatch = Dispatch.borrow(this.getOwner(), petMsg);
|
||
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} else if (this.isPet() || this.isNecroPet()) {
|
||
|
this.state = STATE.Disabled;
|
||
|
|
||
|
this.combatTarget = null;
|
||
|
this.hasLoot = false;
|
||
|
|
||
|
if (this.parentZone != null)
|
||
|
this.parentZone.zoneMobSet.remove(this);
|
||
|
|
||
|
try {
|
||
|
this.clearEffects();
|
||
|
}catch(Exception e){
|
||
|
Logger.error( e.getMessage());
|
||
|
}
|
||
|
this.playerAgroMap.clear();
|
||
|
WorldGrid.RemoveWorldObject(this);
|
||
|
|
||
|
DbManager.removeFromCache(this);
|
||
|
|
||
|
// YEAH BONUS CODE! THANKS UNNAMED ASSHOLE!
|
||
|
//WorldServer.removeObject(this);
|
||
|
//WorldGrid.INSTANCE.removeWorldObject(this);
|
||
|
//owner.getPet().disableIntelligence();
|
||
|
|
||
|
PlayerCharacter petOwner = this.getOwner();
|
||
|
|
||
|
if (petOwner != null){
|
||
|
this.setOwner(null);
|
||
|
petOwner.setPet(null);
|
||
|
PetMsg petMsg = new PetMsg(5, null);
|
||
|
dispatch = Dispatch.borrow(petOwner, petMsg);
|
||
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
//cleanup effects
|
||
|
|
||
|
this.deathTime = System.currentTimeMillis();
|
||
|
this.state = STATE.Dead;
|
||
|
|
||
|
playerAgroMap.clear();
|
||
|
|
||
|
if (!this.isPlayerGuard){
|
||
|
|
||
|
ArrayList<MobLoot> alml = LootTable.getMobLootDeath(this, this.getLevel(), this.getLootTable());
|
||
|
|
||
|
for (MobLoot ml : alml) {
|
||
|
this.charItemManager.addItemToInventory(ml);
|
||
|
}
|
||
|
|
||
|
if (this.equip != null){
|
||
|
|
||
|
for (MobEquipment me: equip.values()){
|
||
|
if (me.getDropChance() == 0)
|
||
|
continue;
|
||
|
|
||
|
float chance = ThreadLocalRandom.current().nextFloat();
|
||
|
|
||
|
if (chance <= me.getDropChance()){
|
||
|
MobLoot ml = new MobLoot(this, me.getItemBase(), false);
|
||
|
ml.setFidelityEquipID(me.getObjectUUID());
|
||
|
this.charItemManager.addItemToInventory(ml);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
try {
|
||
|
this.clearEffects();
|
||
|
}catch(Exception e){
|
||
|
Logger.error( e.getMessage());
|
||
|
}
|
||
|
|
||
|
this.combat = false;
|
||
|
this.walkMode = true;
|
||
|
this.combatTarget = null;
|
||
|
|
||
|
this.hasLoot = (this.charItemManager.getInventoryCount() > 0) ? true : false;
|
||
|
|
||
|
} catch (Exception e) {
|
||
|
Logger.error(e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void respawn() {
|
||
|
//Commenting out Mob ID rotation.
|
||
|
|
||
|
this.despawned = false;
|
||
|
this.playerAgroMap.clear();
|
||
|
this.setCombatTarget(null);
|
||
|
this.setHealth(this.healthMax);
|
||
|
this.stamina.set(this.staminaMax);
|
||
|
this.mana.set(this.manaMax);
|
||
|
this.combat = false;
|
||
|
this.walkMode = true;
|
||
|
this.combatTarget = null;
|
||
|
this.isAlive.set(true);
|
||
|
|
||
|
if (!this.isSiege)
|
||
|
this.lastBindLoc = Mob.GetSpawnRadiusLocation(this);
|
||
|
else
|
||
|
this.lastBindLoc = this.bindLoc;
|
||
|
this.bindLoc = this.lastBindLoc;
|
||
|
this.setLoc(this.lastBindLoc);
|
||
|
this.stopMovement(this.lastBindLoc);
|
||
|
this.initializeStaticEffects();
|
||
|
this.recalculateStats();
|
||
|
|
||
|
this.setHealth(this.healthMax);
|
||
|
|
||
|
if (!this.isSiege && !this.isPlayerGuard && contract == null)
|
||
|
loadInventory();
|
||
|
|
||
|
// LoadJob.getInstance();
|
||
|
// LoadJob.forceLoad(this);
|
||
|
}
|
||
|
|
||
|
public void despawn() {
|
||
|
|
||
|
this.despawned = true;
|
||
|
|
||
|
//WorldServer.removeObject(this);
|
||
|
WorldGrid.RemoveWorldObject(this);
|
||
|
this.charItemManager.clearInventory();
|
||
|
this.despawnTime = System.currentTimeMillis();
|
||
|
// this.setLoc(Vector3fImmutable.ZERO);
|
||
|
}
|
||
|
|
||
|
//Sets the relative position to a parent zone
|
||
|
public void setRelPos(Zone zone, float locX, float locY, float locZ) {
|
||
|
|
||
|
//update mob zone map
|
||
|
|
||
|
if (this.parentZone != null)
|
||
|
this.parentZone.zoneMobSet.remove(this);
|
||
|
|
||
|
zone.zoneMobSet.add(this);
|
||
|
|
||
|
this.statLat = locX;
|
||
|
this.statAlt = locY;
|
||
|
this.statLon = locZ;
|
||
|
this.parentZone = zone;
|
||
|
this.setBindLoc(new Vector3fImmutable(this.statLat + zone.absX, this.statAlt + zone.absY, this.statLon + zone.absZ));
|
||
|
}
|
||
|
|
||
|
public boolean canRespawn(){
|
||
|
return System.currentTimeMillis() > this.despawnTime + 4000;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean canBeLooted() {
|
||
|
return !this.isAlive();
|
||
|
}
|
||
|
|
||
|
public int getTypeMasks() {
|
||
|
|
||
|
if (this.mobBase == null)
|
||
|
return 0;
|
||
|
|
||
|
return this.mobBase.getTypeMasks();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clears and sets the inventory of the Mob. Must be called every time the
|
||
|
* mob is spawned or respawned.
|
||
|
*/
|
||
|
private void loadInventory() {
|
||
|
|
||
|
if (!MBServerStatics.ENABLE_MOB_LOOT)
|
||
|
return;
|
||
|
|
||
|
this.charItemManager.clearInventory();
|
||
|
this.charItemManager.clearEquip();
|
||
|
|
||
|
if (isPlayerGuard)
|
||
|
return;
|
||
|
|
||
|
int gold = Mob.randomGoldAmount(this);
|
||
|
|
||
|
if (gold > 0 && this.getLootTable() != 0) {
|
||
|
addGoldToInventory(gold);
|
||
|
}
|
||
|
|
||
|
//add random loot to mob
|
||
|
ArrayList<MobLoot> alml = LootTable.getMobLoot(this, this.getLevel(), this.getLootTable(), false); //add hotzone check in later
|
||
|
|
||
|
for (MobLoot ml : alml) {
|
||
|
this.charItemManager.addItemToInventory(ml);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//add special loot to mob
|
||
|
}
|
||
|
|
||
|
private int getLootTable() {
|
||
|
|
||
|
if (this.mobBase == null)
|
||
|
return 0;
|
||
|
|
||
|
return this.mobBase.getLootTable();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the quantity of gold in the inventory. Calling this multiple times
|
||
|
* will overwrite the gold amount.
|
||
|
*
|
||
|
* @param quantity Quantity of gold.
|
||
|
*/
|
||
|
private void addGoldToInventory(int quantity) {
|
||
|
MobLoot gold = new MobLoot(this, quantity);
|
||
|
this.charItemManager.addItemToInventory(gold);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generate a random quantity of gold for this mob.
|
||
|
*
|
||
|
* @return Quantity of gold
|
||
|
*/
|
||
|
public static int randomGoldAmount( Mob mob) {
|
||
|
|
||
|
// percentage chance to drop gold
|
||
|
|
||
|
//R8 mobs have 100% gold drop.
|
||
|
if (mob.getLevel() < 80)
|
||
|
if ((ThreadLocalRandom.current().nextDouble() * 100d) > MBServerStatics.GOLD_DROP_PERCENTAGE_CHANCE)
|
||
|
return 0;
|
||
|
|
||
|
|
||
|
int level = (int) mob.getLevel();
|
||
|
level = (level < 0) ? 0 : level;
|
||
|
level = (level > 50) ? 50 : level;
|
||
|
|
||
|
double minGold;
|
||
|
double maxGold;
|
||
|
|
||
|
if (mob.mobBase != null) {
|
||
|
minGold = mob.mobBase.getMinGold();
|
||
|
maxGold = mob.mobBase.getMaxGold();
|
||
|
} else {
|
||
|
minGold = MBServerStatics.GOLD_DROP_MINIMUM_PER_MOB_LEVEL[level];
|
||
|
maxGold = MBServerStatics.GOLD_DROP_MAXIMUM_PER_MOB_LEVEL[level];
|
||
|
}
|
||
|
|
||
|
double gold = (ThreadLocalRandom.current().nextDouble() * (maxGold - minGold) + minGold);
|
||
|
|
||
|
|
||
|
//server specific gold multiplier
|
||
|
double goldMod = MBServerStatics.GOLD_RATE_MOD;
|
||
|
gold *= goldMod;
|
||
|
|
||
|
//modify for hotzone
|
||
|
|
||
|
if (ZoneManager.inHotZone(mob.getLoc()))
|
||
|
gold *= MBServerStatics.HOT_GOLD_RATE_MOD;
|
||
|
|
||
|
gold *= MBServerStatics.GOLD_RATE_MOD;
|
||
|
|
||
|
return (int) gold;
|
||
|
}
|
||
|
|
||
|
public static Mob createMob(int loadID, Vector3fImmutable spawn, Guild guild, boolean isMob, Zone parent,Building building, int contractID) {
|
||
|
|
||
|
Mob mobWithoutID = new Mob("", "", (short) 0, (short) 0, (short) 0, (short) 0,
|
||
|
(short) 0, (short) 1, 0, false, false, false, spawn, spawn, Vector3fImmutable.ZERO,
|
||
|
(short) 1, (short) 1, (short) 1, guild, (byte) 0, loadID, isMob, parent,building,contractID);
|
||
|
|
||
|
if (parent != null) {
|
||
|
mobWithoutID.setRelPos(parent, spawn.x - parent.absX, spawn.y - parent.absY, spawn.z - parent.absZ);
|
||
|
}
|
||
|
|
||
|
|
||
|
if (mobWithoutID.mobBase == null) {
|
||
|
return null;
|
||
|
}
|
||
|
Mob mob;
|
||
|
try {
|
||
|
mob = DbManager.MobQueries.ADD_MOB(mobWithoutID, isMob);
|
||
|
mob.setObjectTypeMask(MBServerStatics.MASK_MOB | mob.getTypeMasks());
|
||
|
mob.setMob();
|
||
|
mob.setParentZone(parent);
|
||
|
} catch (Exception e) {
|
||
|
Logger.error("SQLException:" + e.getMessage());
|
||
|
mob = null;
|
||
|
}
|
||
|
return mob;
|
||
|
}
|
||
|
|
||
|
public static Mob createPet( int loadID, Guild guild, Zone parent, PlayerCharacter owner, short level) {
|
||
|
MobBase mobBase = MobBase.getMobBase(loadID);
|
||
|
Mob mob = null;
|
||
|
if (mobBase == null || owner == null) {
|
||
|
return null;
|
||
|
}
|
||
|
createLock.writeLock().lock();
|
||
|
level += 20;
|
||
|
try {
|
||
|
mob = new Mob( mobBase, guild, parent, level, owner, 0);
|
||
|
if (mob.mobBase == null) {
|
||
|
return null;
|
||
|
}
|
||
|
mob.runAfterLoad();
|
||
|
|
||
|
Vector3fImmutable loc = owner.getLoc();
|
||
|
if (parent != null) {
|
||
|
mob.setRelPos(parent, loc.x - parent.absX, loc.y - parent.absY, loc.z - parent.absZ);
|
||
|
}
|
||
|
DbManager.addToCache(mob);
|
||
|
mob.setPet(owner, true);
|
||
|
mob.setWalkMode(false);
|
||
|
mob.state = STATE.Awake;
|
||
|
|
||
|
} catch (Exception e) {
|
||
|
Logger.error(e);
|
||
|
} finally {
|
||
|
createLock.writeLock().unlock();
|
||
|
}
|
||
|
|
||
|
return mob;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
public static int nextStaticID() {
|
||
|
int id = Mob.staticID;
|
||
|
Mob.staticID++;
|
||
|
return id;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Database
|
||
|
*/
|
||
|
|
||
|
|
||
|
public static Mob getMob(int id) {
|
||
|
|
||
|
if (id == 0)
|
||
|
return null;
|
||
|
|
||
|
Mob mob = (Mob) DbManager.getFromCache(GameObjectType.Mob, id);
|
||
|
if (mob != null)
|
||
|
return mob;
|
||
|
return DbManager.MobQueries.GET_MOB(id);
|
||
|
}
|
||
|
|
||
|
public static Mob getFromCache(int id) {
|
||
|
|
||
|
|
||
|
return (Mob) DbManager.getFromCache(GameObjectType.Mob, id);
|
||
|
}
|
||
|
|
||
|
public static Mob getFromCacheDBID(int id) {
|
||
|
if (Mob.mobMapByDBID.containsKey(id)) {
|
||
|
return Mob.mobMapByDBID.get(id);
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void updateDatabase() {
|
||
|
// DbManager.MobQueries.updateDatabase(this);
|
||
|
}
|
||
|
|
||
|
public int removeFromDatabase() {
|
||
|
return DbManager.MobQueries.DELETE_MOB(this);
|
||
|
}
|
||
|
|
||
|
public void refresh() {
|
||
|
if (this.isAlive())
|
||
|
WorldGrid.updateObject(this);
|
||
|
}
|
||
|
|
||
|
public void recalculateStats() {
|
||
|
|
||
|
try {
|
||
|
calculateModifiedStats();
|
||
|
} catch (Exception e) {
|
||
|
Logger.error(e.getMessage());
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
calculateAtrDefenseDamage();
|
||
|
} catch (Exception e) {
|
||
|
Logger.error( this.getMobBaseID() + " /" + e.getMessage());
|
||
|
}
|
||
|
try {
|
||
|
calculateMaxHealthManaStamina();
|
||
|
} catch (Exception e) {
|
||
|
Logger.error( e.getMessage());
|
||
|
}
|
||
|
|
||
|
Resists.calculateResists(this);
|
||
|
}
|
||
|
|
||
|
public void calculateMaxHealthManaStamina() {
|
||
|
float h = 1f;
|
||
|
float m = 0f;
|
||
|
float s = 0f;
|
||
|
|
||
|
h = this.mobBase.getHealthMax();
|
||
|
m = this.statSpiCurrent;
|
||
|
s = this.statConCurrent;
|
||
|
|
||
|
// Apply any bonuses from runes and effects
|
||
|
if (this.bonuses != null) {
|
||
|
h += this.bonuses.getFloat(ModType.HealthFull, SourceType.None);
|
||
|
m += this.bonuses.getFloat(ModType.ManaFull,SourceType.None);
|
||
|
s += this.bonuses.getFloat(ModType.StaminaFull, SourceType.None);
|
||
|
|
||
|
//apply effects percent modifiers. DO THIS LAST!
|
||
|
h *= (1 + this.bonuses.getFloatPercentAll(ModType.HealthFull,SourceType.None));
|
||
|
m *= (1 + this.bonuses.getFloatPercentAll(ModType.ManaFull,SourceType.None));
|
||
|
s *= (1 + this.bonuses.getFloatPercentAll(ModType.StaminaFull,SourceType.None));
|
||
|
}
|
||
|
|
||
|
// Set max health, mana and stamina
|
||
|
if (h > 0)
|
||
|
this.healthMax = h;
|
||
|
else
|
||
|
this.healthMax = 1;
|
||
|
|
||
|
if (m > -1)
|
||
|
this.manaMax = m;
|
||
|
else
|
||
|
this.manaMax = 0;
|
||
|
|
||
|
if (s > -1)
|
||
|
this.staminaMax = s;
|
||
|
else
|
||
|
this.staminaMax = 0;
|
||
|
|
||
|
// Update health, mana and stamina if needed
|
||
|
if (this.getHealth() > this.healthMax)
|
||
|
this.setHealth(this.healthMax);
|
||
|
|
||
|
if (this.mana.get() > this.manaMax)
|
||
|
this.mana.set(this.manaMax);
|
||
|
|
||
|
if (this.stamina.get() > this.staminaMax)
|
||
|
this.stamina.set(staminaMax);
|
||
|
|
||
|
}
|
||
|
|
||
|
public void calculateAtrDefenseDamage() {
|
||
|
|
||
|
if (this.charItemManager == null || this.equip == null) {
|
||
|
Logger.error("Player " + currentID + " missing skills or equipment");
|
||
|
defaultAtrAndDamage(true);
|
||
|
defaultAtrAndDamage(false);
|
||
|
this.defenseRating = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
calculateAtrDamageForWeapon(
|
||
|
this.equip.get(MBServerStatics.SLOT_MAINHAND), true, this.equip.get(MBServerStatics.SLOT_OFFHAND));
|
||
|
} catch (Exception e) {
|
||
|
|
||
|
this.atrHandOne = (short) this.mobBase.getAttackRating();
|
||
|
this.minDamageHandOne = (short) this.mobBase.getMinDmg();
|
||
|
this.maxDamageHandOne = (short) this.mobBase.getMaxDmg();
|
||
|
this.rangeHandOne = 6.5f;
|
||
|
this.speedHandOne = 20;
|
||
|
Logger.info("Mobbase ID " + this.getMobBaseID() + " returned an error. setting to default ATR and Damage." + e.getMessage());
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
calculateAtrDamageForWeapon(this.equip.get(MBServerStatics.SLOT_OFFHAND), false, this.equip.get(MBServerStatics.SLOT_MAINHAND));
|
||
|
|
||
|
} catch (Exception e) {
|
||
|
|
||
|
this.atrHandTwo = (short) this.mobBase.getAttackRating();
|
||
|
this.minDamageHandTwo = (short) this.mobBase.getMinDmg();
|
||
|
this.maxDamageHandTwo = (short) this.mobBase.getMaxDmg();
|
||
|
this.rangeHandTwo = 6.5f;
|
||
|
this.speedHandTwo = 20;
|
||
|
Logger.info( "Mobbase ID " + this.getMobBaseID() + " returned an error. setting to default ATR and Damage." + e.getMessage());
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
float defense = this.mobBase.getDefenseRating();
|
||
|
defense += getShieldDefense(equip.get(MBServerStatics.SLOT_OFFHAND));
|
||
|
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_HELMET));
|
||
|
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_CHEST));
|
||
|
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_ARMS));
|
||
|
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_GLOVES));
|
||
|
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_LEGGINGS));
|
||
|
defense += getArmorDefense(equip.get(MBServerStatics.SLOT_FEET));
|
||
|
defense += getWeaponDefense(equip);
|
||
|
|
||
|
if (this.bonuses != null) {
|
||
|
// add any bonuses
|
||
|
defense += (short) this.bonuses.getFloat(ModType.DCV, SourceType.None);
|
||
|
|
||
|
// Finally multiply any percent modifiers. DO THIS LAST!
|
||
|
float pos_Bonus = 1 + this.bonuses.getFloatPercentPositive(ModType.DCV, SourceType.None);
|
||
|
|
||
|
|
||
|
|
||
|
defense = (short) (defense * pos_Bonus);
|
||
|
|
||
|
//Lucky rune applies next
|
||
|
|
||
|
float neg_Bonus = this.bonuses.getFloatPercentNegative(ModType.DCV, SourceType.None);
|
||
|
defense = (short) (defense *(1 + neg_Bonus));
|
||
|
|
||
|
|
||
|
|
||
|
} else {
|
||
|
// TODO add error log here
|
||
|
Logger.error( "Error: missing bonuses");
|
||
|
}
|
||
|
|
||
|
defense = (defense < 1) ? 1 : defense;
|
||
|
this.defenseRating = (short) (defense + 0.5f);
|
||
|
} catch (Exception e) {
|
||
|
Logger.info("Mobbase ID " + this.getMobBaseID() + " returned an error. Setting to Default Defense." + e.getMessage());
|
||
|
this.defenseRating = (short) this.mobBase.getDefense();
|
||
|
}
|
||
|
// calculate defense for equipment
|
||
|
}
|
||
|
|
||
|
private float getWeaponDefense(HashMap<Integer, MobEquipment> equipped) {
|
||
|
MobEquipment weapon = equipped.get(MBServerStatics.SLOT_MAINHAND);
|
||
|
ItemBase wb = null;
|
||
|
CharacterSkill skill, mastery;
|
||
|
float val = 0;
|
||
|
boolean unarmed = false;
|
||
|
if (weapon == null) {
|
||
|
weapon = equipped.get(MBServerStatics.SLOT_OFFHAND);
|
||
|
|
||
|
if (weapon == null)
|
||
|
unarmed = true;
|
||
|
else
|
||
|
wb = weapon.getItemBase();
|
||
|
|
||
|
} else
|
||
|
wb = weapon.getItemBase();
|
||
|
|
||
|
if (wb == null)
|
||
|
unarmed = true;
|
||
|
|
||
|
if (unarmed) {
|
||
|
skill = null;
|
||
|
mastery = null;
|
||
|
} else {
|
||
|
skill = this.skills.get(wb.getSkillRequired());
|
||
|
mastery = this.skills.get(wb.getMastery());
|
||
|
}
|
||
|
|
||
|
if (skill != null)
|
||
|
val += (int) skill.getModifiedAmount() / 2f;
|
||
|
|
||
|
if (mastery != null)
|
||
|
val += (int) mastery.getModifiedAmount() / 2f;
|
||
|
|
||
|
return val;
|
||
|
}
|
||
|
|
||
|
private float getShieldDefense(MobEquipment shield) {
|
||
|
|
||
|
if (shield == null)
|
||
|
return 0;
|
||
|
|
||
|
ItemBase ab = shield.getItemBase();
|
||
|
|
||
|
if (ab == null || !ab.isShield())
|
||
|
return 0;
|
||
|
|
||
|
CharacterSkill blockSkill = this.skills.get("Block");
|
||
|
float skillMod;
|
||
|
|
||
|
if (blockSkill == null) {
|
||
|
skillMod = CharacterSkill.getQuickMastery(this, "Block");
|
||
|
|
||
|
if (skillMod == 0f)
|
||
|
return 0;
|
||
|
|
||
|
} else
|
||
|
skillMod = blockSkill.getModifiedAmount();
|
||
|
|
||
|
// // Only fighters and healers can block
|
||
|
// if (this.baseClass != null && (this.baseClass.getUUID() == 2500 || this.baseClass.getUUID() == 2501))
|
||
|
// this.bonuses.setBool("Block", true);
|
||
|
|
||
|
float def = ab.getDefense();
|
||
|
//apply item defense bonuses
|
||
|
// float val = ((float)ab.getDefense()) * (1 + (skillMod / 100));
|
||
|
return (def * (1 + ((int) skillMod / 100f)));
|
||
|
}
|
||
|
|
||
|
private float getArmorDefense(MobEquipment armor) {
|
||
|
|
||
|
if (armor == null)
|
||
|
return 0;
|
||
|
|
||
|
ItemBase ib = armor.getItemBase();
|
||
|
|
||
|
if (ib == null)
|
||
|
return 0;
|
||
|
|
||
|
if (!ib.getType().equals(ItemType.ARMOR))
|
||
|
return 0;
|
||
|
|
||
|
if (ib.getSkillRequired().isEmpty())
|
||
|
return ib.getDefense();
|
||
|
|
||
|
CharacterSkill armorSkill = this.skills.get(ib.getSkillRequired());
|
||
|
|
||
|
if (armorSkill == null)
|
||
|
return ib.getDefense();
|
||
|
|
||
|
float def = ib.getDefense();
|
||
|
|
||
|
//apply item defense bonuses
|
||
|
|
||
|
return (def * (1 + ((int) armorSkill.getModifiedAmount() / 50f)));
|
||
|
}
|
||
|
|
||
|
private void calculateAtrDamageForWeapon(MobEquipment weapon, boolean mainHand, MobEquipment otherHand) {
|
||
|
|
||
|
int baseStrength = 0;
|
||
|
|
||
|
float skillPercentage, masteryPercentage;
|
||
|
float mastDam;
|
||
|
|
||
|
// make sure weapon exists
|
||
|
boolean noWeapon = false;
|
||
|
ItemBase wb = null;
|
||
|
|
||
|
if (weapon == null)
|
||
|
noWeapon = true;
|
||
|
else {
|
||
|
|
||
|
ItemBase ib = weapon.getItemBase();
|
||
|
|
||
|
if (ib == null)
|
||
|
noWeapon = true;
|
||
|
else {
|
||
|
|
||
|
if (ib.getType().equals(ItemType.WEAPON) == false) {
|
||
|
defaultAtrAndDamage(mainHand);
|
||
|
return;
|
||
|
} else
|
||
|
wb = ib;
|
||
|
}
|
||
|
}
|
||
|
float min, max;
|
||
|
float speed = 20f;
|
||
|
boolean strBased = false;
|
||
|
|
||
|
// get skill percentages and min and max damage for weapons
|
||
|
|
||
|
if (noWeapon) {
|
||
|
|
||
|
if (mainHand)
|
||
|
this.rangeHandOne = this.mobBase.getAttackRange();
|
||
|
else
|
||
|
this.rangeHandTwo = -1; // set to do not attack
|
||
|
|
||
|
skillPercentage = getModifiedAmount(this.skills.get("Unarmed Combat"));
|
||
|
masteryPercentage = getModifiedAmount(this.skills.get("Unarmed Combat Mastery"));
|
||
|
|
||
|
if (masteryPercentage == 0f)
|
||
|
mastDam = CharacterSkill.getQuickMastery(this, "Unarmed Combat Mastery");
|
||
|
else
|
||
|
mastDam = masteryPercentage;
|
||
|
|
||
|
// TODO Correct these
|
||
|
min = this.mobBase.getMinDmg();
|
||
|
max = this.mobBase.getMaxDmg();
|
||
|
} else {
|
||
|
|
||
|
if (mainHand)
|
||
|
this.rangeHandOne = weapon.getItemBase().getRange() * (1 + (baseStrength / 600));
|
||
|
else
|
||
|
this.rangeHandTwo = weapon.getItemBase().getRange() * (1 + (baseStrength / 600));
|
||
|
|
||
|
skillPercentage = getModifiedAmount(this.skills.get(wb.getSkillRequired()));
|
||
|
masteryPercentage = getModifiedAmount(this.skills.get(wb.getMastery()));
|
||
|
|
||
|
if (masteryPercentage == 0f)
|
||
|
mastDam = 0f;
|
||
|
else
|
||
|
mastDam = masteryPercentage;
|
||
|
|
||
|
min = (float) wb.getMinDamage();
|
||
|
max = (float) wb.getMaxDamage();
|
||
|
strBased = wb.isStrBased();
|
||
|
}
|
||
|
|
||
|
// calculate atr
|
||
|
float atr = this.mobBase.getAttackRating();
|
||
|
|
||
|
atr += ((int) skillPercentage * 4f); //<-round down skill% -
|
||
|
atr += ((int) masteryPercentage * 3f);
|
||
|
|
||
|
if (this.statStrCurrent > this.statDexCurrent)
|
||
|
atr += statStrCurrent / 2;
|
||
|
else
|
||
|
atr += statDexCurrent / 2;
|
||
|
|
||
|
// add in any bonuses to atr
|
||
|
if (this.bonuses != null) {
|
||
|
// Add any base bonuses
|
||
|
atr += this.bonuses.getFloat(ModType.OCV, SourceType.None);
|
||
|
|
||
|
// Finally use any multipliers. DO THIS LAST!
|
||
|
float pos_Bonus = 1 + this.bonuses.getFloatPercentPositive(ModType.OCV, SourceType.None);
|
||
|
|
||
|
|
||
|
atr *= pos_Bonus;
|
||
|
|
||
|
// next precise
|
||
|
|
||
|
// atr *= (1 + ((float) this.bonuses.getShort("rune.Attack") / 100));
|
||
|
|
||
|
//and negative percent modifiers
|
||
|
//TODO DO DEBUFFS AFTER?? wILL TEst when finished
|
||
|
float neg_Bonus = this.bonuses.getFloatPercentNegative(ModType.OCV, SourceType.None);
|
||
|
|
||
|
|
||
|
|
||
|
atr *= (1 + neg_Bonus);
|
||
|
}
|
||
|
|
||
|
atr = (atr < 1) ? 1 : atr;
|
||
|
|
||
|
// set atr
|
||
|
if (mainHand)
|
||
|
this.atrHandOne = (short) (atr + 0.5f);
|
||
|
else
|
||
|
this.atrHandTwo = (short) (atr + 0.5f);
|
||
|
|
||
|
//calculate speed
|
||
|
|
||
|
if (wb != null)
|
||
|
speed = wb.getSpeed();
|
||
|
else
|
||
|
speed = 20f; //unarmed attack speed
|
||
|
|
||
|
if (this.bonuses != null && this.bonuses.getFloat(ModType.AttackDelay, SourceType.None) != 0f) //add effects speed bonus
|
||
|
speed *= (1 + this.bonuses.getFloatPercentAll(ModType.AttackDelay, SourceType.None));
|
||
|
|
||
|
if (speed < 10)
|
||
|
speed = 10;
|
||
|
|
||
|
//add min/max damage bonuses for weapon **REMOVED
|
||
|
|
||
|
//if duel wielding, cut damage by 30%
|
||
|
// calculate damage
|
||
|
float minDamage;
|
||
|
float maxDamage;
|
||
|
float pri = (strBased) ? (float) this.statStrCurrent : (float) this.statDexCurrent;
|
||
|
float sec = (strBased) ? (float) this.statDexCurrent : (float) this.statStrCurrent;
|
||
|
|
||
|
minDamage = (float) (min * ((0.0315f * Math.pow(pri, 0.75f)) + (0.042f * Math.pow(sec, 0.75f)) + (0.01f * ((int) skillPercentage + (int) mastDam))));
|
||
|
maxDamage = (float) (max * ((0.0785f * Math.pow(pri, 0.75f)) + (0.016f * Math.pow(sec, 0.75f)) + (0.0075f * ((int) skillPercentage + (int) mastDam))));
|
||
|
|
||
|
minDamage = (float) ((int) (minDamage + 0.5f)); //round to nearest decimal
|
||
|
maxDamage = (float) ((int) (maxDamage + 0.5f)); //round to nearest decimal
|
||
|
// Logger.info("MobCalculateDamage", "Mob with ID "+ this.getObjectUUID() + " and MOBBASE with ID " + this.getMobBaseID() + " returned " + minDamage + "/" + maxDamage + " modified Damage.");
|
||
|
|
||
|
//add Base damage last.
|
||
|
float minDamageMod = this.mobBase.getDamageMin();
|
||
|
float maxDamageMod = this.mobBase.getDamageMax();
|
||
|
|
||
|
minDamage += minDamageMod;
|
||
|
maxDamage += maxDamageMod;
|
||
|
|
||
|
// add in any bonuses to damage
|
||
|
if (this.bonuses != null) {
|
||
|
// Add any base bonuses
|
||
|
minDamage += this.bonuses.getFloat(ModType.MinDamage, SourceType.None);
|
||
|
maxDamage += this.bonuses.getFloat(ModType.MaxDamage, SourceType.None);
|
||
|
|
||
|
// Finally use any multipliers. DO THIS LAST!
|
||
|
minDamage *= (1 + this.bonuses.getFloatPercentAll(ModType.MinDamage, SourceType.None));
|
||
|
maxDamage *= (1 + this.bonuses.getFloatPercentAll(ModType.MaxDamage, SourceType.None));
|
||
|
}
|
||
|
|
||
|
// set damages
|
||
|
if (mainHand) {
|
||
|
this.minDamageHandOne = (short) minDamage;
|
||
|
this.maxDamageHandOne = (short) maxDamage;
|
||
|
this.speedHandOne = 30;
|
||
|
} else {
|
||
|
this.minDamageHandTwo = (short) minDamage;
|
||
|
this.maxDamageHandTwo = (short) maxDamage;
|
||
|
this.speedHandTwo = 30;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static float getModifiedAmount(CharacterSkill skill) {
|
||
|
|
||
|
if (skill == null)
|
||
|
return 0f;
|
||
|
|
||
|
return skill.getModifiedAmount();
|
||
|
}
|
||
|
|
||
|
private void defaultAtrAndDamage(boolean mainHand) {
|
||
|
|
||
|
if (mainHand) {
|
||
|
this.atrHandOne = 0;
|
||
|
this.minDamageHandOne = 0;
|
||
|
this.maxDamageHandOne = 0;
|
||
|
this.rangeHandOne = -1;
|
||
|
this.speedHandOne = 20;
|
||
|
} else {
|
||
|
this.atrHandTwo = 0;
|
||
|
this.minDamageHandTwo = 0;
|
||
|
this.maxDamageHandTwo = 0;
|
||
|
this.rangeHandTwo = -1;
|
||
|
this.speedHandTwo = 20;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static int getBuildingSlot(Mob mob){
|
||
|
int slot = -1;
|
||
|
|
||
|
if (mob.building == null)
|
||
|
return -1;
|
||
|
|
||
|
|
||
|
|
||
|
BuildingModelBase buildingModel = BuildingModelBase.getModelBase(mob.building.getMeshUUID());
|
||
|
|
||
|
if (buildingModel == null)
|
||
|
return -1;
|
||
|
|
||
|
|
||
|
if (mob.building.getHirelings().containsKey(mob))
|
||
|
slot = (mob.building.getHirelings().get(mob));
|
||
|
|
||
|
|
||
|
if (buildingModel.getNPCLocation(slot) == null)
|
||
|
return -1;
|
||
|
|
||
|
|
||
|
return slot;
|
||
|
}
|
||
|
|
||
|
public void setInBuildingLoc(Building inBuilding, AbstractCharacter ac) {
|
||
|
|
||
|
Mob mob = null;
|
||
|
|
||
|
NPC npc = null;
|
||
|
|
||
|
|
||
|
if (ac.getObjectType().equals(GameObjectType.Mob))
|
||
|
mob = (Mob)ac;
|
||
|
|
||
|
else if (ac.getObjectType().equals(GameObjectType.NPC))
|
||
|
npc = (NPC)ac;
|
||
|
|
||
|
// *** Refactor : Need to take a look at this, make sure
|
||
|
// npc's are loaded in correct spots.
|
||
|
|
||
|
BuildingModelBase buildingModel = BuildingModelBase.getModelBase(inBuilding.getMeshUUID());
|
||
|
|
||
|
Vector3fImmutable slotLocation = Vector3fImmutable.ZERO;
|
||
|
|
||
|
if (buildingModel != null){
|
||
|
|
||
|
|
||
|
int putSlot = -1;
|
||
|
BuildingLocation buildingLocation = null;
|
||
|
|
||
|
//-1 slot means no slot available in building.
|
||
|
|
||
|
if (npc != null){
|
||
|
if (npc.getSiegeMinionMap().containsKey(this))
|
||
|
putSlot = npc.getSiegeMinionMap().get(this);
|
||
|
}else if (mob != null)
|
||
|
if (mob.getSiegeMinionMap().containsKey(this))
|
||
|
putSlot = mob.getSiegeMinionMap().get(this);
|
||
|
|
||
|
int count = 0;
|
||
|
|
||
|
for (BuildingLocation slotLoc: buildingModel.getLocations())
|
||
|
if (slotLoc.getType() == 6)
|
||
|
count++;
|
||
|
|
||
|
|
||
|
buildingLocation = buildingModel.getSlotLocation((count) - putSlot);
|
||
|
|
||
|
if (buildingLocation != null){
|
||
|
slotLocation = buildingLocation.getLoc();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
this.inBuildingLoc = slotLocation;
|
||
|
|
||
|
}
|
||
|
|
||
|
public Vector3fImmutable getInBuildingLoc() {
|
||
|
return inBuildingLoc;
|
||
|
}
|
||
|
|
||
|
public ItemBase getWeaponItemBase(boolean mainHand) {
|
||
|
|
||
|
if (this.equipmentSetID != 0){
|
||
|
|
||
|
if (equip != null) {
|
||
|
MobEquipment me = null;
|
||
|
|
||
|
if (mainHand)
|
||
|
me = equip.get(1); //mainHand
|
||
|
else
|
||
|
me = equip.get(2); //offHand
|
||
|
|
||
|
if (me != null) {
|
||
|
|
||
|
ItemBase ib = me.getItemBase();
|
||
|
|
||
|
if (ib != null)
|
||
|
return ib;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
MobBase mb = this.mobBase;
|
||
|
|
||
|
if (mb != null) {
|
||
|
|
||
|
if (equip != null) {
|
||
|
|
||
|
MobEquipment me = null;
|
||
|
|
||
|
if (mainHand)
|
||
|
me = equip.get(1); //mainHand
|
||
|
else
|
||
|
me = equip.get(2); //offHand
|
||
|
|
||
|
if (me != null) {
|
||
|
|
||
|
ItemBase ib = me.getItemBase();
|
||
|
|
||
|
if (ib != null)
|
||
|
return ib;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void runAfterLoad() {
|
||
|
|
||
|
try{
|
||
|
if (this.equipmentSetID != 0)
|
||
|
this.equip = MobBase.loadEquipmentSet(this.equipmentSetID);
|
||
|
else
|
||
|
this.equip = new HashMap<>();
|
||
|
|
||
|
} catch(Exception e){
|
||
|
Logger.error( e.getMessage());
|
||
|
}
|
||
|
|
||
|
if (this.equip == null) {
|
||
|
Logger.error("Null equipset returned for uuid " + currentID);
|
||
|
this.equip = new HashMap<>(0);
|
||
|
}
|
||
|
|
||
|
try{
|
||
|
this.initializeStaticEffects();
|
||
|
|
||
|
try {
|
||
|
this.initializeSkills();
|
||
|
} catch (Exception e) {
|
||
|
Logger.error( e.getMessage());
|
||
|
}
|
||
|
|
||
|
recalculateStats();
|
||
|
this.setHealth(this.healthMax);
|
||
|
|
||
|
// Set bounds for this mobile
|
||
|
Bounds mobBounds = Bounds.borrow();
|
||
|
mobBounds.setBounds(this.getLoc());
|
||
|
this.setBounds(mobBounds);
|
||
|
|
||
|
} catch (Exception e){
|
||
|
Logger.error(e.getMessage());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected ConcurrentHashMap<Integer, CharacterPower> initializePowers() {
|
||
|
return new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
|
||
|
}
|
||
|
|
||
|
public boolean canSee(PlayerCharacter target) {
|
||
|
return this.mobBase.getSeeInvis() >= target.getHidden();
|
||
|
}
|
||
|
|
||
|
public int getBuildingID() {
|
||
|
return buildingID;
|
||
|
}
|
||
|
|
||
|
public void setBuildingID(int buildingID) {
|
||
|
this.buildingID = buildingID;
|
||
|
}
|
||
|
|
||
|
public boolean isSiege() {
|
||
|
return isSiege;
|
||
|
}
|
||
|
|
||
|
public void setSiege(boolean isSiege) {
|
||
|
this.isSiege = isSiege;
|
||
|
}
|
||
|
|
||
|
public long getTimeToSpawnSiege() {
|
||
|
return timeToSpawnSiege;
|
||
|
}
|
||
|
|
||
|
public void setTimeToSpawnSiege(long timeToSpawnSiege) {
|
||
|
this.timeToSpawnSiege = timeToSpawnSiege;
|
||
|
}
|
||
|
|
||
|
public AbstractCharacter getNpcOwner() {
|
||
|
return npcOwner;
|
||
|
}
|
||
|
|
||
|
public void setNpcOwner(AbstractCharacter npcOwner) {
|
||
|
this.npcOwner = npcOwner;
|
||
|
}
|
||
|
|
||
|
public boolean isNecroPet() {
|
||
|
return this.mobBase.isNecroPet();
|
||
|
}
|
||
|
|
||
|
public static void HandleAssistedAggro(PlayerCharacter source, PlayerCharacter target) {
|
||
|
|
||
|
HashSet<AbstractWorldObject> mobsInRange = WorldGrid.getObjectsInRangePartial(source, MBServerStatics.AI_DROP_AGGRO_RANGE, MBServerStatics.MASK_MOB);
|
||
|
|
||
|
for (AbstractWorldObject awo : mobsInRange) {
|
||
|
Mob mob = (Mob) awo;
|
||
|
|
||
|
//Mob is not attacking anyone, skip.
|
||
|
if (mob.getCombatTarget() == null)
|
||
|
continue;
|
||
|
|
||
|
//Mob not attacking target's target, let's not be failmu and skip this target.
|
||
|
if (mob.getCombatTarget() != target)
|
||
|
continue;
|
||
|
|
||
|
//target is mob's combat target, LETS GO.
|
||
|
if (source.getHateValue() > target.getHateValue()) {
|
||
|
mob.setCombatTarget(source);
|
||
|
MobileFSM.setAggro(mob, source.getObjectUUID());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void handleDirectAggro(AbstractCharacter ac) {
|
||
|
|
||
|
if (ac.getObjectType().equals(GameObjectType.PlayerCharacter) == false)
|
||
|
return;
|
||
|
|
||
|
PlayerCharacter player = (PlayerCharacter)ac;
|
||
|
|
||
|
if (this.getCombatTarget() == null) {
|
||
|
MobileFSM.setAggro(this, player.getObjectUUID());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (player.getObjectUUID() == this.getCombatTarget().getObjectUUID())
|
||
|
return;
|
||
|
|
||
|
if (this.getCombatTarget().getObjectType() == GameObjectType.PlayerCharacter) {
|
||
|
|
||
|
if (ac.getHateValue() > ((PlayerCharacter) this.getCombatTarget()).getHateValue()) {
|
||
|
this.setCombatTarget(player);
|
||
|
MobileFSM.setAggro(this, player.getObjectUUID());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public boolean remove(Building building) {
|
||
|
|
||
|
// Remove npc from it's building
|
||
|
this.state = STATE.Disabled;
|
||
|
|
||
|
try {
|
||
|
this.clearEffects();
|
||
|
}catch(Exception e){
|
||
|
Logger.error(e.getMessage());
|
||
|
}
|
||
|
|
||
|
if (this.parentZone != null)
|
||
|
this.parentZone.zoneMobSet.remove(this);
|
||
|
|
||
|
if (building != null) {
|
||
|
building.getHirelings().remove(this);
|
||
|
this.removeMinions();
|
||
|
}
|
||
|
|
||
|
// Delete npc from database
|
||
|
|
||
|
if (DbManager.MobQueries.DELETE_MOB(this) == 0)
|
||
|
return false;
|
||
|
|
||
|
// Remove npc from the simulation
|
||
|
|
||
|
this.removeFromCache();
|
||
|
DbManager.removeFromCache(this);
|
||
|
WorldGrid.RemoveWorldObject(this);
|
||
|
WorldGrid.removeObject(this);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public void removeMinions() {
|
||
|
|
||
|
for (Mob toRemove : this.siegeMinionMap.keySet()) {
|
||
|
|
||
|
toRemove.state = STATE.Disabled;
|
||
|
|
||
|
if (this.isMoving()){
|
||
|
|
||
|
this.stopMovement(this.getLoc());
|
||
|
this.state = STATE.Disabled;
|
||
|
|
||
|
if (toRemove.parentZone != null)
|
||
|
toRemove.parentZone.zoneMobSet.remove(toRemove);
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
toRemove.clearEffects();
|
||
|
} catch(Exception e){
|
||
|
Logger.error(e.getMessage());
|
||
|
}
|
||
|
|
||
|
if (toRemove.parentZone != null)
|
||
|
toRemove.parentZone.zoneMobSet.remove(toRemove);
|
||
|
|
||
|
WorldGrid.RemoveWorldObject(toRemove);
|
||
|
WorldGrid.removeObject(toRemove);
|
||
|
DbManager.removeFromCache(toRemove);
|
||
|
|
||
|
PlayerCharacter petOwner = toRemove.getOwner();
|
||
|
|
||
|
if (petOwner != null) {
|
||
|
|
||
|
petOwner.setPet(null);
|
||
|
toRemove.setOwner(null);
|
||
|
|
||
|
PetMsg petMsg = new PetMsg(5, null);
|
||
|
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg);
|
||
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void submitUpgradeJob(Mob mob) {
|
||
|
|
||
|
JobContainer jc;
|
||
|
|
||
|
if (mob.getUpgradeDateTime() == null) {
|
||
|
Logger.error("Failed to get Upgrade Date");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Submit upgrade job for future date or current instant
|
||
|
|
||
|
if (mob.getUpgradeDateTime().isAfter(DateTime.now()))
|
||
|
jc = JobScheduler.getInstance().scheduleJob(new UpgradeNPCJob(mob),
|
||
|
mob.getUpgradeDateTime().getMillis());
|
||
|
else
|
||
|
JobScheduler.getInstance().scheduleJob(new UpgradeNPCJob(mob), 0);
|
||
|
|
||
|
}
|
||
|
|
||
|
public void setRank(int newRank) {
|
||
|
|
||
|
DbManager.MobQueries.SET_PROPERTY(this, "mob_level", newRank);
|
||
|
this.level = (short) newRank;
|
||
|
|
||
|
}
|
||
|
|
||
|
public static int getUpgradeTime(Mob mob) {
|
||
|
|
||
|
if (mob.getRank() < 7)
|
||
|
return (mob.getRank() * 8);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
public static int getUpgradeCost(Mob mob) {
|
||
|
|
||
|
int upgradeCost;
|
||
|
|
||
|
upgradeCost = Integer.MAX_VALUE;
|
||
|
|
||
|
if (mob.getRank() < 7)
|
||
|
return (mob.getRank() * 100650) + 21450;
|
||
|
|
||
|
return upgradeCost;
|
||
|
}
|
||
|
|
||
|
public boolean isRanking() {
|
||
|
|
||
|
return this.upgradeDateTime != null;
|
||
|
}
|
||
|
|
||
|
public boolean isNoAggro() {
|
||
|
return noAggro;
|
||
|
}
|
||
|
|
||
|
public void setNoAggro(boolean noAggro) {
|
||
|
this.noAggro = noAggro;
|
||
|
}
|
||
|
|
||
|
public STATE getState() {
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
public void setState(STATE state) {
|
||
|
this.state = state;
|
||
|
}
|
||
|
|
||
|
public int getAggroTargetID() {
|
||
|
return aggroTargetID;
|
||
|
}
|
||
|
|
||
|
public void setAggroTargetID(int aggroTargetID) {
|
||
|
this.aggroTargetID = aggroTargetID;
|
||
|
}
|
||
|
|
||
|
public boolean isWalkingHome() {
|
||
|
return walkingHome;
|
||
|
}
|
||
|
|
||
|
public void setWalkingHome(boolean walkingHome) {
|
||
|
this.walkingHome = walkingHome;
|
||
|
}
|
||
|
|
||
|
public long getLastAttackTime() {
|
||
|
return lastAttackTime;
|
||
|
}
|
||
|
|
||
|
public void setLastAttackTime(long lastAttackTime) {
|
||
|
this.lastAttackTime = lastAttackTime;
|
||
|
}
|
||
|
|
||
|
public ConcurrentHashMap<Integer, Boolean> getPlayerAgroMap() {
|
||
|
return playerAgroMap;
|
||
|
}
|
||
|
|
||
|
public long getDeathTime() {
|
||
|
return deathTime;
|
||
|
}
|
||
|
|
||
|
public boolean isHasLoot() {
|
||
|
return hasLoot;
|
||
|
}
|
||
|
public void setDeathTime(long deathTime) {
|
||
|
this.deathTime = deathTime;
|
||
|
}
|
||
|
|
||
|
public DeferredPowerJob getWeaponPower() {
|
||
|
return weaponPower;
|
||
|
}
|
||
|
|
||
|
public void setWeaponPower(DeferredPowerJob weaponPower) {
|
||
|
this.weaponPower = weaponPower;
|
||
|
}
|
||
|
public ConcurrentHashMap<Mob, Integer> getSiegeMinionMap() {
|
||
|
return siegeMinionMap;
|
||
|
}
|
||
|
|
||
|
public Building getBuilding() {
|
||
|
return this.building;
|
||
|
}
|
||
|
|
||
|
public DateTime getUpgradeDateTime() {
|
||
|
|
||
|
lock.readLock().lock();
|
||
|
|
||
|
try {
|
||
|
return upgradeDateTime;
|
||
|
} finally {
|
||
|
lock.readLock().unlock();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public synchronized Mob createGuardMob(int loadID, Guild guild, Zone parent, Vector3fImmutable loc, short level, String pirateName) {
|
||
|
|
||
|
MobBase minionMobBase;
|
||
|
Mob mob;
|
||
|
int maxSlots = 1;
|
||
|
|
||
|
switch (this.getRank()){
|
||
|
case 1:
|
||
|
case 2:
|
||
|
maxSlots = 1;
|
||
|
break;
|
||
|
case 3:
|
||
|
maxSlots = 2;
|
||
|
break;
|
||
|
case 4:
|
||
|
case 5:
|
||
|
maxSlots = 3;
|
||
|
break;
|
||
|
case 6:
|
||
|
maxSlots = 4;
|
||
|
break;
|
||
|
case 7:
|
||
|
maxSlots = 5;
|
||
|
break;
|
||
|
default:
|
||
|
maxSlots = 1;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (siegeMinionMap.size() == maxSlots)
|
||
|
return null;
|
||
|
|
||
|
minionMobBase = this.mobBase;
|
||
|
|
||
|
if (minionMobBase == null)
|
||
|
return null;
|
||
|
|
||
|
mob = new Mob(minionMobBase, guild, parent, level,new Vector3fImmutable(1,1,1), 0,true);
|
||
|
|
||
|
mob.despawned = true;
|
||
|
|
||
|
mob.setLevel(level);
|
||
|
//grab equipment and name from minionbase.
|
||
|
if (this.contract != null){
|
||
|
MinionType minionType = MinionType.ContractToMinionMap.get(this.contract.getContractID());
|
||
|
if (minionType != null){
|
||
|
mob.equipmentSetID = minionType.getEquipSetID();
|
||
|
String rank = "";
|
||
|
|
||
|
if (this.getRank() < 3)
|
||
|
rank = MBServerStatics.JUNIOR;
|
||
|
else if (this.getRank() < 6)
|
||
|
rank = "";
|
||
|
else if (this.getRank() == 6)
|
||
|
rank = MBServerStatics.VETERAN;
|
||
|
else
|
||
|
rank = MBServerStatics.ELITE;
|
||
|
|
||
|
if (rank.isEmpty())
|
||
|
mob.nameOverride = pirateName + " " + minionType.getRace() + " " + minionType.getName();
|
||
|
else
|
||
|
mob.nameOverride = pirateName + " " + minionType.getRace() + " " + rank + " " + minionType.getName();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
if (parent != null)
|
||
|
mob.setRelPos(parent, loc.x - parent.absX, loc.y - parent.absY, loc.z - parent.absZ);
|
||
|
|
||
|
mob.setObjectTypeMask(MBServerStatics.MASK_MOB | mob.getTypeMasks());
|
||
|
|
||
|
// mob.setMob();
|
||
|
mob.isPlayerGuard = true;
|
||
|
mob.setParentZone(parent);
|
||
|
DbManager.addToCache(mob);
|
||
|
mob.runAfterLoad();
|
||
|
|
||
|
|
||
|
|
||
|
RuneBase guardRune = RuneBase.getRuneBase(252621);
|
||
|
|
||
|
for (MobBaseEffects mbe : guardRune.getEffectsList()) {
|
||
|
|
||
|
EffectsBase eb = PowersManager.getEffectByToken(mbe.getToken());
|
||
|
|
||
|
if (eb == null) {
|
||
|
Logger.info( "EffectsBase Null for Token " + mbe.getToken());
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//check to upgrade effects if needed.
|
||
|
if (mob.effects.containsKey(Integer.toString(eb.getUUID()))) {
|
||
|
if (mbe.getReqLvl() > (int) mob.level) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
Effect eff = mob.effects.get(Integer.toString(eb.getUUID()));
|
||
|
|
||
|
if (eff == null)
|
||
|
continue;
|
||
|
|
||
|
//Current effect is a higher rank, dont apply.
|
||
|
if (eff.getTrains() > mbe.getRank())
|
||
|
continue;
|
||
|
|
||
|
//new effect is of a higher rank. remove old effect and apply new one.
|
||
|
eff.cancelJob();
|
||
|
mob.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true);
|
||
|
} else {
|
||
|
|
||
|
if (mbe.getReqLvl() > (int) mob.level)
|
||
|
continue;
|
||
|
|
||
|
mob.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int slot = 0;
|
||
|
slot += siegeMinionMap.size() + 1;
|
||
|
|
||
|
siegeMinionMap.put(mob, slot);
|
||
|
mob.setInBuildingLoc(this.building, this);
|
||
|
mob.setBindLoc(loc.add(mob.inBuildingLoc));
|
||
|
mob.deathTime = System.currentTimeMillis();
|
||
|
mob.spawnTime = 900;
|
||
|
mob.npcOwner = this;
|
||
|
mob.state = STATE.Respawn;
|
||
|
|
||
|
return mob;
|
||
|
}
|
||
|
|
||
|
public static void setUpgradeDateTime(Mob mob,DateTime upgradeDateTime) {
|
||
|
|
||
|
if (!DbManager.MobQueries.updateUpgradeTime(mob, upgradeDateTime)){
|
||
|
Logger.error("Failed to set upgradeTime for building " + mob.currentID);
|
||
|
return;
|
||
|
}
|
||
|
mob.upgradeDateTime = upgradeDateTime;
|
||
|
}
|
||
|
|
||
|
public Contract getContract() {
|
||
|
return contract;
|
||
|
}
|
||
|
|
||
|
public void setContract(Contract contract) {
|
||
|
this.contract = contract;
|
||
|
}
|
||
|
|
||
|
public boolean isPlayerGuard() {
|
||
|
return isPlayerGuard;
|
||
|
}
|
||
|
|
||
|
public void setPlayerGuard(boolean isPlayerGuard) {
|
||
|
this.isPlayerGuard = isPlayerGuard;
|
||
|
}
|
||
|
|
||
|
public int getPatrolPointIndex() {
|
||
|
return patrolPointIndex;
|
||
|
}
|
||
|
|
||
|
public void setPatrolPointIndex(int patrolPointIndex) {
|
||
|
this.patrolPointIndex = patrolPointIndex;
|
||
|
}
|
||
|
|
||
|
public int getLastMobPowerToken() {
|
||
|
return lastMobPowerToken;
|
||
|
}
|
||
|
|
||
|
public void setLastMobPowerToken(int lastMobPowerToken) {
|
||
|
this.lastMobPowerToken = lastMobPowerToken;
|
||
|
}
|
||
|
|
||
|
public Regions getLastRegion() {
|
||
|
return lastRegion;
|
||
|
}
|
||
|
|
||
|
public void setLastRegion(Regions lastRegion) {
|
||
|
this.lastRegion = lastRegion;
|
||
|
}
|
||
|
|
||
|
public boolean isLootSync() {
|
||
|
return lootSync;
|
||
|
}
|
||
|
|
||
|
public void setLootSync(boolean lootSync) {
|
||
|
this.lootSync = lootSync;
|
||
|
}
|
||
|
|
||
|
public int getFidalityID() {
|
||
|
return fidalityID;
|
||
|
}
|
||
|
|
||
|
public HashMap<Integer, MobEquipment> getEquip() {
|
||
|
return equip;
|
||
|
}
|
||
|
|
||
|
public int getEquipmentSetID() {
|
||
|
return equipmentSetID;
|
||
|
}
|
||
|
|
||
|
public int getLootSet() {
|
||
|
return lootSet;
|
||
|
}
|
||
|
|
||
|
public boolean isGuard(){
|
||
|
return this.isGuard;
|
||
|
}
|
||
|
|
||
|
public String getNameOverride() {
|
||
|
return nameOverride;
|
||
|
}
|
||
|
|
||
|
public static Vector3fImmutable GetSpawnRadiusLocation(Mob mob){
|
||
|
|
||
|
Vector3fImmutable returnLoc = Vector3fImmutable.ZERO;
|
||
|
|
||
|
if (mob.fidalityID != 0 && mob.building != null){
|
||
|
|
||
|
|
||
|
Vector3fImmutable spawnRadiusLoc = Vector3fImmutable.getRandomPointInCircle(mob.localLoc, mob.spawnRadius);
|
||
|
|
||
|
Vector3fImmutable buildingWorldLoc = ZoneManager.convertLocalToWorld(mob.building, spawnRadiusLoc);
|
||
|
|
||
|
return buildingWorldLoc;
|
||
|
|
||
|
|
||
|
|
||
|
}else{
|
||
|
|
||
|
boolean run = true;
|
||
|
|
||
|
while(run){
|
||
|
Vector3fImmutable localLoc = new Vector3fImmutable(mob.statLat + mob.parentZone.absX, mob.statAlt + mob.parentZone.absY, mob.statLon + mob.parentZone.absZ);
|
||
|
Vector3fImmutable spawnRadiusLoc = Vector3fImmutable.getRandomPointInCircle(localLoc, mob.spawnRadius);
|
||
|
|
||
|
//not a roaming mob, just return the random loc.
|
||
|
if (mob.spawnRadius < 12000)
|
||
|
return spawnRadiusLoc;
|
||
|
|
||
|
Zone spawnZone = ZoneManager.findSmallestZone(spawnRadiusLoc);
|
||
|
//dont spawn roaming mobs in npc cities
|
||
|
if (spawnZone.isNPCCity())
|
||
|
continue;
|
||
|
|
||
|
//dont spawn roaming mobs in player cities.
|
||
|
if (spawnZone.isPlayerCity())
|
||
|
continue;
|
||
|
|
||
|
//don't spawn mobs in water.
|
||
|
if (HeightMap.isLocUnderwater(spawnRadiusLoc))
|
||
|
continue;
|
||
|
|
||
|
run = false;
|
||
|
|
||
|
return spawnRadiusLoc;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//shouldn't ever get here.
|
||
|
|
||
|
return returnLoc;
|
||
|
}
|
||
|
|
||
|
public void processUpgradeMob(PlayerCharacter player){
|
||
|
|
||
|
lock.writeLock().lock();
|
||
|
|
||
|
try{
|
||
|
|
||
|
building = this.getBuilding();
|
||
|
|
||
|
// Cannot upgrade an npc not within a building
|
||
|
|
||
|
if (building == null)
|
||
|
return;
|
||
|
|
||
|
// Cannot upgrade an npc at max rank
|
||
|
|
||
|
if (this.getRank() == 7)
|
||
|
return;
|
||
|
|
||
|
// Cannot upgrade an npc who is currently ranking
|
||
|
|
||
|
if (this.isRanking())
|
||
|
return;
|
||
|
|
||
|
int rankCost = Mob.getUpgradeCost(this);
|
||
|
|
||
|
// SEND NOT ENOUGH GOLD ERROR
|
||
|
|
||
|
if (rankCost > building.getStrongboxValue()) {
|
||
|
sendErrorPopup(player, 127);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
|
||
|
if (!building.transferGold(-rankCost,false)){
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DateTime dateToUpgrade = DateTime.now().plusHours(Mob.getUpgradeTime(this));
|
||
|
Mob.setUpgradeDateTime(this,dateToUpgrade);
|
||
|
|
||
|
// Schedule upgrade job
|
||
|
|
||
|
Mob.submitUpgradeJob(this);
|
||
|
|
||
|
} catch (Exception e) {
|
||
|
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||
|
}
|
||
|
|
||
|
}catch(Exception e){
|
||
|
Logger.error(e);
|
||
|
}finally{
|
||
|
lock.writeLock().unlock();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void processRedeedMob(ClientConnection origin) {
|
||
|
|
||
|
// Member variable declaration
|
||
|
PlayerCharacter player;
|
||
|
Contract contract;
|
||
|
CharacterItemManager itemMan;
|
||
|
ItemBase itemBase;
|
||
|
Item item;
|
||
|
|
||
|
this.lock.writeLock().lock();
|
||
|
|
||
|
try{
|
||
|
|
||
|
player = SessionManager.getPlayerCharacter(origin);
|
||
|
itemMan = player.getCharItemManager();
|
||
|
|
||
|
|
||
|
contract = this.getContract();
|
||
|
|
||
|
if (!player.getCharItemManager().hasRoomInventory((short)1)){
|
||
|
ErrorPopupMsg.sendErrorPopup(player, 21);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (!building.getHirelings().containsKey(this))
|
||
|
return;
|
||
|
|
||
|
if (!this.remove(building)) {
|
||
|
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
building.getHirelings().remove(this);
|
||
|
|
||
|
itemBase = ItemBase.getItemBase(contract.getContractID());
|
||
|
|
||
|
if (itemBase == null) {
|
||
|
Logger.error( "Could not find Contract for npc: " + this.getObjectUUID());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
boolean itemWorked = false;
|
||
|
|
||
|
item = new Item( itemBase, player.getObjectUUID(), OwnerType.PlayerCharacter, (byte) ((byte) this.getRank() - 1), (byte) ((byte) this.getRank() - 1),
|
||
|
(short) 1, (short) 1, true, false, Enum.ItemContainerType.INVENTORY, (byte) 0,
|
||
|
new ArrayList<>(),"");
|
||
|
item.setNumOfItems(1);
|
||
|
item.containerType = Enum.ItemContainerType.INVENTORY;
|
||
|
|
||
|
try {
|
||
|
item = DbManager.ItemQueries.ADD_ITEM(item);
|
||
|
itemWorked = true;
|
||
|
} catch (Exception e) {
|
||
|
Logger.error(e);
|
||
|
}
|
||
|
if (itemWorked) {
|
||
|
itemMan.addItemToInventory(item);
|
||
|
itemMan.updateInventory();
|
||
|
}
|
||
|
|
||
|
ManageCityAssetsMsg mca = new ManageCityAssetsMsg();
|
||
|
mca.actionType = NPC.SVR_CLOSE_WINDOW;
|
||
|
mca.setTargetType(building.getObjectType().ordinal());
|
||
|
mca.setTargetID(building.getObjectUUID());
|
||
|
origin.sendMsg(mca);
|
||
|
|
||
|
|
||
|
}catch(Exception e){
|
||
|
Logger.error(e);
|
||
|
}finally{
|
||
|
this.lock.writeLock().unlock();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
public void dismiss() {
|
||
|
|
||
|
if (this.isPet()) {
|
||
|
|
||
|
if (this.isSummonedPet()) { //delete summoned pet
|
||
|
|
||
|
WorldGrid.RemoveWorldObject(this);
|
||
|
DbManager.removeFromCache(this);
|
||
|
if (this.getObjectType() == GameObjectType.Mob){
|
||
|
((Mob)this).setState(STATE.Disabled);
|
||
|
if (((Mob)this).getParentZone() != null)
|
||
|
((Mob)this).getParentZone().zoneMobSet.remove(this);
|
||
|
}
|
||
|
|
||
|
} else { //revert charmed pet
|
||
|
this.setMob();
|
||
|
this.setCombatTarget(null);
|
||
|
// if (this.isAlive())
|
||
|
// WorldServer.updateObject(this);
|
||
|
}
|
||
|
//clear owner
|
||
|
PlayerCharacter owner = this.getOwner();
|
||
|
|
||
|
//close pet window
|
||
|
if (owner != null) {
|
||
|
Mob pet = owner.getPet();
|
||
|
PetMsg pm = new PetMsg(5, null);
|
||
|
Dispatch dispatch = Dispatch.borrow(owner, pm);
|
||
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||
|
|
||
|
if (pet != null && pet.getObjectUUID() == this.getObjectUUID())
|
||
|
owner.setPet(null);
|
||
|
|
||
|
if (this.getObjectType().equals(GameObjectType.Mob))
|
||
|
((Mob)this).setOwner(null);
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void dismissNecroPet(boolean updateOwner) {
|
||
|
|
||
|
this.state = STATE.Disabled;
|
||
|
|
||
|
this.combatTarget = null;
|
||
|
this.hasLoot = false;
|
||
|
|
||
|
if (this.parentZone != null)
|
||
|
this.parentZone.zoneMobSet.remove(this);
|
||
|
|
||
|
try {
|
||
|
this.clearEffects();
|
||
|
}catch(Exception e){
|
||
|
Logger.error( e.getMessage());
|
||
|
}
|
||
|
this.playerAgroMap.clear();
|
||
|
WorldGrid.RemoveWorldObject(this);
|
||
|
|
||
|
DbManager.removeFromCache(this);
|
||
|
|
||
|
// YEAH BONUS CODE! THANKS UNNAMED ASSHOLE!
|
||
|
//WorldServer.removeObject(this);
|
||
|
//WorldGrid.INSTANCE.removeWorldObject(this);
|
||
|
//owner.getPet().disableIntelligence();
|
||
|
|
||
|
PlayerCharacter petOwner = this.getOwner();
|
||
|
|
||
|
if (petOwner != null){
|
||
|
((Mob)this).setOwner(null);
|
||
|
petOwner.setPet(null);
|
||
|
|
||
|
if (updateOwner == false)
|
||
|
return;
|
||
|
PetMsg petMsg = new PetMsg(5, null);
|
||
|
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg);
|
||
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
}
|