From aff2a8fa0e014471c3853cb5d8aca80f39722ca5 Mon Sep 17 00:00:00 2001 From: FatBoy-DOTC Date: Wed, 27 Mar 2024 17:17:34 -0500 Subject: [PATCH] ABS char skill system --- .../db/handlers/dbPlayerCharacterHandler.java | 9 +- src/engine/devcmd/cmds/InfoCmd.java | 6 +- src/engine/gameManager/ChatManager.java | 2 +- src/engine/gameManager/PowersManager.java | 6 +- src/engine/mobileAI/MobAI.java | 4 +- .../handlers/ArcLoginNotifyMsgHandler.java | 7 +- .../client/handlers/ChangeRankHandler.java | 2 +- .../handlers/VendorDialogMsgHandler.java | 4 +- src/engine/net/client/msg/WhoResponseMsg.java | 9 +- src/engine/objects/AbstractCharacter.java | 478 ++++++++++++++- src/engine/objects/CharacterPower.java | 28 +- src/engine/objects/CharacterSkill.java | 20 +- src/engine/objects/Mob.java | 45 -- src/engine/objects/PlayerBonuses.java | 12 +- src/engine/objects/PlayerCharacter.java | 562 +----------------- src/engine/objects/PowerGrant.java | 4 +- 16 files changed, 542 insertions(+), 656 deletions(-) diff --git a/src/engine/db/handlers/dbPlayerCharacterHandler.java b/src/engine/db/handlers/dbPlayerCharacterHandler.java index 59b48a78..cfb672e8 100644 --- a/src/engine/db/handlers/dbPlayerCharacterHandler.java +++ b/src/engine/db/handlers/dbPlayerCharacterHandler.java @@ -11,10 +11,7 @@ package engine.db.handlers; import engine.Enum; import engine.gameManager.DbManager; -import engine.objects.AbstractWorldObject; -import engine.objects.Heraldry; -import engine.objects.PlayerCharacter; -import engine.objects.PlayerFriends; +import engine.objects.*; import engine.server.MBServerStatics; import org.pmw.tinylog.Logger; @@ -45,8 +42,8 @@ public class dbPlayerCharacterHandler extends dbHandlerBase { preparedStatement.setLong(1, toAdd.getAccount().getObjectUUID()); preparedStatement.setString(2, toAdd.getFirstName()); preparedStatement.setString(3, toAdd.getLastName()); - preparedStatement.setInt(4, toAdd.getRace().getRaceRuneID()); - preparedStatement.setInt(5, toAdd.getBaseClass().getObjectUUID()); + preparedStatement.setInt(4, toAdd.race.getRaceRuneID()); + preparedStatement.setInt(5, toAdd.baseClass.getObjectUUID()); preparedStatement.setInt(6, toAdd.getStrMod()); preparedStatement.setInt(7, toAdd.getDexMod()); preparedStatement.setInt(8, toAdd.getConMod()); diff --git a/src/engine/devcmd/cmds/InfoCmd.java b/src/engine/devcmd/cmds/InfoCmd.java index 1f8b059e..07fce9bd 100644 --- a/src/engine/devcmd/cmds/InfoCmd.java +++ b/src/engine/devcmd/cmds/InfoCmd.java @@ -253,9 +253,9 @@ public class InfoCmd extends AbstractDevCmd { output += newline; output += "InSession : " + SessionManager.getPlayerCharacterByID(target.getObjectUUID()) != null ? " true " : " false"; output += newline; - output += "RaceType: " + targetPC.getRace().getRaceType().name(); + output += "RaceType: " + targetPC.race.getRaceType().name(); output += newline; - output += "Race: " + targetPC.getRace().getName(); + output += "Race: " + targetPC.race.getName(); output += newline; output += "Safe:" + targetPC.inSafeZone(); output += newline; @@ -291,7 +291,7 @@ public class InfoCmd extends AbstractDevCmd { output += "inFloor :" + targetPC.getInFloorID(); output += newline; - BaseClass baseClass = targetPC.getBaseClass(); + BaseClass baseClass = targetPC.baseClass; if (baseClass != null) output += StringUtils.addWS("Class: " + baseClass.getName(), 20); diff --git a/src/engine/gameManager/ChatManager.java b/src/engine/gameManager/ChatManager.java index 1361a1e7..48914dc2 100644 --- a/src/engine/gameManager/ChatManager.java +++ b/src/engine/gameManager/ChatManager.java @@ -412,7 +412,7 @@ public enum ChatManager { chatGuildMsg.setUnknown04(sender.getGuild() != null ? sender.getGuild() .getCharter() : 0); // Charter? chatGuildMsg.setUnknown05(GuildStatusController.getTitle(sender.getGuildStatus())); // Title? - chatGuildMsg.setUnknown06(sender.getRace().getRaceType().getCharacterSex().equals(Enum.CharacterSex.MALE) ? 1 : 2); // isMale?, seen 1 and 2 + chatGuildMsg.setUnknown06(sender.race.getRaceType().getCharacterSex().equals(Enum.CharacterSex.MALE) ? 1 : 2); // isMale?, seen 1 and 2 // Send dispatch to each player diff --git a/src/engine/gameManager/PowersManager.java b/src/engine/gameManager/PowersManager.java index e7dce3ad..baf4c252 100644 --- a/src/engine/gameManager/PowersManager.java +++ b/src/engine/gameManager/PowersManager.java @@ -1188,8 +1188,8 @@ public enum PowersManager { PlayerCharacter pc = (PlayerCharacter) target; int raceID = 0; - if (pc.getRace() != null) - raceID = pc.getRace().getRaceRuneID(); + if (pc.race != null) + raceID = pc.race.getRaceRuneID(); switch (mtp) { case "Shade": @@ -1334,7 +1334,7 @@ public enum PowersManager { timers.get("Summon").cancelJob(); // get time to wait before summons goes through - BaseClass base = source.getBaseClass(); + BaseClass base = source.baseClass; PromotionClass promo = source.getPromotionClass(); int duration; diff --git a/src/engine/mobileAI/MobAI.java b/src/engine/mobileAI/MobAI.java index 22177141..3a40c612 100644 --- a/src/engine/mobileAI/MobAI.java +++ b/src/engine/mobileAI/MobAI.java @@ -609,12 +609,12 @@ public class MobAI { // No aggro for this race type - if (aiAgent.notEnemy.size() > 0 && aiAgent.notEnemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType()) == true) + if (aiAgent.notEnemy.size() > 0 && aiAgent.notEnemy.contains(loadedPlayer.race.getRaceType().getMonsterType()) == true) continue; //mob has enemies and this player race is not it - if (aiAgent.enemy.size() > 0 && aiAgent.enemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType()) == false) + if (aiAgent.enemy.size() > 0 && aiAgent.enemy.contains(loadedPlayer.race.getRaceType().getMonsterType()) == false) continue; if (MovementUtilities.inRangeToAggro(aiAgent, loadedPlayer)) { diff --git a/src/engine/net/client/handlers/ArcLoginNotifyMsgHandler.java b/src/engine/net/client/handlers/ArcLoginNotifyMsgHandler.java index 02b0518c..88603c77 100644 --- a/src/engine/net/client/handlers/ArcLoginNotifyMsgHandler.java +++ b/src/engine/net/client/handlers/ArcLoginNotifyMsgHandler.java @@ -12,10 +12,7 @@ import engine.net.client.msg.ArcLoginNotifyMsg; import engine.net.client.msg.ClientNetMsg; import engine.net.client.msg.HotzoneChangeMsg; import engine.net.client.msg.PetMsg; -import engine.objects.Account; -import engine.objects.Guild; -import engine.objects.PlayerCharacter; -import engine.objects.PlayerFriends; +import engine.objects.*; import engine.server.MBServerStatics; import engine.session.Session; import org.pmw.tinylog.Logger; @@ -73,7 +70,7 @@ public class ArcLoginNotifyMsgHandler extends AbstractClientMsgHandler { ChatManager.sendSystemMessage(player, ConfigManager.currentRepoBranch); // Set player mask for QT - if (player.getRace() != null && player.getRace().getToken() == -524731385) + if (player.race != null && player.race.getToken() == -524731385) player.setObjectTypeMask(MBServerStatics.MASK_PLAYER | MBServerStatics.MASK_UNDEAD); else player.setObjectTypeMask(MBServerStatics.MASK_PLAYER); diff --git a/src/engine/net/client/handlers/ChangeRankHandler.java b/src/engine/net/client/handlers/ChangeRankHandler.java index 36b5fcaf..db3e48be 100644 --- a/src/engine/net/client/handlers/ChangeRankHandler.java +++ b/src/engine/net/client/handlers/ChangeRankHandler.java @@ -66,7 +66,7 @@ public class ChangeRankHandler extends AbstractClientMsgHandler { targetPlayer.setGuildTitle(msg.getNewRank()); targetName = targetPlayer.getFirstName(); - isMale = targetPlayer.getRace().getRaceType().getCharacterSex().equals(Enum.CharacterSex.MALE); + isMale = targetPlayer.race.getRaceType().getCharacterSex().equals(Enum.CharacterSex.MALE); } else { DbManager.GuildQueries.UPDATE_GUILD_RANK_OFFLINE(msg.getPlayerUUID(), msg.getNewRank(), sourcePlayer.getGuild().getObjectUUID()); diff --git a/src/engine/net/client/handlers/VendorDialogMsgHandler.java b/src/engine/net/client/handlers/VendorDialogMsgHandler.java index 567da175..a4a707c6 100644 --- a/src/engine/net/client/handlers/VendorDialogMsgHandler.java +++ b/src/engine/net/client/handlers/VendorDialogMsgHandler.java @@ -376,14 +376,14 @@ public class VendorDialogMsgHandler extends AbstractClientMsgHandler { } // verify race valid for profession - Race race = pc.getRace(); + Race race = pc.race; if (race == null || !promo.isAllowedRune(race.getToken())) { // TODO send client promotion error return; } // verify baseclass valid for profession - BaseClass bc = pc.getBaseClass(); + BaseClass bc = pc.baseClass; if (bc == null || !promo.isAllowedRune(bc.getToken())) { // TODO send client promotion error return; diff --git a/src/engine/net/client/msg/WhoResponseMsg.java b/src/engine/net/client/msg/WhoResponseMsg.java index dc27c00b..6242c427 100644 --- a/src/engine/net/client/msg/WhoResponseMsg.java +++ b/src/engine/net/client/msg/WhoResponseMsg.java @@ -14,10 +14,7 @@ import engine.gameManager.SessionManager; import engine.net.*; import engine.net.client.ClientConnection; import engine.net.client.Protocol; -import engine.objects.Guild; -import engine.objects.GuildStatusController; -import engine.objects.PlayerCharacter; -import engine.objects.PromotionClass; +import engine.objects.*; import engine.server.MBServerStatics; import org.pmw.tinylog.Logger; @@ -91,7 +88,7 @@ public class WhoResponseMsg extends ClientNetMsg { if (player != null) if (!isAdmin(player)) if (player.isActive()) { - String[] race = player.getRace().getName().split(","); + String[] race = player.race.getName().split(","); if (filter.compareTo(race[0]) == 0) if (!HandleSet(set, player, playerCharacter, msg)) break; @@ -101,7 +98,7 @@ public class WhoResponseMsg extends ClientNetMsg { if (player != null) if (!isAdmin(player)) if (player.isActive()) { - if (filter.compareTo(player.getBaseClass().getName()) == 0 || (player.getPromotionClass() != null && filter.compareTo(player.getPromotionClass().getName()) == 0)) + if (filter.compareTo(player.baseClass.getName()) == 0 || (player.getPromotionClass() != null && filter.compareTo(player.getPromotionClass().getName()) == 0)) if (!HandleSet(set, player, playerCharacter, msg)) break; diff --git a/src/engine/objects/AbstractCharacter.java b/src/engine/objects/AbstractCharacter.java index 43637563..072e377a 100644 --- a/src/engine/objects/AbstractCharacter.java +++ b/src/engine/objects/AbstractCharacter.java @@ -136,6 +136,16 @@ public abstract class AbstractCharacter extends AbstractWorldObject { public Enum.SexType absGender = null; public EnumSet absDisciplines; + // Modifiers + public short statStrBase; + public short statDexBase; + public short statConBase; + public short statIntBase; + public short statSpiBase; + public Race race; + public BaseClass baseClass; + public PromotionClass promotionClass; + public AbstractCharacter() { super(); this.firstName = ""; @@ -468,7 +478,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject { //do this after all bonus updates, but before recalculations. // recalculate everything //calculate item bonuses - playerCharacter.calculateItemBonuses(); + calculateItemBonuses(playerCharacter); //recalculate formulas PlayerCharacter.recalculatePlayerStatsOnLoad(playerCharacter); @@ -587,6 +597,470 @@ public abstract class AbstractCharacter extends AbstractWorldObject { } + /** + * @ Calculates Atr (both hands) Defense, and Damage for pc + * @param playerCharacter + */ + public static void calculateAtrDefenseDamage(AbstractCharacter playerCharacter) { + if (playerCharacter.charItemManager == null || playerCharacter.charItemManager.getEquipped() == null || playerCharacter.skills == null) { + Logger.error("Player " + playerCharacter.getObjectUUID() + " missing skills or equipment"); + defaultAtrAndDamage(playerCharacter,true); + defaultAtrAndDamage(playerCharacter,false); + playerCharacter.defenseRating = 0; + return; + } + ConcurrentHashMap equipped = playerCharacter.charItemManager.getEquipped(); + + // // Reset passives + // if (this.bonuses != null) { + // this.bonuses.setBool("Block", false); + // this.bonuses.setBool("Parry", false); + // if (this.baseClass != null && this.baseClass.getUUID() == 2502) + // this.bonuses.setBool("Dodge", true); + // else + // this.bonuses.setBool("Dodge", false); + // } + // calculate atr and damage for each hand + calculateAtrDamageForWeapon(playerCharacter,equipped.get(EquipSlotType.RHELD), true, equipped.get(EquipSlotType.RHELD)); + calculateAtrDamageForWeapon(playerCharacter,equipped.get(EquipSlotType.LHELD), false, equipped.get(EquipSlotType.LHELD)); + + // No Defense while in DeathShroud + if (playerCharacter.effects != null && playerCharacter.effects.containsKey("DeathShroud")) + playerCharacter.defenseRating = (short) 0; + else { + // calculate defense for equipment + float defense = playerCharacter.statDexCurrent * 2; + defense += getShieldDefense(playerCharacter,equipped.get(EquipSlotType.LHELD)); + defense += getArmorDefense(playerCharacter,equipped.get(EquipSlotType.HELM)); + defense += getArmorDefense(playerCharacter,equipped.get(EquipSlotType.CHEST)); + defense += getArmorDefense(playerCharacter,equipped.get(EquipSlotType.UPARM)); + defense += getArmorDefense(playerCharacter,equipped.get(EquipSlotType.HANDS)); + defense += getArmorDefense(playerCharacter,equipped.get(EquipSlotType.LEGS)); + defense += getArmorDefense(playerCharacter,equipped.get(EquipSlotType.FEET)); + defense += getWeaponDefense(playerCharacter,equipped); + + if (playerCharacter.bonuses != null) { + // add any bonuses + defense += (short) playerCharacter.bonuses.getFloat(ModType.DCV, SourceType.NONE); + + // Finally multiply any percent modifiers. DO THIS LAST! + float pos_Bonus = playerCharacter.bonuses.getFloatPercentPositive(ModType.DCV, SourceType.NONE); + defense = (short) (defense * (1 + pos_Bonus)); + + //Lucky rune applies next + //applied runes will be calculated and added to the normal bonuses. no need for this garbage anymore + //defense = (short) (defense * (1 + ((float) this.bonuses.getShort("rune.Defense") / 100))); + + //and negative percent modifiers + //already done... + float neg_Bonus = playerCharacter.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; + playerCharacter.defenseRating = (short) (defense + 0.5f); + } + } + + /** + * @ Calculates Atr, and Damage for each weapon + */ + private static void calculateAtrDamageForWeapon(AbstractCharacter playerCharacter, Item weapon, boolean mainHand, Item otherHand) { + + // make sure weapon exists + boolean noWeapon = false; + ItemBase wb = null; + if (weapon == null) + noWeapon = true; + else { + ItemBase ib = weapon.getItemBase(); + if (ib == null) + noWeapon = true; + else if (!weapon.template.item_type.equals(ItemType.WEAPON)) { + defaultAtrAndDamage(playerCharacter,mainHand); + return; + } else + wb = ib; + } + float skillPercentage, masteryPercentage; + float mastDam; + float min, max; + float speed = 20f; + boolean strBased = false; + + ItemBase wbMain = (weapon != null) ? weapon.getItemBase() : null; + ItemBase wbOff = (otherHand != null) ? otherHand.getItemBase() : null; + + // get skill percentages and min and max damage for weapons + if (noWeapon) { + if (mainHand) { + Item off = playerCharacter.charItemManager.getEquipped().get(EquipSlotType.LHELD); + if (off != null && off.getItemBase() != null && off.template.item_type.equals(ItemType.WEAPON)) + playerCharacter.rangeHandOne = 10 * (1 + (playerCharacter.statStrBase / 600)); // Set + // to + // no + // weapon + // range + else + playerCharacter.rangeHandOne = -1; // set to do not attack + } else + playerCharacter.rangeHandTwo = -1; // set to do not attack + + skillPercentage = getModifiedAmount(playerCharacter.skills.get("Unarmed Combat")); + masteryPercentage = getModifiedAmount(playerCharacter.skills.get("Unarmed Combat Mastery")); + if (masteryPercentage == 0f) + mastDam = CharacterSkill.getQuickMastery(playerCharacter, "Unarmed Combat Mastery"); + else + mastDam = masteryPercentage; + // TODO Correct these + min = 1; + max = 3; + } else { + if (mainHand) + playerCharacter.rangeHandOne = weapon.getItemBase().getRange() * (1 + (playerCharacter.statStrBase / 600)); + else + playerCharacter.rangeHandTwo = weapon.getItemBase().getRange() * (1 + (playerCharacter.statStrBase / 600)); + + if (playerCharacter.bonuses != null) { + float range_bonus = 1 + playerCharacter.bonuses.getFloatPercentAll(ModType.WeaponRange, SourceType.NONE); + + if (mainHand) + playerCharacter.rangeHandOne *= range_bonus; + else + playerCharacter.rangeHandTwo *= range_bonus; + + } + skillPercentage = getModifiedAmount(playerCharacter.skills.get(weapon.template.item_skill_used)); + masteryPercentage = getModifiedAmount(playerCharacter.skills.get(wb.getMastery())); + if (masteryPercentage == 0f) + mastDam = 0f; + // mastDam = CharacterSkill.getQuickMastery(this, wb.getMastery()); + else + mastDam = masteryPercentage; + min = (float) wb.getMinDamage(); + max = (float) wb.getMaxDamage(); + strBased = wb.isStrBased(); + + // + // Add parry bonus for weapon and allow parry if needed + + // // Only Fighters and Thieves can Parry + // if ((this.baseClass != null && this.baseClass.getUUID() == 2500) + // || (this.promotionClass != null && this.promotionClass.getUUID() == 2520)) { + // if (wbMain == null || wbMain.getRange() < MBServerStatics.RANGED_WEAPON_RANGE) + // if (wbOff == null || wbOff.getRange() < MBServerStatics.RANGED_WEAPON_RANGE) + // this.bonuses.setBool("Parry", true); + // } + // } + } + + if (playerCharacter.effects != null && playerCharacter.effects.containsKey("DeathShroud")) + // No Atr in deathshroud. + if (mainHand) + playerCharacter.atrHandOne = (short) 0; + else + playerCharacter.atrHandTwo = (short) 0; + else { + // calculate atr + float atr = 0; + atr += (int) skillPercentage * 4f; //<-round down skill% - + atr += (int) masteryPercentage * 3f; + if (playerCharacter.statStrCurrent > playerCharacter.statDexCurrent) + atr += playerCharacter.statStrCurrent / 2; + else + atr += playerCharacter.statDexCurrent / 2; + + // add in any bonuses to atr + if (playerCharacter.bonuses != null) { + // Add any base bonuses + atr += playerCharacter.bonuses.getFloat(ModType.OCV, SourceType.NONE); + + // Finally use any multipliers. DO THIS LAST! + float pos_Bonus = (1 + playerCharacter.bonuses.getFloatPercentPositive(ModType.OCV, SourceType.NONE)); + atr *= pos_Bonus; + + // next precise + //runes will have their own bonuses. + // atr *= (1 + ((float) this.bonuses.getShort("rune.Attack") / 100)); + + //and negative percent modifiers + float neg_Bonus = playerCharacter.bonuses.getFloatPercentNegative(ModType.OCV, SourceType.NONE); + + atr *= (1 + neg_Bonus); + } + + atr = (atr < 1) ? 1 : atr; + + // set atr + if (mainHand) + playerCharacter.atrHandOne = (short) (atr + 0.5f); + else + playerCharacter.atrHandTwo = (short) (atr + 0.5f); + } + + //calculate speed + if (wb != null) + speed = wb.getSpeed(); + else + speed = 20f; //unarmed attack speed + if (weapon != null) + speed *= (1 + playerCharacter.bonuses.getFloatPercentAll(ModType.WeaponSpeed, SourceType.NONE)); + speed *= (1 + playerCharacter.bonuses.getFloatPercentAll(ModType.AttackDelay, SourceType.NONE)); + if (speed < 10) + speed = 10; + + //add min/max damage bonuses for weapon + if (weapon != null) { + // Add any base bonuses + + min += weapon.getBonus(ModType.MinDamage, SourceType.NONE); + max += weapon.getBonus(ModType.MaxDamage, SourceType.NONE); + + min += weapon.getBonus(ModType.MeleeDamageModifier, SourceType.NONE); + max += weapon.getBonus(ModType.MeleeDamageModifier, SourceType.NONE); + // Finally use any multipliers. DO THIS LAST! + + float percentMinDamage = 1; + float percentMaxDamage = 1; + + percentMinDamage += weapon.getBonusPercent(ModType.MinDamage, SourceType.NONE); + percentMinDamage += weapon.getBonusPercent(ModType.MeleeDamageModifier, SourceType.NONE); + + percentMaxDamage += weapon.getBonusPercent(ModType.MaxDamage, SourceType.NONE); + percentMaxDamage += weapon.getBonusPercent(ModType.MeleeDamageModifier, SourceType.NONE); + + + min *= percentMinDamage; + max *= percentMaxDamage; + } + + //if duel wielding, cut damage by 30% + if (otherHand != null) { + ItemBase ibo = otherHand.getItemBase(); + if (ibo != null && otherHand.template.equals(ItemType.WEAPON)) { + min *= 0.7f; + max *= 0.7f; + } + } + + // calculate damage + float minDamage; + float maxDamage; + float pri = (strBased) ? (float) playerCharacter.statStrCurrent : (float) playerCharacter.statDexCurrent; + float sec = (strBased) ? (float) playerCharacter.statDexCurrent : (float) playerCharacter.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 + + // Half damage if in death shroud + if (playerCharacter.effects != null && playerCharacter.effects.containsKey("DeathShroud")) { + minDamage *= 0.5f; + maxDamage *= 0.5f; + } + + // add in any bonuses to damage + if (playerCharacter.bonuses != null) { + // Add any base bonuses + minDamage += playerCharacter.bonuses.getFloat(ModType.MinDamage, SourceType.NONE); + maxDamage += playerCharacter.bonuses.getFloat(ModType.MaxDamage, SourceType.NONE); + + minDamage += playerCharacter.bonuses.getFloat(ModType.MeleeDamageModifier, SourceType.NONE); + maxDamage += playerCharacter.bonuses.getFloat(ModType.MeleeDamageModifier, SourceType.NONE); + // Finally use any multipliers. DO THIS LAST! + + float percentMinDamage = 1; + float percentMaxDamage = 1; + + percentMinDamage += playerCharacter.bonuses.getFloatPercentAll(ModType.MinDamage, SourceType.NONE); + percentMinDamage += playerCharacter.bonuses.getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.NONE); + + percentMaxDamage += playerCharacter.bonuses.getFloatPercentAll(ModType.MaxDamage, SourceType.NONE); + percentMaxDamage += playerCharacter.bonuses.getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.NONE); + + minDamage *= percentMinDamage; + maxDamage *= percentMaxDamage; + + } + + // set damages + if (mainHand) { + playerCharacter.minDamageHandOne = (int) minDamage; + playerCharacter.maxDamageHandOne = (int) maxDamage; + playerCharacter.speedHandOne = speed; + } else { + playerCharacter.minDamageHandTwo = (int) minDamage; + playerCharacter.maxDamageHandTwo = (int) maxDamage; + playerCharacter.speedHandTwo = speed; + } + } + + /** + * @ Calculates Defense for shield + */ + private static float getShieldDefense(AbstractCharacter playerCharacter, Item shield) { + + if (shield == null) + return 0; + + if (ItemTemplate.isShield(shield) == false) + return 0; + + ItemBase ab = shield.getItemBase(); + + if (ab == null) + return 0; + + CharacterSkill blockSkill = playerCharacter.skills.get("Block"); + + float skillMod; + + if (blockSkill == null) { + skillMod = 0; + } else + skillMod = blockSkill.getModifiedAmount(); + + float def = ab.getDefense(); + + //apply item defense bonuses + if (shield != null) { + def += shield.getBonus(ModType.DR, SourceType.NONE); + def *= (1 + shield.getBonusPercent(ModType.DR, SourceType.NONE)); + + } + + // float val = ((float)ab.getDefense()) * (1 + (skillMod / 100)); + return (def * (1 + ((int) skillMod / 100f))); + } + + /** + * @ Calculates Defense for armor + */ + private static float getArmorDefense(AbstractCharacter playerCharacter, Item armor) { + + if (armor == null) + return 0; + + ItemBase ib = armor.getItemBase(); + + if (ib == null) + return 0; + + if (!armor.template.item_type.equals(ItemType.ARMOR)) + return 0; + + if (armor.template.item_skill_used.isEmpty()) + return ib.getDefense(); + + CharacterSkill armorSkill = playerCharacter.skills.get(armor.template.item_skill_used); + if (armorSkill == null) { + Logger.error("Player " + playerCharacter.getObjectUUID() + + " has armor equipped without the nescessary skill to equip it"); + return ib.getDefense(); + } + + float def = ib.getDefense(); + //apply item defense bonuses + if (armor != null) { + def += armor.getBonus(ModType.DR, SourceType.NONE); + def *= (1 + armor.getBonusPercent(ModType.DR, SourceType.NONE)); + } + + + return (def * (1 + ((int) armorSkill.getModifiedAmount() / 50f))); + } + + /** + * @ Calculates Defense for weapon + */ + private static float getWeaponDefense(AbstractCharacter playerCharacter, ConcurrentHashMap equipped) { + Item weapon = equipped.get(EquipSlotType.RHELD); + ItemBase wb = null; + CharacterSkill skill, mastery; + float val = 0; + boolean unarmed = false; + if (weapon == null) { + weapon = equipped.get(EquipSlotType.LHELD); + if (weapon == null || ItemTemplate.isShield(weapon)) + unarmed = true; + else + wb = weapon.getItemBase(); + } else + wb = weapon.getItemBase(); + if (wb == null) + unarmed = true; + if (unarmed) { + skill = playerCharacter.skills.get("Unarmed Combat"); + mastery = playerCharacter.skills.get("Unarmed Combat Mastery"); + } else { + skill = playerCharacter.skills.get(weapon.template.item_skill_used); + mastery = playerCharacter.skills.get(wb.getMastery()); + } + if (skill != null) + val += (int) skill.getModifiedAmount() / 2f; + if (mastery != null) + val += (int) mastery.getModifiedAmount() / 2f; + return val; + } + + //Don't call this function directly. linked from pc.calculateSkills() + //through SkillCalcJob. Designed to only run from one worker thread + public static void runSkillCalc(AbstractCharacter playerCharacter) { + try { + + //see if any new skills or powers granted + CharacterSkill.calculateSkills(playerCharacter); + // calculate granted Trains in powers. + CharacterPower.grantTrains(playerCharacter); + //see if any new powers unlocked from previous check + CharacterPower.calculatePowers(playerCharacter); + + } catch (Exception e) { + } + + } + + //calculate item bonuses here + public static void calculateItemBonuses(AbstractCharacter playerCharacter) { + if (playerCharacter.charItemManager == null || playerCharacter.bonuses == null) + return; + ConcurrentHashMap equipped = playerCharacter.charItemManager.getEquipped(); + for (Item item : equipped.values()) { + ItemBase ib = item.getItemBase(); + if (ib == null) + continue; + //TODO add effect bonuses in here for equipped items + } + } + + /** + * @ Defaults ATR, Defense and Damage for player + */ + private static void defaultAtrAndDamage(AbstractCharacter playerCharacter, boolean mainHand) { + if (mainHand) { + playerCharacter.atrHandOne = 0; + playerCharacter.minDamageHandOne = 0; + playerCharacter.maxDamageHandOne = 0; + playerCharacter.rangeHandOne = -1; + playerCharacter.speedHandOne = 20; + } else { + playerCharacter.atrHandTwo = 0; + playerCharacter.minDamageHandTwo = 0; + playerCharacter.maxDamageHandTwo = 0; + playerCharacter.rangeHandTwo = -1; + playerCharacter.speedHandTwo = 20; + } + } + + private static float getModifiedAmount(CharacterSkill skill) { + if (skill == null) + return 0f; + return skill.getModifiedAmount(); + } + private void initializeCharacter() { this.timers = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); this.timestamps = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); @@ -1850,7 +2324,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject { PlayerCharacter pc = (PlayerCharacter) this; //calculate item bonuses - pc.calculateItemBonuses(); + calculateItemBonuses(pc); //recalculate formulas pc.recalculatePlayerStats(true); diff --git a/src/engine/objects/CharacterPower.java b/src/engine/objects/CharacterPower.java index c220438f..f6181c8a 100644 --- a/src/engine/objects/CharacterPower.java +++ b/src/engine/objects/CharacterPower.java @@ -9,6 +9,7 @@ package engine.objects; +import engine.Enum; import engine.gameManager.DbManager; import engine.gameManager.PowersManager; import engine.net.ByteBufferWriter; @@ -97,28 +98,29 @@ public class CharacterPower extends AbstractGameObject { * This iterates through players runes and adds and removes powers as needed * Don't Call this directly. Instead call pc.calculateSkills(). */ - public static void calculatePowers(PlayerCharacter pc) { - if (pc == null) + public static void calculatePowers(AbstractCharacter absChar) { + if (absChar == null || absChar.getObjectType().equals(Enum.GameObjectType.PlayerCharacter) == false) return; + PlayerCharacter pc = (PlayerCharacter) absChar; // First add powers that don't exist ConcurrentHashMap powers = pc.getPowers(); // ArrayList genericPowers = PowerReq.getPowerReqsForAll(); // CharacterPower.grantPowers(genericPowers, powers, pc); - Race race = pc.getRace(); + Race race = pc.race; if (race != null) { CharacterPower.grantPowers(race.getPowersGranted(), powers, pc); } else Logger.error("Failed to find Race for player " + pc.getObjectUUID()); - BaseClass bc = pc.getBaseClass(); + BaseClass bc = pc.baseClass; if (bc != null) { CharacterPower.grantPowers(bc.getPowersGranted(), powers, pc); } else Logger.error("Failed to find BaseClass for player " + pc.getObjectUUID()); - PromotionClass promo = pc.getPromotionClass(); + PromotionClass promo = pc.promotionClass; if (promo != null) CharacterPower.grantPowers(promo.getPowersGranted(), powers, pc); - ArrayList runes = pc.getRunes(); + ArrayList runes = pc.runes; if (runes != null) { for (CharacterRune rune : runes) { CharacterPower.grantPowers(rune.getPowersGranted(), powers, pc); @@ -242,9 +244,11 @@ public class CharacterPower extends AbstractGameObject { } } - public static void grantTrains(PlayerCharacter pc) { - if (pc == null) + public static void grantTrains(AbstractCharacter absChar) { + if (absChar == null || absChar.getObjectType().equals(Enum.GameObjectType.PlayerCharacter) == false) return; + + PlayerCharacter pc = (PlayerCharacter) absChar; ConcurrentHashMap powers = pc.getPowers(); for (CharacterPower cp : powers.values()) { cp.grantedTrains = cp.getGrantedTrains(pc); @@ -526,13 +530,13 @@ public class CharacterPower extends AbstractGameObject { return false; ConcurrentHashMap powers = pc.getPowers(); - Race race = pc.getRace(); + Race race = pc.race; if (race != null) { if (!canRefine(race.getPowersGranted(), powers, pc)) return false; } else return false; - BaseClass bc = pc.getBaseClass(); + BaseClass bc = pc.baseClass; if (bc != null) { if (!canRefine(bc.getPowersGranted(), powers, pc)) return false; @@ -585,13 +589,13 @@ public class CharacterPower extends AbstractGameObject { return false; int token = this.power.getToken(); boolean valid = false; - Race race = pc.getRace(); + Race race = pc.race; if (race != null) { if (CharacterPower.powerAllowed(token, race.getPowersGranted(), pc)) return true; } else return false; - BaseClass bc = pc.getBaseClass(); + BaseClass bc = pc.baseClass; if (bc != null) { if (CharacterPower.powerAllowed(token, bc.getPowersGranted(), pc)) return true; diff --git a/src/engine/objects/CharacterSkill.java b/src/engine/objects/CharacterSkill.java index f2ba7e28..5785bfaf 100644 --- a/src/engine/objects/CharacterSkill.java +++ b/src/engine/objects/CharacterSkill.java @@ -378,7 +378,7 @@ public class CharacterSkill extends AbstractGameObject { if (pc == null) return 0; - if (pc.getRace() == null || pc.getBaseClass() == null) { + if (pc.race == null || pc.baseClass == null) { Logger.error("Race or BaseClass not found for player " + pc.getObjectUUID()); return 0; } @@ -388,12 +388,12 @@ public class CharacterSkill extends AbstractGameObject { int available = 0; //get racial bonus; - if (pc.getRace().getRaceType().equals(Enum.RaceType.HUMANMALE) || - pc.getRace().getRaceType().equals(Enum.RaceType.HUMANFEMALE)) + if (pc.race.getRaceType().equals(Enum.RaceType.HUMANMALE) || + pc.race.getRaceType().equals(Enum.RaceType.HUMANFEMALE)) raceBonus = 1; //Human racial bonus; //get base class trains - if (pc.getBaseClass().getObjectUUID() == 2500 || pc.getBaseClass().getObjectUUID() == 2502) { + if (pc.baseClass.getObjectUUID() == 2500 || pc.baseClass.getObjectUUID() == 2502) { baseMod = 4; //Fighter or Rogue } else { baseMod = 5; //Healer or Mage @@ -480,24 +480,26 @@ public class CharacterSkill extends AbstractGameObject { * This iterates through players runes and adds and removes skills as needed * Don't Call this directly. Instead call pc.calculateSkills(). */ - public static void calculateSkills(PlayerCharacter pc) { - if (pc == null) + public static void calculateSkills(AbstractCharacter absChar) { + if (absChar == null && absChar.getObjectType().equals(Enum.GameObjectType.PlayerCharacter) == false) return; + PlayerCharacter pc = (PlayerCharacter)absChar; + ConcurrentHashMap skills = pc.getSkills(); //First add skills that don't exist - Race race = pc.getRace(); + Race race = pc.race; if (race != null) { CharacterSkill.grantSkills(race.getSkillsGranted(), pc); } else Logger.error("Failed to find Race for player " + pc.getObjectUUID()); - BaseClass bc = pc.getBaseClass(); + BaseClass bc = pc.baseClass; if (bc != null) { CharacterSkill.grantSkills(bc.getSkillsGranted(), pc); } else Logger.error("Failed to find BaseClass for player " + pc.getObjectUUID()); - PromotionClass promo = pc.getPromotionClass(); + PromotionClass promo = pc.promotionClass; if (promo != null) CharacterSkill.grantSkills(promo.getSkillsGranted(), pc); ArrayList runes = pc.getRunes(); diff --git a/src/engine/objects/Mob.java b/src/engine/objects/Mob.java index 5116940a..b41aff90 100644 --- a/src/engine/objects/Mob.java +++ b/src/engine/objects/Mob.java @@ -1500,44 +1500,6 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed { } - public ItemBase getWeaponItemBase(boolean mainHand) { - - if (this.equipmentSetID != 0) - if (charItemManager.equipped != null) { - Item me; - - if (mainHand) - me = charItemManager.equipped.get(EquipSlotType.RHELD); //mainHand - else - me = charItemManager.equipped.get(EquipSlotType.LHELD); //offHand - - if (me != null) { - - ItemBase ib = me.getItemBase(); - - if (ib != null) - return ib; - - } - } - MobBase mb = this.mobBase; - - if (mb != null) - if (this.charItemManager.equipped.isEmpty() == false) { - - Item me; - - if (mainHand) - me = this.charItemManager.equipped.get(EquipSlotType.RHELD); //mainHand - else - me = this.charItemManager.equipped.get(EquipSlotType.LHELD); //offHand - - if (me != null) - return me.getItemBase(); - } - return null; - } - @Override public void runAfterLoad() { @@ -1767,9 +1729,6 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed { return lastAttackTime; } - public void setLastAttackTime(long lastAttackTime) { - this.lastAttackTime = lastAttackTime; - } public void setDeathTime(long deathTime) { this.deathTime = deathTime; @@ -1779,10 +1738,6 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed { return hasLoot; } - public DeferredPowerJob getWeaponPower() { - return weaponPower; - } - public void setWeaponPower(DeferredPowerJob weaponPower) { this.weaponPower = weaponPower; } diff --git a/src/engine/objects/PlayerBonuses.java b/src/engine/objects/PlayerBonuses.java index 7a8a8f21..6ca9a59e 100644 --- a/src/engine/objects/PlayerBonuses.java +++ b/src/engine/objects/PlayerBonuses.java @@ -90,11 +90,11 @@ public class PlayerBonuses { //recalculate race - if (pc.getRace() != null) { + if (pc.race != null) { - if (pc.getRace().getEffectsList() != null) - for (MobBaseEffects raceEffect : pc.getRace().getEffectsList()) { + if (pc.race.getEffectsList() != null) + for (MobBaseEffects raceEffect : pc.race.getEffectsList()) { EffectsBase eb = PowersManager.getEffectByToken(raceEffect.getToken()); if (eb == null) @@ -125,10 +125,10 @@ public class PlayerBonuses { } //calculate baseclass effects - if (pc.getBaseClass() != null) { + if (pc.baseClass != null) { - if (pc.getBaseClass().getEffectsList() != null) - for (MobBaseEffects classEffect : pc.getBaseClass().getEffectsList()) { + if (pc.baseClass.getEffectsList() != null) + for (MobBaseEffects classEffect : pc.baseClass.getEffectsList()) { EffectsBase eb = PowersManager.getEffectByToken(classEffect.getToken()); if (eb == null) diff --git a/src/engine/objects/PlayerCharacter.java b/src/engine/objects/PlayerCharacter.java index 381aac2e..7b2cadfe 100644 --- a/src/engine/objects/PlayerCharacter.java +++ b/src/engine/objects/PlayerCharacter.java @@ -64,7 +64,7 @@ public class PlayerCharacter extends AbstractCharacter { public final ReadWriteLock respawnLock = new ReentrantReadWriteLock(true); public final ArrayList necroPets = new ArrayList<>(); private final Account account; - private final Race race; + private final byte skinColor; private final byte hairColor; private final byte beardColor; @@ -99,12 +99,7 @@ public class PlayerCharacter extends AbstractCharacter { public short statIntMin; public short statSpiMin; // Current Stats before Equip and Effect - // Modifiers - public short statStrBase; - public short statDexBase; - public short statConBase; - public short statIntBase; - public short statSpiBase; + public short trainedStatPoints = 0; public boolean isCSR = false; //TODO Public fields break OO!!! @@ -117,8 +112,8 @@ public class PlayerCharacter extends AbstractCharacter { public float landingAltitude = 0; public int bindBuilding = 0; public FriendStatus friendStatus = FriendStatus.Available; - private BaseClass baseClass; - private PromotionClass promotionClass; + + private ConcurrentHashMap ignoredPlayerIDs = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); private boolean lfGroup = false; private boolean lfGuild = false; @@ -1342,7 +1337,7 @@ public class PlayerCharacter extends AbstractCharacter { //calculate ATR, damage and defense - pc.calculateAtrDefenseDamage(); + AbstractCharacter.calculateAtrDefenseDamage(pc); //calculate movement bonus pc.calculateSpeedMod(); @@ -1369,12 +1364,6 @@ public class PlayerCharacter extends AbstractCharacter { return ab.getDexPenalty(); } - private static float getModifiedAmount(CharacterSkill skill) { - if (skill == null) - return 0f; - return skill.getModifiedAmount(); - } - public static void InitializeSkillsOnLoad(PlayerCharacter pc) { try { { @@ -2116,9 +2105,7 @@ public class PlayerCharacter extends AbstractCharacter { /** * @return the race */ - public Race getRace() { - return race; - } + public int getRaceID() { if (race != null) @@ -2129,9 +2116,7 @@ public class PlayerCharacter extends AbstractCharacter { /** * @return the baseClass */ - public BaseClass getBaseClass() { - return baseClass; - } + public int getBaseClassID() { if (baseClass != null) @@ -3359,7 +3344,7 @@ public class PlayerCharacter extends AbstractCharacter { //calculate ATR, damage and defense - calculateAtrDefenseDamage(); + calculateAtrDefenseDamage(this); //calculate movement bonus calculateSpeedMod(); @@ -3779,344 +3764,6 @@ public class PlayerCharacter extends AbstractCharacter { this.follow = false; } - /** - * @ Calculates Atr (both hands) Defense, and Damage for pc - */ - public void calculateAtrDefenseDamage() { - if (this.charItemManager == null || this.charItemManager.getEquipped() == null || this.skills == null) { - Logger.error("Player " + this.getObjectUUID() + " missing skills or equipment"); - defaultAtrAndDamage(true); - defaultAtrAndDamage(false); - this.defenseRating = 0; - return; - } - ConcurrentHashMap equipped = this.charItemManager.getEquipped(); - - // // Reset passives - // if (this.bonuses != null) { - // this.bonuses.setBool("Block", false); - // this.bonuses.setBool("Parry", false); - // if (this.baseClass != null && this.baseClass.getUUID() == 2502) - // this.bonuses.setBool("Dodge", true); - // else - // this.bonuses.setBool("Dodge", false); - // } - // calculate atr and damage for each hand - calculateAtrDamageForWeapon(equipped.get(EquipSlotType.RHELD), true, equipped.get(EquipSlotType.RHELD)); - calculateAtrDamageForWeapon(equipped.get(EquipSlotType.LHELD), false, equipped.get(EquipSlotType.LHELD)); - - // No Defense while in DeathShroud - if (this.effects != null && this.effects.containsKey("DeathShroud")) - this.defenseRating = (short) 0; - else { - // calculate defense for equipment - float defense = this.statDexCurrent * 2; - defense += getShieldDefense(equipped.get(EquipSlotType.LHELD)); - defense += getArmorDefense(equipped.get(EquipSlotType.HELM)); - defense += getArmorDefense(equipped.get(EquipSlotType.CHEST)); - defense += getArmorDefense(equipped.get(EquipSlotType.UPARM)); - defense += getArmorDefense(equipped.get(EquipSlotType.HANDS)); - defense += getArmorDefense(equipped.get(EquipSlotType.LEGS)); - defense += getArmorDefense(equipped.get(EquipSlotType.FEET)); - defense += getWeaponDefense(equipped); - - 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 = this.bonuses.getFloatPercentPositive(ModType.DCV, SourceType.NONE); - defense = (short) (defense * (1 + pos_Bonus)); - - //Lucky rune applies next - //applied runes will be calculated and added to the normal bonuses. no need for this garbage anymore - //defense = (short) (defense * (1 + ((float) this.bonuses.getShort("rune.Defense") / 100))); - - //and negative percent modifiers - //already done... - 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); - } - } - - /** - * @ Calculates Atr, and Damage for each weapon - */ - private void calculateAtrDamageForWeapon(Item weapon, boolean mainHand, Item otherHand) { - - // make sure weapon exists - boolean noWeapon = false; - ItemBase wb = null; - if (weapon == null) - noWeapon = true; - else { - ItemBase ib = weapon.getItemBase(); - if (ib == null) - noWeapon = true; - else if (!weapon.template.item_type.equals(ItemType.WEAPON)) { - defaultAtrAndDamage(mainHand); - return; - } else - wb = ib; - } - float skillPercentage, masteryPercentage; - float mastDam; - float min, max; - float speed = 20f; - boolean strBased = false; - - ItemBase wbMain = (weapon != null) ? weapon.getItemBase() : null; - ItemBase wbOff = (otherHand != null) ? otherHand.getItemBase() : null; - - // get skill percentages and min and max damage for weapons - if (noWeapon) { - if (mainHand) { - Item off = this.charItemManager.getEquipped().get(EquipSlotType.LHELD); - if (off != null && off.getItemBase() != null && off.template.item_type.equals(ItemType.WEAPON)) - this.rangeHandOne = 10 * (1 + (this.statStrBase / 600)); // Set - // to - // no - // weapon - // range - else - this.rangeHandOne = -1; // set to do not attack - } else - this.rangeHandTwo = -1; // set to do not attack - - skillPercentage = getModifiedAmount(this.skills.get("Unarmed Combat")); - masteryPercentage = getModifiedAmount(this.skills.get("Unarmed Combat Mastery")); - if (masteryPercentage == 0f) - mastDam = CharacterSkill.getQuickMastery(this, "Unarmed Combat Mastery"); - else - mastDam = masteryPercentage; - // TODO Correct these - min = 1; - max = 3; - } else { - if (mainHand) - this.rangeHandOne = weapon.getItemBase().getRange() * (1 + (this.statStrBase / 600)); - else - this.rangeHandTwo = weapon.getItemBase().getRange() * (1 + (this.statStrBase / 600)); - - if (this.bonuses != null) { - float range_bonus = 1 + this.bonuses.getFloatPercentAll(ModType.WeaponRange, SourceType.NONE); - - if (mainHand) - this.rangeHandOne *= range_bonus; - else - this.rangeHandTwo *= range_bonus; - - } - skillPercentage = getModifiedAmount(this.skills.get(weapon.template.item_skill_used)); - masteryPercentage = getModifiedAmount(this.skills.get(wb.getMastery())); - if (masteryPercentage == 0f) - mastDam = 0f; - // mastDam = CharacterSkill.getQuickMastery(this, wb.getMastery()); - else - mastDam = masteryPercentage; - min = (float) wb.getMinDamage(); - max = (float) wb.getMaxDamage(); - strBased = wb.isStrBased(); - - // - // Add parry bonus for weapon and allow parry if needed - - // // Only Fighters and Thieves can Parry - // if ((this.baseClass != null && this.baseClass.getUUID() == 2500) - // || (this.promotionClass != null && this.promotionClass.getUUID() == 2520)) { - // if (wbMain == null || wbMain.getRange() < MBServerStatics.RANGED_WEAPON_RANGE) - // if (wbOff == null || wbOff.getRange() < MBServerStatics.RANGED_WEAPON_RANGE) - // this.bonuses.setBool("Parry", true); - // } - // } - } - - if (this.effects != null && this.effects.containsKey("DeathShroud")) - // No Atr in deathshroud. - if (mainHand) - this.atrHandOne = (short) 0; - else - this.atrHandTwo = (short) 0; - else { - // calculate atr - float atr = 0; - atr += (int) skillPercentage * 4f; //<-round down skill% - - atr += (int) masteryPercentage * 3f; - if (this.statStrCurrent > this.statDexCurrent) - atr += statStrCurrent / 2; - else - atr += statDexCurrent / 2; - - // add in any bonuses to atr - if (this.bonuses != null) { - // Add any base bonuses - atr += this.bonuses.getFloat(ModType.OCV, SourceType.NONE); - - // Finally use any multipliers. DO THIS LAST! - float pos_Bonus = (1 + this.bonuses.getFloatPercentPositive(ModType.OCV, SourceType.NONE)); - atr *= pos_Bonus; - - // next precise - //runes will have their own bonuses. - // atr *= (1 + ((float) this.bonuses.getShort("rune.Attack") / 100)); - - //and negative percent modifiers - 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 (weapon != null) - speed *= (1 + this.bonuses.getFloatPercentAll(ModType.WeaponSpeed, SourceType.NONE)); - speed *= (1 + this.bonuses.getFloatPercentAll(ModType.AttackDelay, SourceType.NONE)); - if (speed < 10) - speed = 10; - - //add min/max damage bonuses for weapon - if (weapon != null) { - // Add any base bonuses - - min += weapon.getBonus(ModType.MinDamage, SourceType.NONE); - max += weapon.getBonus(ModType.MaxDamage, SourceType.NONE); - - min += weapon.getBonus(ModType.MeleeDamageModifier, SourceType.NONE); - max += weapon.getBonus(ModType.MeleeDamageModifier, SourceType.NONE); - // Finally use any multipliers. DO THIS LAST! - - float percentMinDamage = 1; - float percentMaxDamage = 1; - - percentMinDamage += weapon.getBonusPercent(ModType.MinDamage, SourceType.NONE); - percentMinDamage += weapon.getBonusPercent(ModType.MeleeDamageModifier, SourceType.NONE); - - percentMaxDamage += weapon.getBonusPercent(ModType.MaxDamage, SourceType.NONE); - percentMaxDamage += weapon.getBonusPercent(ModType.MeleeDamageModifier, SourceType.NONE); - - - min *= percentMinDamage; - max *= percentMaxDamage; - } - - //if duel wielding, cut damage by 30% - if (otherHand != null) { - ItemBase ibo = otherHand.getItemBase(); - if (ibo != null && otherHand.template.equals(ItemType.WEAPON)) { - min *= 0.7f; - max *= 0.7f; - } - } - - // 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 - - // Half damage if in death shroud - if (this.effects != null && this.effects.containsKey("DeathShroud")) { - minDamage *= 0.5f; - maxDamage *= 0.5f; - } - - // 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); - - minDamage += this.bonuses.getFloat(ModType.MeleeDamageModifier, SourceType.NONE); - maxDamage += this.bonuses.getFloat(ModType.MeleeDamageModifier, SourceType.NONE); - // Finally use any multipliers. DO THIS LAST! - - float percentMinDamage = 1; - float percentMaxDamage = 1; - - percentMinDamage += this.bonuses.getFloatPercentAll(ModType.MinDamage, SourceType.NONE); - percentMinDamage += this.bonuses.getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.NONE); - - percentMaxDamage += this.bonuses.getFloatPercentAll(ModType.MaxDamage, SourceType.NONE); - percentMaxDamage += this.bonuses.getFloatPercentAll(ModType.MeleeDamageModifier, SourceType.NONE); - - minDamage *= percentMinDamage; - maxDamage *= percentMaxDamage; - - } - - // set damages - if (mainHand) { - this.minDamageHandOne = (int) minDamage; - this.maxDamageHandOne = (int) maxDamage; - this.speedHandOne = speed; - } else { - this.minDamageHandTwo = (int) minDamage; - this.maxDamageHandTwo = (int) maxDamage; - this.speedHandTwo = speed; - } - } - - /** - * @ Calculates Defense for shield - */ - private float getShieldDefense(Item shield) { - - if (shield == null) - return 0; - - if (ItemTemplate.isShield(shield) == false) - return 0; - - ItemBase ab = shield.getItemBase(); - - if (ab == null) - return 0; - - CharacterSkill blockSkill = this.skills.get("Block"); - - float skillMod; - - if (blockSkill == null) { - skillMod = 0; - } else - skillMod = blockSkill.getModifiedAmount(); - - float def = ab.getDefense(); - - //apply item defense bonuses - if (shield != null) { - def += shield.getBonus(ModType.DR, SourceType.NONE); - def *= (1 + shield.getBonusPercent(ModType.DR, SourceType.NONE)); - - } - - // float val = ((float)ab.getDefense()) * (1 + (skillMod / 100)); - return (def * (1 + ((int) skillMod / 100f))); - } - public void setPassives() { if (this.bonuses != null) { ConcurrentHashMap equipped = this.charItemManager.getEquipped(); @@ -4153,134 +3800,15 @@ public class PlayerCharacter extends AbstractCharacter { } - /** - * @ Calculates Defense for armor - */ - private float getArmorDefense(Item armor) { - - if (armor == null) - return 0; - - ItemBase ib = armor.getItemBase(); - - if (ib == null) - return 0; - - if (!armor.template.item_type.equals(ItemType.ARMOR)) - return 0; - - if (armor.template.item_skill_used.isEmpty()) - return ib.getDefense(); - - CharacterSkill armorSkill = this.skills.get(armor.template.item_skill_used); - if (armorSkill == null) { - Logger.error("Player " + this.getObjectUUID() - + " has armor equipped without the nescessary skill to equip it"); - return ib.getDefense(); - } - - float def = ib.getDefense(); - //apply item defense bonuses - if (armor != null) { - def += armor.getBonus(ModType.DR, SourceType.NONE); - def *= (1 + armor.getBonusPercent(ModType.DR, SourceType.NONE)); - } - - - return (def * (1 + ((int) armorSkill.getModifiedAmount() / 50f))); - } - - /** - * @ Calculates Defense for weapon - */ - private float getWeaponDefense(ConcurrentHashMap equipped) { - Item weapon = equipped.get(EquipSlotType.RHELD); - ItemBase wb = null; - CharacterSkill skill, mastery; - float val = 0; - boolean unarmed = false; - if (weapon == null) { - weapon = equipped.get(EquipSlotType.LHELD); - if (weapon == null || ItemTemplate.isShield(weapon)) - unarmed = true; - else - wb = weapon.getItemBase(); - } else - wb = weapon.getItemBase(); - if (wb == null) - unarmed = true; - if (unarmed) { - skill = this.skills.get("Unarmed Combat"); - mastery = this.skills.get("Unarmed Combat Mastery"); - } else { - skill = this.skills.get(weapon.template.item_skill_used); - mastery = this.skills.get(wb.getMastery()); - } - if (skill != null) - val += (int) skill.getModifiedAmount() / 2f; - if (mastery != null) - val += (int) mastery.getModifiedAmount() / 2f; - return val; - } - //Call this function to recalculate granted skills and powers for player public synchronized void calculateSkills() { //tell the player to applyBonuses because something has changed - runSkillCalc(); + AbstractCharacter.runSkillCalc(this); //start running the skill/power calculations } - //Don't call this function directly. linked from pc.calculateSkills() - //through SkillCalcJob. Designed to only run from one worker thread - public void runSkillCalc() { - try { - - //see if any new skills or powers granted - CharacterSkill.calculateSkills(this); - // calculate granted Trains in powers. - CharacterPower.grantTrains(this); - //see if any new powers unlocked from previous check - CharacterPower.calculatePowers(this); - - } catch (Exception e) { - } - - } - - //calculate item bonuses here - public void calculateItemBonuses() { - if (this.charItemManager == null || this.bonuses == null) - return; - ConcurrentHashMap equipped = this.charItemManager.getEquipped(); - for (Item item : equipped.values()) { - ItemBase ib = item.getItemBase(); - if (ib == null) - continue; - //TODO add effect bonuses in here for equipped items - } - } - - /** - * @ Defaults ATR, Defense and Damage for player - */ - 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 calculateMaxHealthManaStamina() { float h = 1f; float m = 0f; @@ -4431,36 +3959,6 @@ public class PlayerCharacter extends AbstractCharacter { return (amount - attackerLevel + this.getLevel()) / 4; } - public float getPassiveChance1(ModType modType, SourceType sourceType, int attackerLevel, boolean fromCombat) { - if (this.skills == null || this.bonuses == null) - return 0f; - - // must be allowed to use this passive - if (!this.bonuses.getBool(modType, sourceType)) - return 0f; - - // must not be stunned - if (this.bonuses.getBool(ModType.Stunned, SourceType.NONE)) - return 0f; - - // Get base skill amount - CharacterSkill sk = this.skills.get(sourceType.name()); - float amount; - if (sk == null) - amount = CharacterSkill.getQuickMastery(this, modType.name()); - else - amount = sk.getModifiedAmount(); - - // Add bonuses - amount += this.bonuses.getFloat(modType, sourceType); - - // Add item bonuses and return - if (sourceType.equals(SourceType.DODGE) && !fromCombat) - return ((amount / 4) - attackerLevel + this.getLevel()) / 4; - else - return (amount - attackerLevel + this.getLevel()) / 4; - } - public float getRegenModifier(ModType type) { float regen = 1f; @@ -4475,40 +3973,6 @@ public class PlayerCharacter extends AbstractCharacter { return !this.isAlive(); } - public void ResetLevel(short targetLevel) { - - if (targetLevel > 13) { - ChatManager.chatSystemError(this, "Please choose a level between 1 and 13."); - return; - } - this.promotionClass = null; - if (targetLevel > 10) { - this.level = 10; - this.exp = Experience.getBaseExperience(11); - int maxEXP = Experience.getBaseExperience(targetLevel); //target level exp; - this.overFlowEXP = maxEXP - this.exp; - } else { - this.level = targetLevel; - this.exp = Experience.getBaseExperience(level); - this.overFlowEXP = 0; - } - - - for (CharacterSkill skill : this.getSkills().values()) { - skill.reset(this, true); - } - - for (CharacterPower power : this.getPowers().values()) { - power.reset(this); - } - - this.recalculatePlayerStats(initialized); - this.recalculate(); - - ChatManager.chatSystemInfo(this, "Character reset to " + targetLevel + ". All training points have been refunded. Relog to update changes on client."); - - } - @Override public void removeFromCache() { Logger.info("Removing " + this.getName() + " from Object Cache."); @@ -4545,10 +4009,6 @@ public class PlayerCharacter extends AbstractCharacter { super.removeFromCache(); } - public void storeIgnoreListDB() { - - } - public void updateSkillsAndPowersToDatabase() { if (this.skills != null) for (CharacterSkill skill : this.skills.values()) { @@ -4572,11 +4032,11 @@ public class PlayerCharacter extends AbstractCharacter { this.setBounds(playerBounds); //assign enum values for restrictions - String race = this.getRace().getName().replace("-", "").replace(", Male", "").replace(", Female", ""); + String race = this.race.getName().replace("-", "").replace(", Male", "").replace(", Female", ""); this.absRace = Enum.MonsterType.valueOf(race); if (this.baseClass != null) - this.absBaseClass = ClassType.valueOf(this.getBaseClass().getName()); + this.absBaseClass = ClassType.valueOf(this.baseClass.getName()); if (this.promotionClass != null) this.absPromotionClass = ClassType.valueOf(this.getPromotionClass().getName()); diff --git a/src/engine/objects/PowerGrant.java b/src/engine/objects/PowerGrant.java index 04c08552..6fe2b2cc 100644 --- a/src/engine/objects/PowerGrant.java +++ b/src/engine/objects/PowerGrant.java @@ -53,12 +53,12 @@ public class PowerGrant extends AbstractGameObject { ArrayList toks = new ArrayList<>(); //get race ID - Race race = pc.getRace(); + Race race = pc.race; if (race != null) toks.add(race.getRaceRuneID()); //get baseClass ID - BaseClass bc = pc.getBaseClass(); + BaseClass bc = pc.baseClass; if (bc != null) toks.add(bc.getObjectUUID());