From 9f09a0e8b0b00176f74921d7f6feb2b8c22ddb3e Mon Sep 17 00:00:00 2001 From: FatBoy-DOTC Date: Mon, 3 Mar 2025 06:33:31 -0600 Subject: [PATCH] proc chance broken into separate method --- src/engine/gameManager/CombatManager.java | 55 ++- src/engine/gameManager/CombatSystem.java | 430 ---------------------- 2 files changed, 35 insertions(+), 450 deletions(-) delete mode 100644 src/engine/gameManager/CombatSystem.java diff --git a/src/engine/gameManager/CombatManager.java b/src/engine/gameManager/CombatManager.java index be582615..fb952d51 100644 --- a/src/engine/gameManager/CombatManager.java +++ b/src/engine/gameManager/CombatManager.java @@ -978,26 +978,7 @@ public enum CombatManager { errorTrack = 14; //handle procs - - if (weapon != null && tarAc != null && tarAc.isAlive()) { - - if(weapon.effects != null){ - for (Effect eff : weapon.effects.values()){ - for(AbstractEffectModifier mod : eff.getEffectModifiers()){ - if(mod.modType.equals(ModType.WeaponProc)){ - int procChance = ThreadLocalRandom.current().nextInt(100); - if (procChance < MBServerStatics.PROC_CHANCE) { - try { - ((WeaponProcEffectModifier) mod).applyProc(ac, target); - }catch(Exception e){ - Logger.error(eff.getName() + " Failed To Cast Proc"); - } - } - } - } - } - } - } + procChanceHandler(weapon,ac,tarAc); errorTrack = 15; @@ -1081,6 +1062,40 @@ public enum CombatManager { } } + private static void procChanceHandler(Item weapon, AbstractCharacter ac, AbstractCharacter tarAc) { + + //no weapon means no proc + if(weapon == null) + return; + + //caster is dead of null, no proc + if(ac == null || !ac.isAlive()) + return; + + //target is dead or null, no proc + if(tarAc == null || !tarAc.isAlive()) + return; + + //no effects on weapon, skip proc + if(weapon.effects == null || weapon.effects.isEmpty()) + return; + + for (Effect eff : weapon.effects.values()){ + for(AbstractEffectModifier mod : eff.getEffectModifiers()) { + if (mod.modType.equals(ModType.WeaponProc)) { + int procChance = ThreadLocalRandom.current().nextInt(100); + if (procChance < MBServerStatics.PROC_CHANCE) { + try { + ((WeaponProcEffectModifier) mod).applyProc(ac, tarAc); + } catch (Exception e) { + Logger.error(eff.getName() + " Failed To Cast Proc"); + } + } + } + } + } + } + public static boolean canTestParry(AbstractCharacter ac, AbstractWorldObject target) { if (ac == null || target == null || !AbstractWorldObject.IsAbstractCharacter(target)) diff --git a/src/engine/gameManager/CombatSystem.java b/src/engine/gameManager/CombatSystem.java deleted file mode 100644 index a2eadb3b..00000000 --- a/src/engine/gameManager/CombatSystem.java +++ /dev/null @@ -1,430 +0,0 @@ -package engine.gameManager; - -import engine.Enum; -import engine.exception.MsgSendException; -import engine.job.JobContainer; -import engine.job.JobScheduler; -import engine.jobs.AttackJob; -import engine.jobs.DeferredPowerJob; -import engine.net.DispatchMessage; -import engine.net.client.ClientConnection; -import engine.net.client.msg.AttackCmdMsg; -import engine.net.client.msg.TargetedActionMsg; -import engine.objects.*; -import engine.powers.DamageShield; -import engine.powers.effectmodifiers.AbstractEffectModifier; -import engine.powers.effectmodifiers.WeaponProcEffectModifier; -import engine.server.MBServerStatics; -import org.pmw.tinylog.Logger; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ThreadLocalRandom; - -public class CombatSystem { - - public static void attemptCombat(AbstractCharacter source, AbstractWorldObject target, boolean mainhand){ - - //1. source or target doesn't exist, early exit - if(source == null || target == null) - return; - - //2. source or target is dead, early exit - if(!source.isAlive() || !target.isAlive()) - return; - - //3. make sure if target is a building to ensure that it is damageable - if(target.getObjectType().equals(Enum.GameObjectType.Building)){ - Building building = (Building)target; - if(building.assetIsProtected() || building.getProtectionState().equals(Enum.ProtectionState.NPC)) - return; - } - - //after thought: make sure target is in range of source - if(!inRange(source,target,mainhand)) - return; - - //4. apply any weapon powers and then clear the weapon power memory for the player - if (source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) { - PlayerCharacter pc = (PlayerCharacter)source; - if(pc.getWeaponPower() != null){ - pc.getWeaponPower().attack(target,pc.getRange()); - pc.setWeaponPower(null); - } - } - - //5. make sure if target is AbstractCharacter to check for defense trigger and passive trigger - if(AbstractCharacter.IsAbstractCharacter(target)) { - int atr; - int def; - if (source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) { - PlayerCharacter pc = (PlayerCharacter)source; - if(pc.combatStats == null) - pc.combatStats = new PlayerCombatStats(pc); - atr = (int) pc.combatStats.atrHandOne; - if(!mainhand) - atr =(int) pc.combatStats.atrHandTwo; - - def = pc.combatStats.defense; - } else { - atr = (int) ((source.getAtrHandOne() + source.getAtrHandTwo()) * 0.5f); - def = source.defenseRating; - } - - if(!LandHit(atr,def)) { - createTimer(source,mainhand); - return; - } - - if(source.getBonuses() != null) - if(!source.getBonuses().getBool(Enum.ModType.IgnorePassiveDefense, Enum.SourceType.None)) - if(triggerPassive(source,target)) { - createTimer(source,mainhand); - return; - } - } - - //commence actual combat management - - //6. check for any procs - if (source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) { - PlayerCharacter pc = (PlayerCharacter)source; - if(pc.getCharItemManager() != null && pc.getCharItemManager().getEquipped() != null){ - Item weapon = pc.getCharItemManager().getEquipped(1); - if(!mainhand) - weapon = pc.getCharItemManager().getEquipped(2); - if(weapon != null){ - if(weapon.effects != null){ - for (Effect eff : weapon.effects.values()){ - for(AbstractEffectModifier mod : eff.getEffectModifiers()){ - if(mod.modType.equals(Enum.ModType.WeaponProc)){ - int procChance = ThreadLocalRandom.current().nextInt(0,101); - if (procChance <= MBServerStatics.PROC_CHANCE) { - try { - ((WeaponProcEffectModifier) mod).applyProc(source, target); - }catch(Exception e){ - Logger.error(eff.getName() + " Failed To Cast Proc"); - } - } - } - } - } - } - } - } - } - - //7. configure damage amounts and type - Enum.DamageType damageType = Enum.DamageType.Crush; - int min = 0; - int max = 0; - if (source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) { - PlayerCharacter pc = (PlayerCharacter) source; - if(mainhand){ - min = pc.combatStats.minDamageHandOne; - max = pc.combatStats.maxDamageHandOne; - }else{ - min = pc.combatStats.minDamageHandTwo; - max = pc.combatStats.maxDamageHandTwo; - } - }else if (source.getObjectType().equals(Enum.GameObjectType.Mob)) { - Mob mob = (Mob) source; - min = (int) mob.mobBase.getDamageMin(); - max = (int) mob.mobBase.getDamageMax(); - } - - int damage = ThreadLocalRandom.current().nextInt(min,max + 1); - - if(source.getBonuses() != null){ - damage *= 1 + source.getBonuses().getFloatPercentAll(Enum.ModType.MeleeDamageModifier, Enum.SourceType.None); - } - if (source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) { - PlayerCharacter pc = (PlayerCharacter) source; - damage *= pc.ZergMultiplier; - } - - //8. configure the attack message to be sent to the clients - int animation = 0; - ItemBase wb = null; - if(source.getCharItemManager() != null && source.getCharItemManager().getEquipped() != null) { - Item weapon = source.getCharItemManager().getEquipped(1); - if (!mainhand) - weapon = source.getCharItemManager().getEquipped(2); - - if(weapon != null && weapon.getItemBase().getAnimations() != null && !weapon.getItemBase().getAnimations().isEmpty()){ - animation = weapon.getItemBase().getAnimations().get(0); - wb = weapon.getItemBase(); - damageType = wb.getDamageType(); - } - } - - //9. reduce damage from resists and apply damage shields - if(AbstractCharacter.IsAbstractCharacter(target)){ - AbstractCharacter abs = (AbstractCharacter) target; - damage = (int) abs.getResists().getResistedDamage(source, abs,damageType,damage,1); - handleDamageShields(source,abs,damage); - } - - - - sendCombatMessage(source, target, 0f, wb, null, mainhand, animation); - - //if attacker is player, set last attack timestamp - if (source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) - updateAttackTimers((PlayerCharacter) source, target); - - //10. cancel all effects that cancel on attack - source.cancelOnAttack(); - } - - public static boolean LandHit(int ATR, int DEF){ - - int roll = ThreadLocalRandom.current().nextInt(101); - - float chance = PlayerCombatStats.getHitChance(ATR,DEF); - return chance >= roll; - } - - private static void sendCombatMessage(AbstractCharacter source, AbstractWorldObject target, float damage, ItemBase wb, DeferredPowerJob dpj, boolean mainHand, int swingAnimation) { - - if (dpj != null) - if (PowersManager.AnimationOverrides.containsKey(dpj.getAction().getEffectID())) - swingAnimation = PowersManager.AnimationOverrides.get(dpj.getAction().getEffectID()); - - if (source.getObjectType() == Enum.GameObjectType.PlayerCharacter) - for (Effect eff : source.getEffects().values()) - if (eff.getPower() != null && (eff.getPower().getToken() == 429506943 || eff.getPower().getToken() == 429408639 || eff.getPower().getToken() == 429513599 || eff.getPower().getToken() == 429415295)) - swingAnimation = 0; - - TargetedActionMsg cmm = new TargetedActionMsg(source, target, damage, swingAnimation); - DispatchMessage.sendToAllInRange(target, cmm); - } - - private static void updateAttackTimers(PlayerCharacter pc, AbstractWorldObject target) { - - //Set Attack Timers - - if (target.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) - pc.setLastPlayerAttackTime(); - } - - public static void handleDamageShields(AbstractCharacter ac, AbstractCharacter target, float damage) { - - if (ac == null || target == null) - return; - - PlayerBonuses bonuses = target.getBonuses(); - - if (bonuses != null) { - - ConcurrentHashMap damageShields = bonuses.getDamageShields(); - float total = 0; - - for (DamageShield ds : damageShields.values()) { - - //get amount to damage back - - float amount; - - if (ds.usePercent()) - amount = damage * ds.getAmount() / 100; - else - amount = ds.getAmount(); - - //get resisted damage for damagetype - - Resists resists = ac.getResists(); - - if (resists != null) { - amount = resists.getResistedDamage(target, ac, ds.getDamageType(), amount, 0); - } - total += amount; - } - - if (total > 0) { - - //apply Damage back - - ac.modifyHealth(-total, target, true); - - TargetedActionMsg cmm = new TargetedActionMsg(ac, ac, total, 0); - DispatchMessage.sendToAllInRange(target, cmm); - - } - } - } - - public static boolean inRange(AbstractCharacter source, AbstractWorldObject target, boolean mainhand){ - - if(source == null || target == null) - return false; - - float distanceSquared = source.loc.distanceSquared(target.loc); - - float rangeSquared = 16.0f; - - if(source.getCharItemManager() != null && source.getCharItemManager().getEquipped() != null){ - Item weapon = source.getCharItemManager().getEquipped(1); - if(!mainhand) - weapon = source.getCharItemManager().getEquipped(2); - if(weapon != null) - rangeSquared = weapon.getItemBase().getRange() * weapon.getItemBase().getRange(); - } - - if(source.getBonuses() != null){ - rangeSquared *= 1 + source.getBonuses().getFloatPercentAll(Enum.ModType.WeaponRange, Enum.SourceType.None); - } - - return distanceSquared <= rangeSquared; - } - - public static boolean triggerPassive(AbstractCharacter source, AbstractWorldObject target) { - boolean passiveFired = false; - - if (!AbstractCharacter.IsAbstractCharacter(target)) - return false; - - AbstractCharacter tarAc = (AbstractCharacter) target; - //Handle Block passive - if (testPassive(source, tarAc, "Block")) { - sendPassiveDefenseMessage(source, null, target, MBServerStatics.COMBAT_SEND_DODGE, null, true); - return true; - } - - //Handle Parry passive - if (testPassive(source, tarAc, "Parry")) { - sendPassiveDefenseMessage(source, null, target, MBServerStatics.COMBAT_SEND_DODGE, null, true); - return true; - } - - //Handle Dodge passive - if (testPassive(source, tarAc, "Dodge")) { - sendPassiveDefenseMessage(source, null, target, MBServerStatics.COMBAT_SEND_DODGE, null, true); - return true; - } - return false; - } - - private static void sendPassiveDefenseMessage(AbstractCharacter source, ItemBase wb, AbstractWorldObject target, int passiveType, DeferredPowerJob dpj, boolean mainHand) { - - int swingAnimation = 75; - - if (dpj != null) - if (PowersManager.AnimationOverrides.containsKey(dpj.getAction().getEffectID())) - swingAnimation = PowersManager.AnimationOverrides.get(dpj.getAction().getEffectID()); - - TargetedActionMsg cmm = new TargetedActionMsg(source, swingAnimation, target, passiveType); - DispatchMessage.sendToAllInRange(target, cmm); - } - - private static boolean testPassive(AbstractCharacter source, AbstractCharacter target, String type) { - - if(target.getBonuses() != null) - if(target.getBonuses().getBool(Enum.ModType.Stunned, Enum.SourceType.None)) - return false; - - float chance = target.getPassiveChance(type, source.getLevel(), true); - - if (chance == 0f) - return false; - - //max 75% chance of passive to fire - - if (chance > 75f) - chance = 75f; - - int roll = ThreadLocalRandom.current().nextInt(1,100); - - return roll < chance; - - } - - private static void createTimer(AbstractCharacter source, boolean mainhand) { - - ConcurrentHashMap timers = source.getTimers(); - int slot = 1; - if(!mainhand) - slot = 2; - - int time = 3000; - if(source.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)){ - PlayerCharacter pc = (PlayerCharacter)source; - if(mainhand){ - time = (int) pc.combatStats.attackSpeedHandOne; - }else{ - time = (int) pc.combatStats.attackSpeedHandTwo; - } - } - - if (timers != null) { - AttackJob aj = new AttackJob(source, slot, true); - JobContainer job; - job = JobScheduler.getInstance().scheduleJob(aj, (time * 100)); - timers.put("Attack" + slot, job); - } else { - Logger.error("Unable to find Timers for Character " + source.getObjectUUID()); - } - } - - public static void setAttackTarget(AttackCmdMsg msg, ClientConnection origin) throws MsgSendException { - - PlayerCharacter player; - int targetType; - AbstractWorldObject target; - - if (TargetedActionMsg.un2cnt == 60 || TargetedActionMsg.un2cnt == 70) - return; - - player = SessionManager.getPlayerCharacter(origin); - - if (player == null) - return; - - //source must match player this account belongs to - - if (player.getObjectUUID() != msg.getSourceID() || player.getObjectType().ordinal() != msg.getSourceType()) { - Logger.error("Msg Source ID " + msg.getSourceID() + " Does not Match Player ID " + player.getObjectUUID()); - return; - } - - targetType = msg.getTargetType(); - - if (targetType == Enum.GameObjectType.PlayerCharacter.ordinal()) { - target = PlayerCharacter.getFromCache(msg.getTargetID()); - } else if (targetType == Enum.GameObjectType.Building.ordinal()) { - target = BuildingManager.getBuildingFromCache(msg.getTargetID()); - } else if (targetType == Enum.GameObjectType.Mob.ordinal()) { - target = Mob.getFromCache(msg.getTargetID()); - } else { - player.setCombatTarget(null); - return; //not valid type to attack - } - - // quit of the combat target is already the current combat target - // or there is no combat target - - if (target == null) - return; - - //set sources target - - player.setCombatTarget(target); - - boolean hasMain = false; - boolean hasOff = false; - if(player.getCharItemManager() != null && player.getCharItemManager().getEquipped() != null){ - if(player.getCharItemManager().getEquipped(1) != null) - hasMain = true; - if(player.getCharItemManager().getEquipped(2) != null && !player.getCharItemManager().getEquipped(2).getItemBase().isShield()) - hasOff = true; - } - - if(hasMain){ - createTimer(player,true); - } - - if(hasOff){ - createTimer(player,false); - } - - } -}