From 7473067329b04066d14fb1f84d10f7d6d4372879 Mon Sep 17 00:00:00 2001 From: MagicBot Date: Wed, 15 Mar 2023 08:47:22 -0400 Subject: [PATCH] Reformatting of MobCast() method in manager. --- src/engine/ai/MobileFSM.java | 101 +- src/engine/objects/Mob.java | 5447 +++++++++++++++++----------------- 2 files changed, 2772 insertions(+), 2776 deletions(-) diff --git a/src/engine/ai/MobileFSM.java b/src/engine/ai/MobileFSM.java index 731369e8..ab7be602 100644 --- a/src/engine/ai/MobileFSM.java +++ b/src/engine/ai/MobileFSM.java @@ -1648,59 +1648,72 @@ public class MobileFSM { return true; } public static boolean MobCast(Mob mob) { - if (mob.getMobBase().getFlags().contains(Enum.MobFlagType.CALLSFORHELP)) { - MobCallForHelp(mob); - } + + // Method picks a random spell from a mobile's list of powers + // and casts it on the player. Validation (including empty lists) + // if done previously in canCast(); + + ArrayList powerTokens; PlayerCharacter target = (PlayerCharacter) mob.getCombatTarget(); - HashMap eligiblePowers = mob.mobPowers; - for(Map.Entry power : mob.mobPowers.entrySet()) { - PowersBase pwr= PowersManager.getPowerByToken(power.getKey()); + + if (mob.getMobBase().getFlags().contains(Enum.MobFlagType.CALLSFORHELP)) + MobCallForHelp(mob); + + // Generate a list of tokens from the mob powers for this mobile. + + powerTokens = new ArrayList<>(mob.mobPowers.keySet()); + + // If player has this effect on them already then remove the token + // from the list of mob powers + + for (int powerToken : powerTokens){ + + PowersBase pwr= PowersManager.getPowerByToken(powerToken); + for(ActionsBase act : pwr.getActions()){ + String des = act.stackType; - try { - if (target.getEffects() != null && target.getEffects().containsKey(des) == true) { - eligiblePowers.remove(power.getKey()); - } - }catch(Exception ex){ - } + if (target.getEffects() != null && target.getEffects().containsKey(des)) + powerTokens.remove(powerToken); } - } - int random = ThreadLocalRandom.current().nextInt(eligiblePowers.size()); - int powerToken = 0; - int powerRank = 0; - Map entries = eligiblePowers; - int count = -1; - for (Map.Entry entry : entries.entrySet()) { - count += 1; - if (count == random) { - powerToken = entry.getKey(); - powerRank = entry.getValue(); - PowersBase mobPower = PowersManager.getPowerByToken(powerToken); - if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mobPower.getRange())) { - PowersManager.useMobPower(mob,(AbstractCharacter)mob.getCombatTarget(),mobPower,powerRank); - PerformActionMsg msg = new PerformActionMsg(); - if(mobPower.isHarmful() == false || mobPower.targetSelf == true){ - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob); - } else { - msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); - } - msg.setUnknown04(2); - PowersManager.finishUseMobPower(msg, mob, 0, 0); - //default minimum seconds between cast = 10 - long cooldown = mobPower.getCooldown(); - if(cooldown < 10000){ - mob.nextCastTime = System.currentTimeMillis() + 10000 + cooldown; - } else { - mob.nextCastTime = System.currentTimeMillis() + cooldown; - } - return true; + + // Pick random spell from our list of powers + + int powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); + int powerRank = mob.mobPowers.get(powerToken); + PowersBase mobPower = PowersManager.getPowerByToken(powerToken); + + // Cast the spell + + if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mobPower.getRange())) { + PowersManager.useMobPower(mob,(AbstractCharacter)mob.getCombatTarget(),mobPower,powerRank); + PerformActionMsg msg; + + if(mobPower.isHarmful() == false || mobPower.targetSelf == true) + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, mob); + else + msg = PowersManager.createPowerMsg(mobPower, powerRank, mob, target); + + msg.setUnknown04(2); + PowersManager.finishUseMobPower(msg, mob, 0, 0); + + //default minimum seconds between cast = 10 + + long coolDown = mobPower.getCooldown(); + + if(coolDown < 10000) + mob.nextCastTime = System.currentTimeMillis() + 10000 + coolDown; + else + mob.nextCastTime = System.currentTimeMillis() + coolDown; + + return true; } - } - } + return false; } + public static void MobCallForHelp(Mob mob) { if(mob.nextCallForHelp == 0){ mob.nextCallForHelp = System.currentTimeMillis(); diff --git a/src/engine/objects/Mob.java b/src/engine/objects/Mob.java index 9521656b..81d9dde0 100644 --- a/src/engine/objects/Mob.java +++ b/src/engine/objects/Mob.java @@ -51,2982 +51,2965 @@ 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 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 playerAgroMap = new ConcurrentHashMap<>(); - private boolean noAggro = false; - private STATE state = STATE.Disabled; - private int aggroTargetID = 0; - private boolean walkingHome = true; - private long lastAttackTime = 0; - public long nextCastTime = 0; - public long nextCallForHelp = 0; - private long deathTime = 0; - private ConcurrentHashMap 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 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 fidelityRunes = null; - - public boolean despawned = false; - public Vector3fImmutable destination = Vector3fImmutable.ZERO; - public Vector3fImmutable localLoc = Vector3fImmutable.ZERO; - public HashMap mobPowers; - /** - * 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; + private static final ReentrantReadWriteLock createLock = new ReentrantReadWriteLock(); + // Variables NOT to be stored in db + private static int staticID = 0; + private static final ConcurrentHashMap mobMapByDBID = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + + //mob specific + private final ConcurrentHashMap playerAgroMap = new ConcurrentHashMap<>(); + public long nextCastTime = 0; + public long nextCallForHelp = 0; + public ReentrantReadWriteLock minionLock = new ReentrantReadWriteLock(); + public boolean despawned = false; + public Vector3fImmutable destination = Vector3fImmutable.ZERO; + public Vector3fImmutable localLoc = Vector3fImmutable.ZERO; + public HashMap mobPowers; + protected int dbID; //the database ID + protected int loadID; + protected boolean isMob; + protected MobBase mobBase; + 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 int currentID; + private int ownerUID = 0; //only used by pets + private boolean hasLoot = false; + 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 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 final ConcurrentHashMap siegeMinionMap = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); + private int patrolPointIndex = 0; + private int lastMobPowerToken = 0; + private HashMap 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 fidelityRunes = null; + + /** + * 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); + } + + } + + 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); + } + + /** + * 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 = 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 + + gold *= Float.parseFloat(ConfigManager.MB_NORMAL_DROP_RATE.getValue()); + + //modify for hotzone + + if (ZoneManager.inHotZone(mob.getLoc())) + gold *= Float.parseFloat(ConfigManager.MB_HOTZONE_DROP_RATE.getValue()); + + 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; + } - Effect eff = this.effects.get(Integer.toString(eb.getUUID())); + 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(); - if (eff == null) - continue; + 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; - if (eff.getTrains() > mbe.getRank()) - continue; + } catch (Exception e) { + Logger.error(e); + } finally { + createLock.writeLock().unlock(); + } - //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; + return mob; + } - this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true); - } - } + public static int nextStaticID() { + int id = Mob.staticID; + Mob.staticID++; + return id; + } - //Apply all rune effects. - // Only Captains have contracts - if (contract != null || this.isPlayerGuard){ - RuneBase guardRune = RuneBase.getRuneBase(252621); - for (MobBaseEffects mbe : guardRune.getEffectsList()) { + public static Mob getMob(int id) { - eb = PowersManager.getEffectByToken(mbe.getToken()); + if (id == 0) + return null; - if (eb == null) { - Logger.info( "EffectsBase Null for Token " + mbe.getToken()); - continue; - } + Mob mob = (Mob) DbManager.getFromCache(GameObjectType.Mob, id); + if (mob != null) + return mob; + return DbManager.MobQueries.GET_MOB(id); + } - //check to upgrade effects if needed. - if (this.effects.containsKey(Integer.toString(eb.getUUID()))) { + public static Mob getFromCache(int id) { - if (mbe.getReqLvl() > (int) this.level) - continue; - Effect eff = this.effects.get(Integer.toString(eb.getUUID())); + return (Mob) DbManager.getFromCache(GameObjectType.Mob, id); + } - if (eff == null) - continue; + public static Mob getFromCacheDBID(int id) { + if (Mob.mobMapByDBID.containsKey(id)) { + return Mob.mobMapByDBID.get(id); + } + return null; + } - //Current effect is a higher rank, dont apply. - if (eff.getTrains() > mbe.getRank()) - continue; + private static float getModifiedAmount(CharacterSkill skill) { - //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 (skill == null) + return 0f; - if (mbe.getReqLvl() > (int) this.level) - continue; + return skill.getModifiedAmount(); + } - this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true); - } - } + public static int getBuildingSlot(Mob mob) { + int slot = -1; - RuneBase WarriorRune = RuneBase.getRuneBase(2518); - for (MobBaseEffects mbe : WarriorRune.getEffectsList()) { + if (mob.building == null) + return -1; - eb = PowersManager.getEffectByToken(mbe.getToken()); - if (eb == null) { - Logger.info( "EffectsBase Null for Token " + mbe.getToken()); - continue; - } + BuildingModelBase buildingModel = BuildingModelBase.getModelBase(mob.building.getMeshUUID()); - //check to upgrade effects if needed. - if (this.effects.containsKey(Integer.toString(eb.getUUID()))) { + if (buildingModel == null) + return -1; - if (mbe.getReqLvl() > (int) this.level) - continue; - Effect eff = this.effects.get(Integer.toString(eb.getUUID())); + if (mob.building.getHirelings().containsKey(mob)) + slot = (mob.building.getHirelings().get(mob)); - if (eff == null) - continue; - //Current effect is a higher rank, dont apply. - if (eff.getTrains() > mbe.getRank()) - continue; + if (buildingModel.getNPCLocation(slot) == null) + return -1; - //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; + return slot; + } - this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true); - } - } - } + public static void HandleAssistedAggro(PlayerCharacter source, PlayerCharacter target) { - if (this.fidelityRunes != null){ + HashSet mobsInRange = WorldGrid.getObjectsInRangePartial(source, MBServerStatics.AI_DROP_AGGRO_RANGE, MBServerStatics.MASK_MOB); - for (int fidelityRune : this.fidelityRunes) { + for (AbstractWorldObject awo : mobsInRange) { + Mob mob = (Mob) awo; - RuneBase rune = RuneBase.getRuneBase(fidelityRune); + //Mob is not attacking anyone, skip. + if (mob.getCombatTarget() == null) + continue; - if (rune != null) - for (MobBaseEffects mbe : rune.getEffectsList()) { + //Mob not attacking target's target, let's not be failmu and skip this target. + if (mob.getCombatTarget() != target) + continue; - eb = PowersManager.getEffectByToken(mbe.getToken()); - if (eb == null) { - Logger.info("EffectsBase Null for Token " + mbe.getToken()); - continue; - } + //target is mob's combat target, LETS GO. + if (source.getHateValue() > target.getHateValue()) { + mob.setCombatTarget(source); + MobileFSM.setAggro(mob, source.getObjectUUID()); + } + } + } - //check to upgrade effects if needed. - if (this.effects.containsKey(Integer.toString(eb.getUUID()))) { - if (mbe.getReqLvl() > (int) this.level) - continue; + public static void submitUpgradeJob(Mob mob) { - Effect eff = this.effects.get(Integer.toString(eb.getUUID())); + JobContainer jc; - if (eff == null) - continue; + if (mob.getUpgradeDateTime() == null) { + Logger.error("Failed to get Upgrade Date"); + return; + } - //Current effect is a higher rank, dont apply. - if (eff.getTrains() > mbe.getRank()) - continue; + // Submit upgrade job for future date or current instant - //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); + if (mob.getUpgradeDateTime().isAfter(DateTime.now())) + jc = JobScheduler.getInstance().scheduleJob(new UpgradeNPCJob(mob), + mob.getUpgradeDateTime().getMillis()); + else + JobScheduler.getInstance().scheduleJob(new UpgradeNPCJob(mob), 0); - } else { + } - if (mbe.getReqLvl() > (int) this.level) - continue; + public static int getUpgradeTime(Mob mob) { - this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true); - } - } - } - }else - for (RuneBase rune : this.mobBase.getRunes()) { - for (MobBaseEffects mbe : rune.getEffectsList()) { + if (mob.getRank() < 7) + return (mob.getRank() * 8); - eb = PowersManager.getEffectByToken(mbe.getToken()); - if (eb == null) { - Logger.info( "EffectsBase Null for Token " + mbe.getToken()); - continue; - } + return 0; + } - //check to upgrade effects if needed. - if (this.effects.containsKey(Integer.toString(eb.getUUID()))) { - if (mbe.getReqLvl() > (int) this.level) - continue; + public static int getUpgradeCost(Mob mob) { - Effect eff = this.effects.get(Integer.toString(eb.getUUID())); + int upgradeCost; - if (eff == null) - continue; + upgradeCost = Integer.MAX_VALUE; - //Current effect is a higher rank, dont apply. - if (eff.getTrains() > mbe.getRank()) - continue; + if (mob.getRank() < 7) + return (mob.getRank() * 100650) + 21450; - //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 { + return upgradeCost; + } - if (mbe.getReqLvl() > (int) this.level) - continue; + public static void setUpgradeDateTime(Mob mob, DateTime upgradeDateTime) { - this.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true); - } - } - } - } + if (!DbManager.MobQueries.updateUpgradeTime(mob, upgradeDateTime)) { + Logger.error("Failed to set upgradeTime for building " + mob.currentID); + return; + } + mob.upgradeDateTime = upgradeDateTime; + } - /* - * Getters - */ - @Override - public int getDBID() { - return this.dbID; - } + public static Vector3fImmutable GetSpawnRadiusLocation(Mob mob) { - public int getLoadID() { - return loadID; - } + Vector3fImmutable returnLoc = Vector3fImmutable.ZERO; - @Override - public int getObjectUUID() { - return currentID; - } + if (mob.fidalityID != 0 && mob.building != null) { - public float getSpawnX() { - return this.statLat; - } - public float getSpawnY() { - return this.statAlt; - } + Vector3fImmutable spawnRadiusLoc = Vector3fImmutable.getRandomPointInCircle(mob.localLoc, mob.spawnRadius); - public float getSpawnZ() { - return this.statLon; - } + Vector3fImmutable buildingWorldLoc = ZoneManager.convertLocalToWorld(mob.building, spawnRadiusLoc); - public float getSpawnRadius() { - return this.spawnRadius; - } + return buildingWorldLoc; - public int getSpawnTime() { - if (this.spawnTime == 0) - return MBServerStatics.RESPAWN_TIMER; - else - return this.spawnTime * 1000; - } + } else { - //use getSpawnTime instead. This is just for init tables - public int getTrueSpawnTime() { - return this.spawnTime; - } + boolean run = true; - public String getSpawnTimeAsString() { - if (this.spawnTime == 0) - return MBServerStatics.DEFAULT_SPAWN_TIME_MS / 1000 + " seconds (Default)"; - else - return this.spawnTime + " seconds"; + 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; - public void setSpawnTime(int value) { - this.spawnTime = value; - } - - @Override - public MobBase getMobBase() { - return this.mobBase; - } + //dont spawn roaming mobs in player cities. + if (spawnZone.isPlayerCity()) + continue; - public int getMobBaseID() { + //don't spawn mobs in water. + if (HeightMap.isLocUnderwater(spawnRadiusLoc)) + continue; - if (this.mobBase != null) - return this.mobBase.getObjectUUID(); + run = false; - return 0; - } + return spawnRadiusLoc; - 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()) { + //shouldn't ever get here. - PlayerCharacter petOwner = this.getOwner(); + return returnLoc; + } - 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 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); - } - } + private void clearStatic() { - 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(); + if (this.parentZone != null) + this.parentZone.zoneMobSet.remove(this); - this.setHealth(this.healthMax); - - if (!this.isSiege && !this.isPlayerGuard && contract == null) - loadInventory(); + this.parentZone = null; + this.statLat = 0f; + this.statLon = 0f; + this.statAlt = 0f; + } - // LoadJob.getInstance(); - // LoadJob.forceLoad(this); - } + private void initializeMob(boolean isPet, boolean isSiege, boolean isGuard) { - public void despawn() { - - this.despawned = true; + if (this.mobBase != null) { - //WorldServer.removeObject(this); - WorldGrid.RemoveWorldObject(this); - this.charItemManager.clearInventory(); - this.despawnTime = System.currentTimeMillis(); - // this.setLoc(Vector3fImmutable.ZERO); - } + 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); - //Sets the relative position to a parent zone - public void setRelPos(Zone zone, float locX, float locY, float locZ) { + 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(); + } - //update mob zone map + } else + this.level = 1; - if (this.parentZone != null) - this.parentZone.zoneMobSet.remove(this); + //add this npc to building + if (this.building != null && this.loadID != 0 && this.fidalityID == 0) { - zone.zoneMobSet.add(this); + int maxSlots; + maxSlots = building.getBlueprint().getSlotsForRank(this.building.getRank()); - 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; + for (int slot = 1; slot < maxSlots + 1; slot++) { + if (!this.building.getHirelings().containsValue(slot)) { + this.building.getHirelings().put(this, slot); + break; + } + } + } - int gold = Mob.randomGoldAmount(this); - - if (gold > 0 && this.getLootTable() != 0) { - addGoldToInventory(gold); - } - - //add random loot to mob - ArrayList alml = LootTable.getMobLoot(this, this.getLevel(), this.getLootTable(), false); //add hotzone check in later - - for (MobLoot ml : alml) { - this.charItemManager.addItemToInventory(ml); - } + //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; + } + + /* + * Serialization + */ + + 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; + } + + public void setSpawnTime(int value) { + this.spawnTime = value; + } + + //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"; + + } + + @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 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); + } + + 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; + } + + @Override + public Vector3fImmutable getBindLoc() { + + if (this.isPet() && !this.isSiege) + return this.getOwner() != null ? this.getOwner().getLoc() : this.getLoc(); + return this.bindLoc; + } + + 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. + + } + + /* + * Database + */ + + @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 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; + + } 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 alml = LootTable.getMobLoot(this, this.getLevel(), this.getLootTable(), false); //add hotzone check in later + + for (MobLoot ml : alml) { + this.charItemManager.addItemToInventory(ml); + } //send announcement if disc or godly rune - for(Item it : this.getInventory()) { - ItemBase ib = it.getItemBase(); - if (ib.isDiscRune()) { - //if disc rune send system message - ChatSystemMsg chatMsg = new ChatSystemMsg(null, this.getName() + " in " + this.getParentZone().getName() + " has found the " + ib.getName() +". Are you tough enough to take it?"); - chatMsg.setMessageType(10); - chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID()); - DispatchMessage.dispatchMsgToAll(chatMsg); - } - if (ib.isStatRune() && ib.getName().toLowerCase().contains("of the gods")) { - //godly rune send system message - ChatSystemMsg chatMsg = new ChatSystemMsg(null, this.getName() + " in " + this.getParentZone().getName() + " has found the " + ib.getName() +". Are you tough enough to take it?"); - chatMsg.setMessageType(10); - chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID()); - DispatchMessage.dispatchMsgToAll(chatMsg); - return; - } - } - - //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 - - gold *= Float.parseFloat(ConfigManager.MB_NORMAL_DROP_RATE.getValue()); - - //modify for hotzone - - if (ZoneManager.inHotZone(mob.getLoc())) - gold *= Float.parseFloat(ConfigManager.MB_HOTZONE_DROP_RATE.getValue()); - - 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"); - } + for (Item it : this.getInventory()) { + ItemBase ib = it.getItemBase(); + if (ib.isDiscRune()) { + //if disc rune send system message + ChatSystemMsg chatMsg = new ChatSystemMsg(null, this.getName() + " in " + this.getParentZone().getName() + " has found the " + ib.getName() + ". Are you tough enough to take it?"); + chatMsg.setMessageType(10); + chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID()); + DispatchMessage.dispatchMsgToAll(chatMsg); + } + if (ib.isStatRune() && ib.getName().toLowerCase().contains("of the gods")) { + //godly rune send system message + ChatSystemMsg chatMsg = new ChatSystemMsg(null, this.getName() + " in " + this.getParentZone().getName() + " has found the " + ib.getName() + ". Are you tough enough to take it?"); + chatMsg.setMessageType(10); + chatMsg.setChannel(Enum.ChatChannelType.SYSTEM.getChannelID()); + DispatchMessage.dispatchMsgToAll(chatMsg); + return; + } + } + + //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); + } + + @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 - } + 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 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); + private float getWeaponDefense(HashMap 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(); + if (weapon == null) + unarmed = true; + else + wb = weapon.getItemBase(); - } else - wb = weapon.getItemBase(); + } else + wb = weapon.getItemBase(); - if (wb == null) - unarmed = true; + 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 (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 (skill != null) + val += (int) skill.getModifiedAmount() / 2f; - if (mastery != null) - val += (int) mastery.getModifiedAmount() / 2f; + if (mastery != null) + val += (int) mastery.getModifiedAmount() / 2f; - return val; - } + return val; + } - private float getShieldDefense(MobEquipment shield) { + private float getShieldDefense(MobEquipment shield) { - if (shield == null) - return 0; + if (shield == null) + return 0; - ItemBase ab = shield.getItemBase(); + ItemBase ab = shield.getItemBase(); - if (ab == null || !ab.isShield()) - return 0; + if (ab == null || !ab.isShield()) + return 0; - CharacterSkill blockSkill = this.skills.get("Block"); - float skillMod; + CharacterSkill blockSkill = this.skills.get("Block"); + float skillMod; - if (blockSkill == null) { - skillMod = CharacterSkill.getQuickMastery(this, "Block"); + if (blockSkill == null) { + skillMod = CharacterSkill.getQuickMastery(this, "Block"); - if (skillMod == 0f) - return 0; + if (skillMod == 0f) + return 0; - } else - skillMod = blockSkill.getModifiedAmount(); + } 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); + // // 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))); - } + 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) { + private float getArmorDefense(MobEquipment armor) { - if (armor == null) - return 0; + if (armor == null) + return 0; - ItemBase ib = armor.getItemBase(); + ItemBase ib = armor.getItemBase(); - if (ib == null) - return 0; + if (ib == null) + return 0; - if (!ib.getType().equals(ItemType.ARMOR)) - return 0; + if (!ib.getType().equals(ItemType.ARMOR)) + return 0; - if (ib.getSkillRequired().isEmpty()) - return ib.getDefense(); + if (ib.getSkillRequired().isEmpty()) + return ib.getDefense(); - CharacterSkill armorSkill = this.skills.get(ib.getSkillRequired()); + CharacterSkill armorSkill = this.skills.get(ib.getSkillRequired()); - if (armorSkill == null) - return ib.getDefense(); + if (armorSkill == null) + return ib.getDefense(); - float def = ib.getDefense(); + float def = ib.getDefense(); - //apply item defense bonuses + //apply item defense bonuses - return (def * (1 + ((int) armorSkill.getModifiedAmount() / 50f))); - } + return (def * (1 + ((int) armorSkill.getModifiedAmount() / 50f))); + } - private void calculateAtrDamageForWeapon(MobEquipment weapon, boolean mainHand, MobEquipment otherHand) { + private void calculateAtrDamageForWeapon(MobEquipment weapon, boolean mainHand, MobEquipment otherHand) { - int baseStrength = 0; + int baseStrength = 0; - float skillPercentage, masteryPercentage; - float mastDam; + float skillPercentage, masteryPercentage; + float mastDam; - // make sure weapon exists - boolean noWeapon = false; - ItemBase wb = null; + // make sure weapon exists + boolean noWeapon = false; + ItemBase wb = null; - if (weapon == null) - noWeapon = true; - else { + if (weapon == null) + noWeapon = true; + else { - ItemBase ib = weapon.getItemBase(); + ItemBase ib = weapon.getItemBase(); - if (ib == null) - noWeapon = true; - else { + 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; + 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 + // get skill percentages and min and max damage for weapons - if (noWeapon) { + if (noWeapon) { - if (mainHand) - this.rangeHandOne = this.mobBase.getAttackRange(); - else - this.rangeHandTwo = -1; // set to do not attack + 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")); + 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; + 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 { + // 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)); + 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())); + skillPercentage = getModifiedAmount(this.skills.get(wb.getSkillRequired())); + masteryPercentage = getModifiedAmount(this.skills.get(wb.getMastery())); - if (masteryPercentage == 0f) - mastDam = 0f; - else - mastDam = masteryPercentage; + if (masteryPercentage == 0f) + mastDam = 0f; + else + mastDam = masteryPercentage; - min = (float) wb.getMinDamage(); - max = (float) wb.getMaxDamage(); - strBased = wb.isStrBased(); - } + min = wb.getMinDamage(); + max = wb.getMaxDamage(); + strBased = wb.isStrBased(); + } - // calculate atr - float atr = this.mobBase.getAttackRating(); + // calculate atr + float atr = this.mobBase.getAttackRating(); - //atr += ((int) skillPercentage * 4f); //<-round down skill% - - //atr += ((int) masteryPercentage * 3f); + //atr += ((int) skillPercentage * 4f); //<-round down skill% - + //atr += ((int) masteryPercentage * 3f); - if (this.statStrCurrent > this.statDexCurrent) - atr += statStrCurrent / 2; - else - atr += statDexCurrent / 2; + 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); + // 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); + // Finally use any multipliers. DO THIS LAST! + float pos_Bonus = 1 + this.bonuses.getFloatPercentPositive(ModType.OCV, SourceType.None); - - atr *= pos_Bonus; - // next precise - + 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); - } + //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 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 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(); + + 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()); + } + mobPowers = new HashMap(); + //mobPowers = DbManager.MobBaseQueries.LOAD_STATIC_POWERS(this.getMobBaseID()); + if (PowersManager.AllMobPowers.containsKey(this.getMobBaseID()) == true) { + mobPowers = PowersManager.AllMobPowers.get(this.getMobBaseID()); + } + 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 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 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 void setRank(int newRank) { + + DbManager.MobQueries.SET_PROPERTY(this, "mob_level", newRank); + this.level = (short) newRank; + + } + + 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; + } - atr = (atr < 1) ? 1 : atr; + public int getAggroTargetID() { + return aggroTargetID; + } - // set atr - if (mainHand) - this.atrHandOne = (short) (atr + 0.5f); - else - this.atrHandTwo = (short) (atr + 0.5f); + public void setAggroTargetID(int aggroTargetID) { + this.aggroTargetID = aggroTargetID; + } - //calculate speed + public boolean isWalkingHome() { + return walkingHome; + } - if (wb != null) - speed = wb.getSpeed(); - else - speed = 20f; //unarmed attack speed + public void setWalkingHome(boolean walkingHome) { + this.walkingHome = walkingHome; + } - 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)); + public long getLastAttackTime() { + return lastAttackTime; + } - if (speed < 10) - speed = 10; + public void setLastAttackTime(long lastAttackTime) { + this.lastAttackTime = lastAttackTime; + } - //add min/max damage bonuses for weapon **REMOVED + public ConcurrentHashMap getPlayerAgroMap() { + return playerAgroMap; + } - //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)))); + public long getDeathTime() { + return deathTime; + } - 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."); + public void setDeathTime(long deathTime) { + this.deathTime = deathTime; + } - //add Base damage last. - float minDamageMod = this.mobBase.getDamageMin(); - float maxDamageMod = this.mobBase.getDamageMax(); + public boolean isHasLoot() { + return hasLoot; + } - minDamage += minDamageMod; - maxDamage += maxDamageMod; + public DeferredPowerJob getWeaponPower() { + return weaponPower; + } - // 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); + public void setWeaponPower(DeferredPowerJob weaponPower) { + this.weaponPower = weaponPower; + } - // 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) { + public ConcurrentHashMap getSiegeMinionMap() { + return siegeMinionMap; + } - 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; + public Building getBuilding() { + return this.building; + } + public DateTime getUpgradeDateTime() { + lock.readLock().lock(); - BuildingModelBase buildingModel = BuildingModelBase.getModelBase(mob.building.getMeshUUID()); + try { + return upgradeDateTime; + } finally { + lock.readLock().unlock(); + } + } - if (buildingModel == null) - return -1; + public synchronized Mob createGuardMob(int loadID, Guild guild, Zone parent, Vector3fImmutable loc, short level, String pirateName) { - - if (mob.building.getHirelings().containsKey(mob)) - slot = (mob.building.getHirelings().get(mob)); - + MobBase minionMobBase; + Mob mob; + int maxSlots = 1; - if (buildingModel.getNPCLocation(slot) == null) - return -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; - return slot; - } + mob.addEffectNoTimer(Integer.toString(eb.getUUID()), eb, mbe.getRank(), true); + } + } - 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; + int slot = 0; + slot += siegeMinionMap.size() + 1; - // *** Refactor : Need to take a look at this, make sure - // npc's are loaded in correct spots. + 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; - 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 + return mob; + } - if (me != null) { + public Contract getContract() { + return contract; + } - ItemBase ib = me.getItemBase(); + public void setContract(Contract contract) { + this.contract = contract; + } - if (ib != null) - return ib; + public boolean isPlayerGuard() { + return isPlayerGuard; + } - } - } - } - MobBase mb = this.mobBase; + public void setPlayerGuard(boolean isPlayerGuard) { + this.isPlayerGuard = isPlayerGuard; + } - 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; - } + public int getPatrolPointIndex() { + return patrolPointIndex; + } - @Override - public void runAfterLoad() { + public void setPatrolPointIndex(int patrolPointIndex) { + this.patrolPointIndex = patrolPointIndex; + } - try{ - if (this.equipmentSetID != 0) - this.equip = MobBase.loadEquipmentSet(this.equipmentSetID); - else - this.equip = new HashMap<>(); + public int getLastMobPowerToken() { + return lastMobPowerToken; + } - } catch(Exception e){ - Logger.error( e.getMessage()); - } - mobPowers = new HashMap(); - //mobPowers = DbManager.MobBaseQueries.LOAD_STATIC_POWERS(this.getMobBaseID()); - if(PowersManager.AllMobPowers.containsKey(this.getMobBaseID()) == true){ - mobPowers = PowersManager.AllMobPowers.get(this.getMobBaseID()); - } - 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()); - } + public void setLastMobPowerToken(int lastMobPowerToken) { + this.lastMobPowerToken = lastMobPowerToken; + } - recalculateStats(); - this.setHealth(this.healthMax); + public Regions getLastRegion() { + return lastRegion; + } - // Set bounds for this mobile - Bounds mobBounds = Bounds.borrow(); - mobBounds.setBounds(this.getLoc()); - this.setBounds(mobBounds); + public void setLastRegion(Regions lastRegion) { + this.lastRegion = lastRegion; + } - } catch (Exception e){ - Logger.error(e.getMessage()); - } - } + public boolean isLootSync() { + return lootSync; + } - @Override - protected ConcurrentHashMap initializePowers() { - return new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); - } + public void setLootSync(boolean lootSync) { + this.lootSync = lootSync; + } - public boolean canSee(PlayerCharacter target) { - return this.mobBase.getSeeInvis() >= target.getHidden(); - } + public int getFidalityID() { + return fidalityID; + } - public int getBuildingID() { - return buildingID; - } + public HashMap getEquip() { + return equip; + } - public void setBuildingID(int buildingID) { - this.buildingID = buildingID; - } + public int getEquipmentSetID() { + return equipmentSetID; + } - public boolean isSiege() { - return isSiege; - } + public int getLootSet() { + return lootSet; + } - public void setSiege(boolean isSiege) { - this.isSiege = isSiege; - } + public boolean isGuard() { + return this.isGuard; + } - public long getTimeToSpawnSiege() { - return timeToSpawnSiege; - } + public String getNameOverride() { + return nameOverride; + } - public void setTimeToSpawnSiege(long timeToSpawnSiege) { - this.timeToSpawnSiege = timeToSpawnSiege; - } + public void processUpgradeMob(PlayerCharacter player) { - public AbstractCharacter getNpcOwner() { - return npcOwner; - } + lock.writeLock().lock(); - public void setNpcOwner(AbstractCharacter npcOwner) { - this.npcOwner = npcOwner; - } + try { - public boolean isNecroPet() { - return this.mobBase.isNecroPet(); - } - - public static void HandleAssistedAggro(PlayerCharacter source, PlayerCharacter target) { - - HashSet 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; + building = this.getBuilding(); - //Mob not attacking target's target, let's not be failmu and skip this target. - if (mob.getCombatTarget() != target) - continue; + // Cannot upgrade an npc not within a building - //target is mob's combat target, LETS GO. - if (source.getHateValue() > target.getHateValue()) { - mob.setCombatTarget(source); - MobileFSM.setAggro(mob, source.getObjectUUID()); - } - } - } + if (building == null) + return; - public void handleDirectAggro(AbstractCharacter ac) { + // Cannot upgrade an npc at max rank - if (ac.getObjectType().equals(GameObjectType.PlayerCharacter) == false) - return; + if (this.getRank() == 7) + return; - PlayerCharacter player = (PlayerCharacter)ac; + // Cannot upgrade an npc who is currently ranking - if (this.getCombatTarget() == null) { - MobileFSM.setAggro(this, player.getObjectUUID()); - return; - } + if (this.isRanking()) + return; - if (player.getObjectUUID() == this.getCombatTarget().getObjectUUID()) - return; + int rankCost = Mob.getUpgradeCost(this); - if (this.getCombatTarget().getObjectType() == GameObjectType.PlayerCharacter) { + // SEND NOT ENOUGH GOLD ERROR - if (ac.getHateValue() > ((PlayerCharacter) this.getCombatTarget()).getHateValue()) { - this.setCombatTarget(player); - MobileFSM.setAggro(this, player.getObjectUUID()); - } - } - } + if (rankCost > building.getStrongboxValue()) { + sendErrorPopup(player, 127); + return; + } - public boolean remove(Building building) { + try { - // Remove npc from it's building - this.state = STATE.Disabled; + if (!building.transferGold(-rankCost, false)) { + return; + } - try { - this.clearEffects(); - }catch(Exception e){ - Logger.error(e.getMessage()); - } + DateTime dateToUpgrade = DateTime.now().plusHours(Mob.getUpgradeTime(this)); + Mob.setUpgradeDateTime(this, dateToUpgrade); - if (this.parentZone != null) - this.parentZone.zoneMobSet.remove(this); + // Schedule upgrade job - if (building != null) { - building.getHirelings().remove(this); - this.removeMinions(); - } + Mob.submitUpgradeJob(this); - // Delete npc from database + } catch (Exception e) { + PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity"); + } - if (DbManager.MobQueries.DELETE_MOB(this) == 0) - return false; + } catch (Exception e) { + Logger.error(e); + } finally { + lock.writeLock().unlock(); + } + } - // Remove npc from the simulation + public void processRedeedMob(ClientConnection origin) { - this.removeFromCache(); - DbManager.removeFromCache(this); - WorldGrid.RemoveWorldObject(this); - WorldGrid.removeObject(this); - return true; - } + // Member variable declaration + PlayerCharacter player; + Contract contract; + CharacterItemManager itemMan; + ItemBase itemBase; + Item item; - public void removeMinions() { + this.lock.writeLock().lock(); - for (Mob toRemove : this.siegeMinionMap.keySet()) { + try { - toRemove.state = STATE.Disabled; + player = SessionManager.getPlayerCharacter(origin); + itemMan = player.getCharItemManager(); - if (this.isMoving()){ - - this.stopMovement(this.getLoc()); - this.state = STATE.Disabled; - if (toRemove.parentZone != null) - toRemove.parentZone.zoneMobSet.remove(toRemove); - } + contract = this.getContract(); - try { - toRemove.clearEffects(); - } catch(Exception e){ - Logger.error(e.getMessage()); - } + if (!player.getCharItemManager().hasRoomInventory((short) 1)) { + ErrorPopupMsg.sendErrorPopup(player, 21); + return; + } - if (toRemove.parentZone != null) - toRemove.parentZone.zoneMobSet.remove(toRemove); - WorldGrid.RemoveWorldObject(toRemove); - WorldGrid.removeObject(toRemove); - DbManager.removeFromCache(toRemove); + if (!building.getHirelings().containsKey(this)) + return; - PlayerCharacter petOwner = toRemove.getOwner(); + if (!this.remove(building)) { + PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity"); + return; + } - if (petOwner != null) { + building.getHirelings().remove(this); - petOwner.setPet(null); - toRemove.setOwner(null); + itemBase = ItemBase.getItemBase(contract.getContractID()); - PetMsg petMsg = new PetMsg(5, null); - Dispatch dispatch = Dispatch.borrow(petOwner, petMsg); - DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY); - } - } - } + if (itemBase == null) { + Logger.error("Could not find Contract for npc: " + this.getObjectUUID()); + return; + } - public static void submitUpgradeJob(Mob mob) { + boolean itemWorked = false; - JobContainer jc; + 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; - if (mob.getUpgradeDateTime() == null) { - Logger.error("Failed to get Upgrade Date"); - return; - } + try { + item = DbManager.ItemQueries.ADD_ITEM(item); + itemWorked = true; + } catch (Exception e) { + Logger.error(e); + } + if (itemWorked) { + itemMan.addItemToInventory(item); + itemMan.updateInventory(); + } - // Submit upgrade job for future date or current instant + ManageCityAssetsMsg mca = new ManageCityAssetsMsg(); + mca.actionType = NPC.SVR_CLOSE_WINDOW; + mca.setTargetType(building.getObjectType().ordinal()); + mca.setTargetID(building.getObjectUUID()); + origin.sendMsg(mca); - if (mob.getUpgradeDateTime().isAfter(DateTime.now())) - jc = JobScheduler.getInstance().scheduleJob(new UpgradeNPCJob(mob), - mob.getUpgradeDateTime().getMillis()); - else - JobScheduler.getInstance().scheduleJob(new UpgradeNPCJob(mob), 0); - } + } catch (Exception e) { + Logger.error(e); + } finally { + this.lock.writeLock().unlock(); + } - public void setRank(int newRank) { + } - DbManager.MobQueries.SET_PROPERTY(this, "mob_level", newRank); - this.level = (short) newRank; + public void dismiss() { - } + if (this.isPet()) { - public static int getUpgradeTime(Mob mob) { + if (this.isSummonedPet()) { //delete summoned pet - if (mob.getRank() < 7) - return (mob.getRank() * 8); + WorldGrid.RemoveWorldObject(this); + DbManager.removeFromCache(this); + if (this.getObjectType() == GameObjectType.Mob) { + this.setState(STATE.Disabled); + if (this.getParentZone() != null) + this.getParentZone().zoneMobSet.remove(this); + } - return 0; - } + } else { //revert charmed pet + this.setMob(); + this.setCombatTarget(null); + // if (this.isAlive()) + // WorldServer.updateObject(this); + } + //clear owner + PlayerCharacter owner = this.getOwner(); - public static int getUpgradeCost(Mob mob) { + //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); - int upgradeCost; + if (pet != null && pet.getObjectUUID() == this.getObjectUUID()) + owner.setPet(null); - upgradeCost = Integer.MAX_VALUE; + if (this.getObjectType().equals(GameObjectType.Mob)) + this.setOwner(null); + } - if (mob.getRank() < 7) - return (mob.getRank() * 100650) + 21450; - return upgradeCost; - } + } + } - public boolean isRanking() { + public void dismissNecroPet(boolean updateOwner) { - return this.upgradeDateTime != null; - } + this.state = STATE.Disabled; - public boolean isNoAggro() { - return noAggro; - } + this.combatTarget = null; + this.hasLoot = false; - public void setNoAggro(boolean noAggro) { - this.noAggro = noAggro; - } + if (this.parentZone != null) + this.parentZone.zoneMobSet.remove(this); - public STATE getState() { - return state; - } + try { + this.clearEffects(); + } catch (Exception e) { + Logger.error(e.getMessage()); + } + this.playerAgroMap.clear(); + WorldGrid.RemoveWorldObject(this); - public void setState(STATE state) { - this.state = state; - } + DbManager.removeFromCache(this); - public int getAggroTargetID() { - return aggroTargetID; - } + // YEAH BONUS CODE! THANKS UNNAMED ASSHOLE! + //WorldServer.removeObject(this); + //WorldGrid.INSTANCE.removeWorldObject(this); + //owner.getPet().disableIntelligence(); - public void setAggroTargetID(int aggroTargetID) { - this.aggroTargetID = aggroTargetID; - } + PlayerCharacter petOwner = this.getOwner(); - public boolean isWalkingHome() { - return walkingHome; - } + if (petOwner != null) { + this.setOwner(null); + petOwner.setPet(null); - public void setWalkingHome(boolean walkingHome) { - this.walkingHome = walkingHome; - } + if (updateOwner == false) + return; + PetMsg petMsg = new PetMsg(5, null); + Dispatch dispatch = Dispatch.borrow(petOwner, petMsg); + DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY); + } + } - public long getLastAttackTime() { - return lastAttackTime; - } - public void setLastAttackTime(long lastAttackTime) { - this.lastAttackTime = lastAttackTime; - } - - public ConcurrentHashMap 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 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 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); - } - } - - - - }