From 1bff06cde00de842518c2b07ccd868b1ef643d15 Mon Sep 17 00:00:00 2001 From: FatBoy-DOTC Date: Mon, 8 Apr 2024 20:20:16 -0500 Subject: [PATCH 1/6] using building bounds and hitBox for mele range --- src/engine/gameManager/CombatManager.java | 27 ++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/engine/gameManager/CombatManager.java b/src/engine/gameManager/CombatManager.java index c621180d..56dc7890 100644 --- a/src/engine/gameManager/CombatManager.java +++ b/src/engine/gameManager/CombatManager.java @@ -12,6 +12,7 @@ import engine.job.JobContainer; import engine.job.JobScheduler; import engine.jobs.AttackJob; import engine.jobs.DeferredPowerJob; +import engine.math.Bounds; import engine.mbEnums; import engine.net.DispatchMessage; import engine.net.client.ClientConnection; @@ -23,6 +24,8 @@ import engine.powers.effectmodifiers.AbstractEffectModifier; import engine.server.MBServerStatics; import org.pmw.tinylog.Logger; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; import java.util.EnumSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; @@ -109,7 +112,29 @@ public enum CombatManager { float distanceSquared = attacker.loc.distanceSquared(target.loc); - if (distanceSquared > attackRange * attackRange) + boolean inRange = false; + + float attackerHitbox = attacker.calcHitBox(); + switch(target.getObjectType()){ + case PlayerCharacter: + case Mob: + float targetHitbox = ((AbstractCharacter)target).calcHitBox(); + if(distanceSquared < ((attackRange + attackerHitbox + targetHitbox) * 2)) + inRange = true; + break; + case Building: + float locX = target.loc.x - target.getBounds().getHalfExtents().x; + float locZ = target.loc.z - target.getBounds().getHalfExtents().y; + float sizeX = (target.getBounds().getHalfExtents().x + attackRange + attackerHitbox) * 2; + float sizeZ = (target.getBounds().getHalfExtents().y + attackRange + attackerHitbox) * 2; + Rectangle2D.Float rect = new Rectangle2D.Float(locX,locZ,sizeX,sizeZ); + if(rect.contains(new Point2D.Float(attacker.loc.x,attacker.loc.z))) + inRange = true; + break; + } + + + if (!inRange) return; // take stamina away from attacker From 4a001179b568c0fff04d2ff017cf2c3dc82f286d Mon Sep 17 00:00:00 2001 From: FatBoy-DOTC Date: Mon, 8 Apr 2024 20:37:27 -0500 Subject: [PATCH 2/6] add hitbox to abs vs abs range checks --- src/engine/gameManager/CombatManager.java | 302 +++++++++++----------- 1 file changed, 151 insertions(+), 151 deletions(-) diff --git a/src/engine/gameManager/CombatManager.java b/src/engine/gameManager/CombatManager.java index 56dc7890..f5b2b75d 100644 --- a/src/engine/gameManager/CombatManager.java +++ b/src/engine/gameManager/CombatManager.java @@ -86,9 +86,9 @@ public enum CombatManager { // heck if character can even attack yet - if (attacker.getTimestamps().containsKey("Attack" + slot.name())) - if (System.currentTimeMillis() < attacker.getTimestamps().get("Attack" + slot.name())) - return; + //if (attacker.getTimestamps().containsKey("Attack" + slot.name())) + // if (System.currentTimeMillis() < attacker.getTimestamps().get("Attack" + slot.name())) + // return; // check if character is in range to attack target @@ -114,19 +114,19 @@ public enum CombatManager { boolean inRange = false; - float attackerHitbox = attacker.calcHitBox(); + attackRange += attacker.calcHitBox(); switch(target.getObjectType()){ case PlayerCharacter: case Mob: - float targetHitbox = ((AbstractCharacter)target).calcHitBox(); - if(distanceSquared < ((attackRange + attackerHitbox + targetHitbox) * 2)) + attackRange += ((AbstractCharacter)target).calcHitBox(); + if(distanceSquared < attackRange * 2) inRange = true; break; case Building: float locX = target.loc.x - target.getBounds().getHalfExtents().x; float locZ = target.loc.z - target.getBounds().getHalfExtents().y; - float sizeX = (target.getBounds().getHalfExtents().x + attackRange + attackerHitbox) * 2; - float sizeZ = (target.getBounds().getHalfExtents().y + attackRange + attackerHitbox) * 2; + float sizeX = (target.getBounds().getHalfExtents().x + attackRange) * 2; + float sizeZ = (target.getBounds().getHalfExtents().y + attackRange) * 2; Rectangle2D.Float rect = new Rectangle2D.Float(locX,locZ,sizeX,sizeZ); if(rect.contains(new Point2D.Float(attacker.loc.x,attacker.loc.z))) inRange = true; @@ -134,213 +134,213 @@ public enum CombatManager { } - if (!inRange) - return; + if (inRange) { - // take stamina away from attacker + // take stamina away from attacker - if (weapon != null) { - float stam = weapon.template.item_wt / 3f; - stam = (stam < 1) ? 1 : stam; - attacker.modifyStamina(-(stam), attacker, true); - } else - attacker.modifyStamina(-0.5f, attacker, true); + if (weapon != null) { + float stam = weapon.template.item_wt / 3f; + stam = (stam < 1) ? 1 : stam; + attacker.modifyStamina(-(stam), attacker, true); + } else + attacker.modifyStamina(-0.5f, attacker, true); - //cancel things that are cancelled by an attack + //cancel things that are cancelled by an attack - attacker.cancelOnAttackSwing(); + attacker.cancelOnAttackSwing(); - //declare relevant variables + //declare relevant variables - int min = attacker.minDamageHandOne; - int max = attacker.maxDamageHandOne; - int atr = attacker.atrHandOne; + int min = attacker.minDamageHandOne; + int max = attacker.maxDamageHandOne; + int atr = attacker.atrHandOne; - //get the proper stats based on which slot is attacking + //get the proper stats based on which slot is attacking - if (slot == mbEnums.EquipSlotType.LHELD) { - min = attacker.minDamageHandTwo; - max = attacker.maxDamageHandTwo; - atr = attacker.atrHandTwo; - } + if (slot == mbEnums.EquipSlotType.LHELD) { + min = attacker.minDamageHandTwo; + max = attacker.maxDamageHandTwo; + atr = attacker.atrHandTwo; + } - int def = 0; + int def = 0; - if (AbstractCharacter.IsAbstractCharacter(target)) - def = ((AbstractCharacter) target).defenseRating; + if (AbstractCharacter.IsAbstractCharacter(target)) + def = ((AbstractCharacter) target).defenseRating; - //calculate hit chance based off ATR and DEF + //calculate hit chance based off ATR and DEF - int hitChance; - if (def == 0) - def = 1; - float dif = atr / def; + int hitChance; + if (def == 0) + def = 1; + float dif = atr / def; - if (dif <= 0.8f) - hitChance = 4; - else - hitChance = ((int) (450 * (dif - 0.8f)) + 4); + if (dif <= 0.8f) + hitChance = 4; + else + hitChance = ((int) (450 * (dif - 0.8f)) + 4); - if (target.getObjectType() == mbEnums.GameObjectType.Building) - hitChance = 100; + if (target.getObjectType() == mbEnums.GameObjectType.Building) + hitChance = 100; - int passiveAnim = getSwingAnimation(null, null, slot.equals(mbEnums.EquipSlotType.RHELD)); - if (attacker.charItemManager.getEquipped().get(slot) != null) { - passiveAnim = getSwingAnimation(attacker.charItemManager.getEquipped().get(slot).template, null, true); - } + int passiveAnim = getSwingAnimation(null, null, slot.equals(mbEnums.EquipSlotType.RHELD)); + if (attacker.charItemManager.getEquipped().get(slot) != null) { + passiveAnim = getSwingAnimation(attacker.charItemManager.getEquipped().get(slot).template, null, true); + } - if (ThreadLocalRandom.current().nextInt(100) > hitChance) { - TargetedActionMsg msg = new TargetedActionMsg(attacker, target, 0f, passiveAnim); + if (ThreadLocalRandom.current().nextInt(100) > hitChance) { + TargetedActionMsg msg = new TargetedActionMsg(attacker, target, 0f, passiveAnim); - if (target.getObjectType() == mbEnums.GameObjectType.PlayerCharacter) - DispatchMessage.dispatchMsgToInterestArea(target, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false); - else - DispatchMessage.sendToAllInRange(attacker, msg); + if (target.getObjectType() == mbEnums.GameObjectType.PlayerCharacter) + DispatchMessage.dispatchMsgToInterestArea(target, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false); + else + DispatchMessage.sendToAllInRange(attacker, msg); - return; - } + return; + } - //calculate passive chances only if target is AbstractCharacter + //calculate passive chances only if target is AbstractCharacter - if (EnumSet.of(mbEnums.GameObjectType.PlayerCharacter, mbEnums.GameObjectType.NPC, mbEnums.GameObjectType.Mob).contains(target.getObjectType())) { - mbEnums.PassiveType passiveType = mbEnums.PassiveType.None; - int hitRoll = ThreadLocalRandom.current().nextInt(100); + if (EnumSet.of(mbEnums.GameObjectType.PlayerCharacter, mbEnums.GameObjectType.NPC, mbEnums.GameObjectType.Mob).contains(target.getObjectType())) { + mbEnums.PassiveType passiveType = mbEnums.PassiveType.None; + int hitRoll = ThreadLocalRandom.current().nextInt(100); - float dodgeChance = ((AbstractCharacter) target).getPassiveChance("Dodge", attacker.getLevel(), true); - float blockChance = ((AbstractCharacter) target).getPassiveChance("Block", attacker.getLevel(), true); - float parryChance = ((AbstractCharacter) target).getPassiveChance("Parry", attacker.getLevel(), true); + float dodgeChance = ((AbstractCharacter) target).getPassiveChance("Dodge", attacker.getLevel(), true); + float blockChance = ((AbstractCharacter) target).getPassiveChance("Block", attacker.getLevel(), true); + float parryChance = ((AbstractCharacter) target).getPassiveChance("Parry", attacker.getLevel(), true); - // Passive chance clamped at 75 + // Passive chance clamped at 75 - dodgeChance = Math.max(0, Math.min(75, dodgeChance)); - blockChance = Math.max(0, Math.min(75, blockChance)); - parryChance = Math.max(0, Math.min(75, parryChance)); + dodgeChance = Math.max(0, Math.min(75, dodgeChance)); + blockChance = Math.max(0, Math.min(75, blockChance)); + parryChance = Math.max(0, Math.min(75, parryChance)); - if (hitRoll < dodgeChance) - passiveType = mbEnums.PassiveType.Dodge; - else if (hitRoll < blockChance) - passiveType = mbEnums.PassiveType.Block; - else if (hitRoll < parryChance) - passiveType = mbEnums.PassiveType.Parry; + if (hitRoll < dodgeChance) + passiveType = mbEnums.PassiveType.Dodge; + else if (hitRoll < blockChance) + passiveType = mbEnums.PassiveType.Block; + else if (hitRoll < parryChance) + passiveType = mbEnums.PassiveType.Parry; - if (passiveType.equals(mbEnums.PassiveType.None) == false) { - TargetedActionMsg msg = new TargetedActionMsg(attacker, passiveAnim, target, passiveType.value); + if (passiveType.equals(mbEnums.PassiveType.None) == false) { + TargetedActionMsg msg = new TargetedActionMsg(attacker, passiveAnim, target, passiveType.value); - if (target.getObjectType() == mbEnums.GameObjectType.PlayerCharacter) - DispatchMessage.dispatchMsgToInterestArea(target, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false); - else - DispatchMessage.sendToAllInRange(attacker, msg); + if (target.getObjectType() == mbEnums.GameObjectType.PlayerCharacter) + DispatchMessage.dispatchMsgToInterestArea(target, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false); + else + DispatchMessage.sendToAllInRange(attacker, msg); - return; + return; + } } - } - //calculate the base damage - int damage = ThreadLocalRandom.current().nextInt(min, max + 1); - if (damage == 0) - return; + //calculate the base damage + int damage = ThreadLocalRandom.current().nextInt(min, max + 1); + if (damage == 0) + return; - //get the damage type + //get the damage type - mbEnums.DamageType damageType; + mbEnums.DamageType damageType; - if (attacker.charItemManager.getEquipped().get(slot) == null) { - damageType = mbEnums.DamageType.CRUSHING; - if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob)) - if (((Mob) attacker).isSiege()) - damageType = mbEnums.DamageType.SIEGE; - } else { - damageType = (mbEnums.DamageType) attacker.charItemManager.getEquipped().get(slot).template.item_weapon_damage.keySet().toArray()[0]; - } + if (attacker.charItemManager.getEquipped().get(slot) == null) { + damageType = mbEnums.DamageType.CRUSHING; + if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob)) + if (((Mob) attacker).isSiege()) + damageType = mbEnums.DamageType.SIEGE; + } else { + damageType = (mbEnums.DamageType) attacker.charItemManager.getEquipped().get(slot).template.item_weapon_damage.keySet().toArray()[0]; + } - //get resists + //get resists - Resists resists; + Resists resists; - if (AbstractCharacter.IsAbstractCharacter(target) == false) - resists = ((Building) target).getResists(); //this is a building - else - resists = ((AbstractCharacter) target).getResists(); //this is a character + if (AbstractCharacter.IsAbstractCharacter(target) == false) + resists = ((Building) target).getResists(); //this is a building + else + resists = ((AbstractCharacter) target).getResists(); //this is a character - if (AbstractCharacter.IsAbstractCharacter(target)) { - AbstractCharacter absTarget = (AbstractCharacter) target; + if (AbstractCharacter.IsAbstractCharacter(target)) { + AbstractCharacter absTarget = (AbstractCharacter) target; - //check damage shields + //check damage shields - PlayerBonuses bonuses = absTarget.getBonuses(); + PlayerBonuses bonuses = absTarget.getBonuses(); - if (bonuses != null) { + if (bonuses != null) { - ConcurrentHashMap damageShields = bonuses.getDamageShields(); - float total = 0; + ConcurrentHashMap damageShields = bonuses.getDamageShields(); + float total = 0; - for (DamageShield ds : damageShields.values()) { + for (DamageShield ds : damageShields.values()) { - //get amount to damage back + //get amount to damage back - float amount; + float amount; - if (ds.usePercent()) - amount = damage * ds.getAmount() / 100; - else - amount = ds.getAmount(); + if (ds.usePercent()) + amount = damage * ds.getAmount() / 100; + else + amount = ds.getAmount(); - //get resisted damage for damagetype + //get resisted damage for damagetype - if (resists != null) - amount = resists.getResistedDamage(absTarget, attacker, ds.getDamageType(), amount, 0); - total += amount; - } + if (resists != null) + amount = resists.getResistedDamage(absTarget, attacker, ds.getDamageType(), amount, 0); + total += amount; + } - if (total > 0) { - //apply Damage back - attacker.modifyHealth(-total, absTarget, true); - TargetedActionMsg cmm = new TargetedActionMsg(attacker, attacker, total, 0); - DispatchMessage.sendToAllInRange(target, cmm); + if (total > 0) { + //apply Damage back + attacker.modifyHealth(-total, absTarget, true); + TargetedActionMsg cmm = new TargetedActionMsg(attacker, attacker, total, 0); + DispatchMessage.sendToAllInRange(target, cmm); + } } - } - if (resists != null) { + if (resists != null) { - //check for damage type immunities + //check for damage type immunities - if (resists.immuneTo(damageType)) - return; + if (resists.immuneTo(damageType)) + return; - //calculate resisted damage including fortitude + //calculate resisted damage including fortitude - damage = (int) resists.getResistedDamage(attacker, (AbstractCharacter) target, damageType, damage, 0); + damage = (int) resists.getResistedDamage(attacker, (AbstractCharacter) target, damageType, damage, 0); + } } - } - //remove damage from target health + //remove damage from target health - if (damage > 0) { + if (damage > 0) { - if (AbstractCharacter.IsAbstractCharacter(target)) - ((AbstractCharacter) target).modifyHealth(-damage, attacker, true); - else - ((Building) target).setCurrentHitPoints(target.getCurrentHitpoints() - damage); + if (AbstractCharacter.IsAbstractCharacter(target)) + ((AbstractCharacter) target).modifyHealth(-damage, attacker, true); + else + ((Building) target).setCurrentHitPoints(target.getCurrentHitpoints() - damage); - int attackAnim = getSwingAnimation(null, null, slot.equals(mbEnums.EquipSlotType.RHELD)); - if (attacker.charItemManager.getEquipped().get(slot) != null) { - attackAnim = getSwingAnimation(attacker.charItemManager.getEquipped().get(slot).template, null, slot.equals(mbEnums.EquipSlotType.RHELD)); + int attackAnim = getSwingAnimation(null, null, slot.equals(mbEnums.EquipSlotType.RHELD)); + if (attacker.charItemManager.getEquipped().get(slot) != null) { + attackAnim = getSwingAnimation(attacker.charItemManager.getEquipped().get(slot).template, null, slot.equals(mbEnums.EquipSlotType.RHELD)); + } + TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) damage, attackAnim); + DispatchMessage.sendToAllInRange(target, cmm); } - TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) damage, attackAnim); - DispatchMessage.sendToAllInRange(target, cmm); - } - DeferredPowerJob dpj = null; + DeferredPowerJob dpj = null; - if (attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)) { + if (attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)) { - dpj = ((PlayerCharacter) attacker).getWeaponPower(); + dpj = ((PlayerCharacter) attacker).getWeaponPower(); - if (dpj != null) { - dpj.attack(target, attackRange); + if (dpj != null) { + dpj.attack(target, attackRange); - if (dpj.getPower() != null && (dpj.getPowerToken() == -1851459567 || dpj.getPowerToken() == -1851489518)) - ((PlayerCharacter) attacker).setWeaponPower(dpj); + if (dpj.getPower() != null && (dpj.getPowerToken() == -1851459567 || dpj.getPowerToken() == -1851489518)) + ((PlayerCharacter) attacker).setWeaponPower(dpj); + } } } //calculate next allowed attack and update the timestamp From dc81ddaba78ec7a3ee9ab087b1236cd7ded5fe44 Mon Sep 17 00:00:00 2001 From: FatBoy-DOTC Date: Tue, 9 Apr 2024 21:23:29 -0500 Subject: [PATCH 3/6] handle retaliate when being attacked --- src/engine/gameManager/CombatManager.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/engine/gameManager/CombatManager.java b/src/engine/gameManager/CombatManager.java index f5b2b75d..9f9566b2 100644 --- a/src/engine/gameManager/CombatManager.java +++ b/src/engine/gameManager/CombatManager.java @@ -136,6 +136,13 @@ public enum CombatManager { if (inRange) { + //handle retaliate + if(AbstractCharacter.IsAbstractCharacter(target)){ + if(((AbstractCharacter)target).combatTarget == null){ + ((AbstractCharacter)target).combatTarget = attacker; + } + } + // take stamina away from attacker if (weapon != null) { From 79f4a33b6efc87bc2f3db81ef02c3cbc9183ab47 Mon Sep 17 00:00:00 2001 From: FatBoy-DOTC Date: Sat, 13 Apr 2024 19:10:10 -0500 Subject: [PATCH 4/6] add half player character height to attack range in lieu of hitbox --- src/engine/gameManager/CombatManager.java | 40 ++++++++++++++--------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/engine/gameManager/CombatManager.java b/src/engine/gameManager/CombatManager.java index 9f9566b2..0a61159c 100644 --- a/src/engine/gameManager/CombatManager.java +++ b/src/engine/gameManager/CombatManager.java @@ -113,13 +113,20 @@ public enum CombatManager { float distanceSquared = attacker.loc.distanceSquared(target.loc); boolean inRange = false; - - attackRange += attacker.calcHitBox(); + if(attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)){ + attackRange += ((PlayerCharacter)attacker).getCharacterHeight() * 0.5f; + }else { + attackRange += attacker.calcHitBox(); + } switch(target.getObjectType()){ case PlayerCharacter: + attackRange += ((PlayerCharacter)target).getCharacterHeight() * 0.5f; + if(distanceSquared < attackRange * attackRange) + inRange = true; + break; case Mob: attackRange += ((AbstractCharacter)target).calcHitBox(); - if(distanceSquared < attackRange * 2) + if(distanceSquared < attackRange * attackRange) inRange = true; break; case Building: @@ -143,6 +150,20 @@ public enum CombatManager { } } + DeferredPowerJob dpj = null; + + if (attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)) { + + dpj = ((PlayerCharacter) attacker).getWeaponPower(); + + if (dpj != null) { + dpj.attack(target, attackRange); + + if (dpj.getPower() != null && (dpj.getPowerToken() == -1851459567 || dpj.getPowerToken() == -1851489518)) + ((PlayerCharacter) attacker).setWeaponPower(dpj); + } + } + // take stamina away from attacker if (weapon != null) { @@ -336,19 +357,6 @@ public enum CombatManager { TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) damage, attackAnim); DispatchMessage.sendToAllInRange(target, cmm); } - DeferredPowerJob dpj = null; - - if (attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)) { - - dpj = ((PlayerCharacter) attacker).getWeaponPower(); - - if (dpj != null) { - dpj.attack(target, attackRange); - - if (dpj.getPower() != null && (dpj.getPowerToken() == -1851459567 || dpj.getPowerToken() == -1851489518)) - ((PlayerCharacter) attacker).setWeaponPower(dpj); - } - } } //calculate next allowed attack and update the timestamp From 3f27bae09958a23be6e1a5f0627dfe4fe103e1af Mon Sep 17 00:00:00 2001 From: FatBoy-DOTC Date: Sat, 13 Apr 2024 19:12:09 -0500 Subject: [PATCH 5/6] mobs dont double tap when unarmed --- src/engine/gameManager/CombatManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/gameManager/CombatManager.java b/src/engine/gameManager/CombatManager.java index 0a61159c..9b5561e1 100644 --- a/src/engine/gameManager/CombatManager.java +++ b/src/engine/gameManager/CombatManager.java @@ -62,7 +62,8 @@ public enum CombatManager { if (mainWeapon == null && offWeapon == null) { //no weapons equipped, punch with both fists processAttack(attacker, target, mbEnums.EquipSlotType.RHELD); - processAttack(attacker, target, mbEnums.EquipSlotType.LHELD); + if(attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)) + processAttack(attacker, target, mbEnums.EquipSlotType.LHELD); } else if (mainWeapon == null && offWeapon != null && offWeapon.template.item_skill_required.containsKey("Block")) { //no weapon equipped with a shield, punch with one hand processAttack(attacker, target, mbEnums.EquipSlotType.RHELD); From 2aaca661e2cf6ae2d74882d08a5dd8cb028e46fb Mon Sep 17 00:00:00 2001 From: FatBoy-DOTC Date: Sat, 13 Apr 2024 19:44:03 -0500 Subject: [PATCH 6/6] new combat finalized --- src/engine/gameManager/CombatManager.java | 115 ++++++++++++++++------ src/engine/mobileAI/MobAI.java | 13 +-- 2 files changed, 85 insertions(+), 43 deletions(-) diff --git a/src/engine/gameManager/CombatManager.java b/src/engine/gameManager/CombatManager.java index 9b5561e1..71c7fae3 100644 --- a/src/engine/gameManager/CombatManager.java +++ b/src/engine/gameManager/CombatManager.java @@ -41,6 +41,10 @@ public enum CombatManager { if (attacker == null || target == null || !attacker.isAlive() || !target.isAlive()) return; + if(attacker.getObjectType().equals(mbEnums.GameObjectType.Mob)) + if (((Mob) attacker).nextAttackTime > System.currentTimeMillis()) + return; + switch (target.getObjectType()) { case Building: if (((Building) target).isVulnerable() == false) @@ -85,12 +89,6 @@ public enum CombatManager { public static void processAttack(AbstractCharacter attacker, AbstractWorldObject target, mbEnums.EquipSlotType slot) { - // heck if character can even attack yet - - //if (attacker.getTimestamps().containsKey("Attack" + slot.name())) - // if (System.currentTimeMillis() < attacker.getTimestamps().get("Attack" + slot.name())) - // return; - // check if character is in range to attack target PlayerBonuses bonus = attacker.getBonuses(); @@ -141,13 +139,36 @@ public enum CombatManager { break; } + //get delay for the auto attack job + long delay = 5000; + + if (weapon != null) { + + int wepSpeed = (int) (weapon.template.item_weapon_wepspeed); + + if (weapon.getBonusPercent(mbEnums.ModType.WeaponSpeed, mbEnums.SourceType.None) != 0f) //add weapon speed bonus + wepSpeed *= (1 + weapon.getBonus(mbEnums.ModType.WeaponSpeed, mbEnums.SourceType.None)); + + if (attacker.getBonuses() != null && attacker.getBonuses().getFloatPercentAll(mbEnums.ModType.AttackDelay, mbEnums.SourceType.None) != 0f) //add effects speed bonus + wepSpeed *= (1 + attacker.getBonuses().getFloatPercentAll(mbEnums.ModType.AttackDelay, mbEnums.SourceType.None)); + + if (wepSpeed < 10) + wepSpeed = 10; //Old was 10, but it can be reached lower with legit buffs,effects. + + delay = wepSpeed * 100; + } + + if(attacker.getObjectType().equals(mbEnums.GameObjectType.Mob)) + ((Mob)attacker).nextAttackTime = System.currentTimeMillis() + delay; if (inRange) { //handle retaliate if(AbstractCharacter.IsAbstractCharacter(target)){ - if(((AbstractCharacter)target).combatTarget == null){ + if(((AbstractCharacter)target).combatTarget == null || ((AbstractCharacter)target).combatTarget.isAlive() == false){ ((AbstractCharacter)target).combatTarget = attacker; + if(target.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter) && ((AbstractCharacter) target).isCombat()) + combatCycle((AbstractCharacter) target, attacker); } } @@ -225,6 +246,19 @@ public enum CombatManager { else DispatchMessage.sendToAllInRange(attacker, msg); + //calculate next allowed attack and update the timestamp + attacker.getTimestamps().put("Attack" + slot.name(), System.currentTimeMillis() + delay); + + //handle auto attack job creation + ConcurrentHashMap timers = attacker.getTimers(); + + if (timers != null) { + AttackJob aj = new AttackJob(attacker, slot.ordinal(), true); + JobContainer job; + job = JobScheduler.getInstance().scheduleJob(aj, (System.currentTimeMillis() + delay)); // offset 1 millisecond so no overlap issue + timers.put("Attack" + slot, job); + } else + Logger.error("Unable to find Timers for Character " + attacker.getObjectUUID()); return; } @@ -260,15 +294,41 @@ public enum CombatManager { else DispatchMessage.sendToAllInRange(attacker, msg); + //calculate next allowed attack and update the timestamp + attacker.getTimestamps().put("Attack" + slot.name(), System.currentTimeMillis() + delay); + + //handle auto attack job creation + ConcurrentHashMap timers = attacker.getTimers(); + + if (timers != null) { + AttackJob aj = new AttackJob(attacker, slot.ordinal(), true); + JobContainer job; + job = JobScheduler.getInstance().scheduleJob(aj, (System.currentTimeMillis() + delay)); // offset 1 millisecond so no overlap issue + timers.put("Attack" + slot, job); + } else + Logger.error("Unable to find Timers for Character " + attacker.getObjectUUID()); return; } } //calculate the base damage int damage = ThreadLocalRandom.current().nextInt(min, max + 1); - if (damage == 0) + if (damage == 0) { + //calculate next allowed attack and update the timestamp + attacker.getTimestamps().put("Attack" + slot.name(), System.currentTimeMillis() + delay); + + //handle auto attack job creation + ConcurrentHashMap timers = attacker.getTimers(); + + if (timers != null) { + AttackJob aj = new AttackJob(attacker, slot.ordinal(), true); + JobContainer job; + job = JobScheduler.getInstance().scheduleJob(aj, (System.currentTimeMillis() + delay)); // offset 1 millisecond so no overlap issue + timers.put("Attack" + slot, job); + } else + Logger.error("Unable to find Timers for Character " + attacker.getObjectUUID()); return; - + } //get the damage type mbEnums.DamageType damageType; @@ -333,9 +393,22 @@ public enum CombatManager { //check for damage type immunities - if (resists.immuneTo(damageType)) - return; + if (resists.immuneTo(damageType)) { + //calculate next allowed attack and update the timestamp + attacker.getTimestamps().put("Attack" + slot.name(), System.currentTimeMillis() + delay); + + //handle auto attack job creation + ConcurrentHashMap timers = attacker.getTimers(); + if (timers != null) { + AttackJob aj = new AttackJob(attacker, slot.ordinal(), true); + JobContainer job; + job = JobScheduler.getInstance().scheduleJob(aj, (System.currentTimeMillis() + delay)); // offset 1 millisecond so no overlap issue + timers.put("Attack" + slot, job); + } else + Logger.error("Unable to find Timers for Character " + attacker.getObjectUUID()); + return; + } //calculate resisted damage including fortitude damage = (int) resists.getResistedDamage(attacker, (AbstractCharacter) target, damageType, damage, 0); @@ -360,29 +433,9 @@ public enum CombatManager { } } //calculate next allowed attack and update the timestamp - - long delay = 20 * 100; - - if (weapon != null) { - - int wepSpeed = (int) (weapon.template.item_weapon_wepspeed); - - if (weapon.getBonusPercent(mbEnums.ModType.WeaponSpeed, mbEnums.SourceType.None) != 0f) //add weapon speed bonus - wepSpeed *= (1 + weapon.getBonus(mbEnums.ModType.WeaponSpeed, mbEnums.SourceType.None)); - - if (attacker.getBonuses() != null && attacker.getBonuses().getFloatPercentAll(mbEnums.ModType.AttackDelay, mbEnums.SourceType.None) != 0f) //add effects speed bonus - wepSpeed *= (1 + attacker.getBonuses().getFloatPercentAll(mbEnums.ModType.AttackDelay, mbEnums.SourceType.None)); - - if (wepSpeed < 10) - wepSpeed = 10; //Old was 10, but it can be reached lower with legit buffs,effects. - - delay = wepSpeed * 100; - } - attacker.getTimestamps().put("Attack" + slot.name(), System.currentTimeMillis() + delay); //handle auto attack job creation - ConcurrentHashMap timers = attacker.getTimers(); if (timers != null) { diff --git a/src/engine/mobileAI/MobAI.java b/src/engine/mobileAI/MobAI.java index e51b7e34..27e9173a 100644 --- a/src/engine/mobileAI/MobAI.java +++ b/src/engine/mobileAI/MobAI.java @@ -764,19 +764,8 @@ public class MobAI { mob.setCombatTarget(null); return; } - if (System.currentTimeMillis() > mob.getNextAttackTime()) { - int delay = 3000; - if (mob.charItemManager.getEquipped().get(mbEnums.EquipSlotType.RHELD) != null) { - delay = (int) (mob.charItemManager.getEquipped().get(mbEnums.EquipSlotType.RHELD).template.item_weapon_wepspeed * 100); - } - if (mob.charItemManager.getEquipped().get(mbEnums.EquipSlotType.LHELD) != null && mob.charItemManager.getEquipped().get(mbEnums.EquipSlotType.LHELD).template.item_type.equals(mbEnums.ItemType.WEAPON)) { - delay += (int) (mob.charItemManager.getEquipped().get(mbEnums.EquipSlotType.LHELD).template.item_weapon_wepspeed * 100); - } + AttackTarget(mob, mob.getCombatTarget()); - - mob.nextAttackTime = System.currentTimeMillis() + delay; - AttackTarget(mob, mob.getCombatTarget()); - } } catch (Exception e) { Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckForAttack" + " " + e.getMessage()); }