Browse Source

rentrant lock on combat

combat-3
FatBoy-DOTC 7 months ago
parent
commit
cf58e7b984
  1. 518
      src/engine/gameManager/CombatManager.java
  2. 1
      src/engine/objects/AbstractWorldObject.java

518
src/engine/gameManager/CombatManager.java

@ -12,7 +12,6 @@ import engine.job.JobContainer; @@ -12,7 +12,6 @@ import engine.job.JobContainer;
import engine.job.JobScheduler;
import engine.jobs.AttackJob;
import engine.jobs.DeferredPowerJob;
import engine.math.Vector3f;
import engine.mbEnums;
import engine.net.client.ClientConnection;
import engine.net.client.msg.TargetedActionMsg;
@ -119,361 +118,360 @@ public enum CombatManager { @@ -119,361 +118,360 @@ public enum CombatManager {
public static void processAttack(AbstractCharacter attacker, AbstractWorldObject target, mbEnums.EquipSlotType slot) {
if(slot == null || target == null || attacker == null)
if (slot == null || target == null || attacker == null)
return;
if (attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)) {
if (!attacker.isCombat())
return;
//check if this slot is on attack timer, if timer has passed clear it, else early exit
if(attacker.getTimers() != null && attacker.getTimers().containsKey("Attack"+slot.name()))
if(attacker.getTimers().get("Attack"+slot.name()).timeToExecutionLeft() <= 0)
attacker.getTimers().remove("Attack"+slot.name());
else
return;
}
target.combatLock.writeLock().lock();
// check if character is in range to attack target
try {
PlayerBonuses bonus = attacker.getBonuses();
PlayerBonuses bonus = attacker.getBonuses();
float rangeMod = 1.0f;
float attackRange = MBServerStatics.NO_WEAPON_RANGE;
float rangeMod = 1.0f;
float attackRange = MBServerStatics.NO_WEAPON_RANGE;
Item weapon = attacker.charItemManager.getEquipped(slot);
Item weapon = attacker.charItemManager.getEquipped(slot);
if (weapon != null) {
if (bonus != null)
rangeMod += bonus.getFloatPercentAll(mbEnums.ModType.WeaponRange, mbEnums.SourceType.None);
if (weapon != null) {
if (bonus != null)
rangeMod += bonus.getFloatPercentAll(mbEnums.ModType.WeaponRange, mbEnums.SourceType.None);
attackRange += weapon.template.item_weapon_max_range * rangeMod;
}
attackRange += weapon.template.item_weapon_max_range * rangeMod;
}
if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob))
if (((Mob) attacker).isSiege())
attackRange = 300;
if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob))
if (((Mob) attacker).isSiege())
attackRange = 300;
float distanceSquared = attacker.loc.distanceSquared(target.loc);
float distanceSquared = attacker.loc.distanceSquared(target.loc);
boolean inRange = false;
if (AbstractCharacter.IsAbstractCharacter(target)) {
attackRange += ((AbstractCharacter)target).calcHitBox();
} else {
boolean inRange = false;
if (AbstractCharacter.IsAbstractCharacter(target)) {
attackRange += ((AbstractCharacter) target).calcHitBox();
} else {
}
}
if(attackRange > 15 && attacker.isMoving()){
//cannot shoot bow while moving;
return;
}
if (attackRange > 15 && attacker.isMoving()) {
//cannot shoot bow while moving;
return;
}
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 * attackRange)
inRange = true;
break;
case Building:
if(attackRange > 15){
float rangeSquared = (attackRange + target.getBounds().getHalfExtents().x) * (attackRange + target.getBounds().getHalfExtents().x);
//float distanceSquared = attacker.loc.distanceSquared(target.loc);
if(distanceSquared < rangeSquared) {
switch (target.getObjectType()) {
case PlayerCharacter:
attackRange += ((PlayerCharacter) target).getCharacterHeight() * 0.5f;
if (distanceSquared < attackRange * attackRange)
inRange = true;
break;
}
}else {
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) * 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)))
break;
case Mob:
attackRange += ((AbstractCharacter) target).calcHitBox();
if (distanceSquared < attackRange * attackRange)
inRange = true;
break;
}
}
case Building:
if (attackRange > 15) {
float rangeSquared = (attackRange + target.getBounds().getHalfExtents().x) * (attackRange + target.getBounds().getHalfExtents().x);
//float distanceSquared = attacker.loc.distanceSquared(target.loc);
if (distanceSquared < rangeSquared) {
inRange = true;
break;
}
} else {
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) * 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;
break;
}
}
//get delay for the auto attack job
long delay = 5000;
//get delay for the auto attack job
long delay = 5000;
if (weapon != null) {
if (weapon != null) {
int wepSpeed = (int) (weapon.template.item_weapon_wepspeed);
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 (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 (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.
if (wepSpeed < 10)
wepSpeed = 10; //Old was 10, but it can be reached lower with legit buffs,effects.
delay = wepSpeed * 100L;
}
delay = wepSpeed * 100L;
}
if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob))
((Mob) attacker).nextAttackTime = System.currentTimeMillis() + delay;
if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob))
((Mob) attacker).nextAttackTime = System.currentTimeMillis() + delay;
if (inRange) {
if (inRange) {
//handle retaliate
if (AbstractCharacter.IsAbstractCharacter(target)) {
if (((AbstractCharacter) target).combatTarget == null || !((AbstractCharacter) target).combatTarget.isAlive()) {
((AbstractCharacter) target).combatTarget = attacker;
if (target.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter) && ((AbstractCharacter) target).isCombat())
combatCycle((AbstractCharacter) target, attacker);
//handle retaliate
if (AbstractCharacter.IsAbstractCharacter(target)) {
if (((AbstractCharacter) target).combatTarget == null || !((AbstractCharacter) target).combatTarget.isAlive()) {
((AbstractCharacter) target).combatTarget = attacker;
if (target.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter) && ((AbstractCharacter) target).isCombat())
combatCycle((AbstractCharacter) target, attacker);
}
}
}
// take stamina away from attacker if its not a mob
if (weapon != null && !attacker.getObjectType().equals(mbEnums.GameObjectType.Mob)) {
//check if Out of Stamina
if (attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)) {
if (attacker.getStamina() < (weapon.template.item_wt / 3f)) {
//set auto attack job
setAutoAttackJob(attacker, slot, delay);
return;
// take stamina away from attacker if its not a mob
if (weapon != null && !attacker.getObjectType().equals(mbEnums.GameObjectType.Mob)) {
//check if Out of Stamina
if (attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)) {
if (attacker.getStamina() < (weapon.template.item_wt / 3f)) {
//set auto attack job
setAutoAttackJob(attacker, slot, delay);
return;
}
}
}
float stam = weapon.template.item_wt / 3f;
stam = (stam < 1) ? 1 : stam;
attacker.modifyStamina(-(stam), attacker, true);
} else
attacker.modifyStamina(1, attacker, true);
float stam = weapon.template.item_wt / 3f;
stam = (stam < 1) ? 1 : stam;
attacker.modifyStamina(-(stam), attacker, true);
} else
attacker.modifyStamina(1, 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;
}
//apply weapon powers before early exit for miss or passives
DeferredPowerJob dpj = null;
//apply weapon powers before early exit for miss or passives
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);
}
}
}
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 * 1f / def;
int hitChance;
if (def == 0)
def = 1;
float dif = atr * 1f / 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;
int passiveAnim = getPassiveAnimation(mbEnums.PassiveType.None); // checking for a miss due to ATR vs Def
if (ThreadLocalRandom.current().nextInt(100) > hitChance) {
TargetedActionMsg msg = new TargetedActionMsg(attacker, target, 0f, passiveAnim);
if (target.getObjectType() == mbEnums.GameObjectType.Building)
hitChance = 100;
int passiveAnim = getPassiveAnimation(mbEnums.PassiveType.None); // checking for a miss due to ATR vs Def
if (ThreadLocalRandom.current().nextInt(100) > hitChance) {
TargetedActionMsg msg = new TargetedActionMsg(attacker, target, 0f, passiveAnim);
if (target.getObjectType() == mbEnums.GameObjectType.PlayerCharacter)
DispatchManager.dispatchMsgToInterestArea(target, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
else
DispatchManager.sendToAllInRange(attacker, msg);
if (target.getObjectType() == mbEnums.GameObjectType.PlayerCharacter)
DispatchManager.dispatchMsgToInterestArea(target, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
else
DispatchManager.sendToAllInRange(attacker, msg);
//we need to send the animation even if the attacker misses
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template,null,slot));
DispatchManager.sendToAllInRange(target, cmm);
//we need to send the animation even if the attacker misses
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template, null, slot));
DispatchManager.sendToAllInRange(target, cmm);
//set auto attack job
setAutoAttackJob(attacker, slot, delay);
return;
}
//set auto attack job
setAutoAttackJob(attacker, slot, delay);
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)) {
passiveAnim = getPassiveAnimation(passiveType);
TargetedActionMsg msg = new TargetedActionMsg(attacker, passiveAnim, target, passiveType.value);
if (!passiveType.equals(mbEnums.PassiveType.None)) {
passiveAnim = getPassiveAnimation(passiveType);
TargetedActionMsg msg = new TargetedActionMsg(attacker, passiveAnim, target, passiveType.value);
if (target.getObjectType() == mbEnums.GameObjectType.PlayerCharacter)
DispatchManager.dispatchMsgToInterestArea(target, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
if (target.getObjectType() == mbEnums.GameObjectType.PlayerCharacter)
DispatchManager.dispatchMsgToInterestArea(target, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
//we need to send the animation even if the attacker misses
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template,null,slot));
DispatchManager.sendToAllInRange(target, cmm);
//we need to send the animation even if the attacker misses
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template, null, slot));
DispatchManager.sendToAllInRange(target, cmm);
//set auto attack job
setAutoAttackJob(attacker, slot, delay);
return;
}
}
//calculate the base damage
int damage = ThreadLocalRandom.current().nextInt(min, max + 1);
if (damage == 0) {
//set auto attack job
setAutoAttackJob(attacker, slot, delay);
return;
}
}
if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob) && ((Mob) attacker).isPet())
calculatePetDamage(attacker);
//calculate the base damage
int damage = ThreadLocalRandom.current().nextInt(min, max + 1);
if (damage == 0) {
//set auto attack job
setAutoAttackJob(attacker, slot, delay);
return;
}
if(attacker.getObjectType().equals(mbEnums.GameObjectType.Mob) && ((Mob)attacker).isPet())
calculatePetDamage(attacker);
//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))
resists = ((Building) target).getResists(); //this is a building
else
resists = ((AbstractCharacter) target).getResists(); //this is a character
if (!AbstractCharacter.IsAbstractCharacter(target))
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<AbstractEffectModifier, DamageShield> damageShields = bonuses.getDamageShields();
float total = 0;
ConcurrentHashMap<AbstractEffectModifier, DamageShield> 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);
DispatchManager.sendToAllInRange(target, cmm);
}
}
if (total > 0) {
//apply Damage back
attacker.modifyHealth(-total, absTarget, true);
TargetedActionMsg cmm = new TargetedActionMsg(attacker, attacker, total, 0);
DispatchManager.sendToAllInRange(target, cmm);
}
}
if (resists != null) {
if (resists != null) {
//check for damage type immunities
//check for damage type immunities
if (resists.immuneTo(damageType)) {
//set auto attack job
//we need to send the animation even if the attacker misses
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template, null, slot));
DispatchManager.sendToAllInRange(target, cmm);
setAutoAttackJob(attacker, slot, delay);
return;
}
//calculate resisted damage including fortitude
if (resists.immuneTo(damageType)) {
//set auto attack job
//we need to send the animation even if the attacker misses
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template,null,slot));
DispatchManager.sendToAllInRange(target, cmm);
setAutoAttackJob(attacker, slot, delay);
return;
damage = (int) resists.getResistedDamage(attacker, (AbstractCharacter) target, damageType, damage, 0);
}
//calculate resisted damage including fortitude
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).modifyHealth(-damage, attacker);
if (AbstractCharacter.IsAbstractCharacter(target))
((AbstractCharacter) target).modifyHealth(-damage, attacker, true);
else
((Building) target).modifyHealth(-damage, attacker);
int attackAnim = getSwingAnimation(null, null, slot);
if (attacker.charItemManager.getEquipped().get(slot) != null) {
if (attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)) {
DeferredPowerJob weaponPower = ((PlayerCharacter) attacker).getWeaponPower();
attackAnim = getSwingAnimation(weapon.template, weaponPower, slot);
} else {
attackAnim = getSwingAnimation(weapon.template, null, slot);
int attackAnim = getSwingAnimation(null, null, slot);
if (attacker.charItemManager.getEquipped().get(slot) != null) {
if (attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)) {
DeferredPowerJob weaponPower = ((PlayerCharacter) attacker).getWeaponPower();
attackAnim = getSwingAnimation(weapon.template, weaponPower, slot);
} else {
attackAnim = getSwingAnimation(weapon.template, null, slot);
}
}
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) damage, attackAnim);
DispatchManager.sendToAllInRange(target, cmm);
}
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) damage, attackAnim);
DispatchManager.sendToAllInRange(target, cmm);
}
}
//set auto attack job
setAutoAttackJob(attacker, slot, delay);
//set auto attack job
setAutoAttackJob(attacker, slot, delay);
} catch (Exception ex) {
cancelAutoAttackJob(attacker,slot);
//Logger.error("COMBAT CAUGHT ERROR: " + ex.getMessage());
} finally {
target.combatLock.writeLock().unlock();
}
}
public static void toggleCombat(boolean toggle, ClientConnection origin) {
@ -624,7 +622,20 @@ public enum CombatManager { @@ -624,7 +622,20 @@ public enum CombatManager {
Logger.error("Unable to find Timers for Character " + attacker.getObjectUUID());
}
public static int calculatePetDamage(AbstractCharacter agent) {
public static void cancelAutoAttackJob(AbstractCharacter attacker, mbEnums.EquipSlotType slot) {
attacker.getTimestamps().put("Attack" + slot.name(), System.currentTimeMillis());
//handle auto attack job creation
ConcurrentHashMap<String, JobContainer> timers = attacker.getTimers();
if (timers != null) {
timers.get("Attack" + slot.name()).cancelJob();
} else
Logger.error("Unable to find Timers for Character " + attacker.getObjectUUID());
}
public static void calculatePetDamage(AbstractCharacter agent) {
//damage calc for pet
float range;
float damage;
@ -636,7 +647,6 @@ public enum CombatManager { @@ -636,7 +647,6 @@ public enum CombatManager {
dmgMultiplier += agent.getLevel() * 0.1f;
range = (float) (maxDmg - minDmg);
damage = min + ((ThreadLocalRandom.current().nextFloat() * range) + (ThreadLocalRandom.current().nextFloat() * range)) / 2;
return (int) (damage * dmgMultiplier);
}
public static double getMinDmg(double min, AbstractCharacter agent) {
int primary = agent.getStatStrCurrent();

1
src/engine/objects/AbstractWorldObject.java

@ -59,6 +59,7 @@ public abstract class AbstractWorldObject extends AbstractGameObject { @@ -59,6 +59,7 @@ public abstract class AbstractWorldObject extends AbstractGameObject {
private Vector3f rot = new Vector3f(0.0f, 0.0f, 0.0f);
private int objectTypeMask = 0;
private Bounds bounds;
public ReentrantReadWriteLock combatLock = new ReentrantReadWriteLock();
/**
* No Id Constructor

Loading…
Cancel
Save