|
|
@ -12,7 +12,6 @@ import engine.job.JobContainer; |
|
|
|
import engine.job.JobScheduler; |
|
|
|
import engine.job.JobScheduler; |
|
|
|
import engine.jobs.AttackJob; |
|
|
|
import engine.jobs.AttackJob; |
|
|
|
import engine.jobs.DeferredPowerJob; |
|
|
|
import engine.jobs.DeferredPowerJob; |
|
|
|
import engine.math.Vector3f; |
|
|
|
|
|
|
|
import engine.mbEnums; |
|
|
|
import engine.mbEnums; |
|
|
|
import engine.net.client.ClientConnection; |
|
|
|
import engine.net.client.ClientConnection; |
|
|
|
import engine.net.client.msg.TargetedActionMsg; |
|
|
|
import engine.net.client.msg.TargetedActionMsg; |
|
|
@ -124,9 +123,9 @@ public enum CombatManager { |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
//check if this slot is on attack timer, if timer has passed clear it, else early exit
|
|
|
|
//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() != null && attacker.getTimers().containsKey("Attack" + slot.name())) |
|
|
|
if(attacker.getTimers().get("Attack"+slot.name()).timeToExecutionLeft() <= 0) |
|
|
|
if (attacker.getTimers().get("Attack" + slot.name()).timeToExecutionLeft() <= 0) |
|
|
|
attacker.getTimers().remove("Attack"+slot.name()); |
|
|
|
attacker.getTimers().remove("Attack" + slot.name()); |
|
|
|
else |
|
|
|
else |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
@ -156,12 +155,12 @@ public enum CombatManager { |
|
|
|
|
|
|
|
|
|
|
|
boolean inRange = false; |
|
|
|
boolean inRange = false; |
|
|
|
if (AbstractCharacter.IsAbstractCharacter(target)) { |
|
|
|
if (AbstractCharacter.IsAbstractCharacter(target)) { |
|
|
|
attackRange += ((AbstractCharacter)target).calcHitBox(); |
|
|
|
attackRange += ((AbstractCharacter) target).calcHitBox(); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(attackRange > 15 && attacker.isMoving()){ |
|
|
|
if (attackRange > 15 && attacker.isMoving()) { |
|
|
|
//cannot shoot bow while moving;
|
|
|
|
//cannot shoot bow while moving;
|
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
@ -178,14 +177,14 @@ public enum CombatManager { |
|
|
|
inRange = true; |
|
|
|
inRange = true; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case Building: |
|
|
|
case Building: |
|
|
|
if(attackRange > 15){ |
|
|
|
if (attackRange > 15) { |
|
|
|
float rangeSquared = (attackRange + target.getBounds().getHalfExtents().x) * (attackRange + target.getBounds().getHalfExtents().x); |
|
|
|
float rangeSquared = (attackRange + target.getBounds().getHalfExtents().x) * (attackRange + target.getBounds().getHalfExtents().x); |
|
|
|
//float distanceSquared = attacker.loc.distanceSquared(target.loc);
|
|
|
|
//float distanceSquared = attacker.loc.distanceSquared(target.loc);
|
|
|
|
if(distanceSquared < rangeSquared) { |
|
|
|
if (distanceSquared < rangeSquared) { |
|
|
|
inRange = true; |
|
|
|
inRange = true; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
}else { |
|
|
|
} else { |
|
|
|
float locX = target.loc.x - target.getBounds().getHalfExtents().x; |
|
|
|
float locX = target.loc.x - target.getBounds().getHalfExtents().x; |
|
|
|
float locZ = target.loc.z - target.getBounds().getHalfExtents().y; |
|
|
|
float locZ = target.loc.z - target.getBounds().getHalfExtents().y; |
|
|
|
float sizeX = (target.getBounds().getHalfExtents().x + attackRange) * 2; |
|
|
|
float sizeX = (target.getBounds().getHalfExtents().x + attackRange) * 2; |
|
|
@ -309,7 +308,7 @@ public enum CombatManager { |
|
|
|
DispatchManager.sendToAllInRange(attacker, msg); |
|
|
|
DispatchManager.sendToAllInRange(attacker, msg); |
|
|
|
|
|
|
|
|
|
|
|
//we need to send the animation even if the attacker misses
|
|
|
|
//we need to send the animation even if the attacker misses
|
|
|
|
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template,null,slot)); |
|
|
|
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template, null, slot)); |
|
|
|
DispatchManager.sendToAllInRange(target, cmm); |
|
|
|
DispatchManager.sendToAllInRange(target, cmm); |
|
|
|
|
|
|
|
|
|
|
|
//set auto attack job
|
|
|
|
//set auto attack job
|
|
|
@ -349,7 +348,7 @@ public enum CombatManager { |
|
|
|
DispatchManager.dispatchMsgToInterestArea(target, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false); |
|
|
|
DispatchManager.dispatchMsgToInterestArea(target, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false); |
|
|
|
|
|
|
|
|
|
|
|
//we need to send the animation even if the attacker misses
|
|
|
|
//we need to send the animation even if the attacker misses
|
|
|
|
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template,null,slot)); |
|
|
|
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template, null, slot)); |
|
|
|
DispatchManager.sendToAllInRange(target, cmm); |
|
|
|
DispatchManager.sendToAllInRange(target, cmm); |
|
|
|
//set auto attack job
|
|
|
|
//set auto attack job
|
|
|
|
setAutoAttackJob(attacker, slot, delay); |
|
|
|
setAutoAttackJob(attacker, slot, delay); |
|
|
@ -364,7 +363,7 @@ public enum CombatManager { |
|
|
|
setAutoAttackJob(attacker, slot, delay); |
|
|
|
setAutoAttackJob(attacker, slot, delay); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
if(attacker.getObjectType().equals(mbEnums.GameObjectType.Mob) && ((Mob)attacker).isPet()) |
|
|
|
if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob) && ((Mob) attacker).isPet()) |
|
|
|
calculatePetDamage(attacker); |
|
|
|
calculatePetDamage(attacker); |
|
|
|
|
|
|
|
|
|
|
|
//get the damage type
|
|
|
|
//get the damage type
|
|
|
@ -434,7 +433,7 @@ public enum CombatManager { |
|
|
|
if (resists.immuneTo(damageType)) { |
|
|
|
if (resists.immuneTo(damageType)) { |
|
|
|
//set auto attack job
|
|
|
|
//set auto attack job
|
|
|
|
//we need to send the animation even if the attacker misses
|
|
|
|
//we need to send the animation even if the attacker misses
|
|
|
|
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template,null,slot)); |
|
|
|
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template, null, slot)); |
|
|
|
DispatchManager.sendToAllInRange(target, cmm); |
|
|
|
DispatchManager.sendToAllInRange(target, cmm); |
|
|
|
setAutoAttackJob(attacker, slot, delay); |
|
|
|
setAutoAttackJob(attacker, slot, delay); |
|
|
|
return; |
|
|
|
return; |
|
|
@ -545,7 +544,7 @@ public enum CombatManager { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//Item has no equipment slots and should not try to return an animation, return default instead
|
|
|
|
//Item has no equipment slots and should not try to return an animation, return default instead
|
|
|
|
if(wb.item_eq_slots_or == null || wb.item_eq_slots_or.isEmpty()){ |
|
|
|
if (wb.item_eq_slots_or == null || wb.item_eq_slots_or.isEmpty()) { |
|
|
|
return 75; |
|
|
|
return 75; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -554,14 +553,14 @@ public enum CombatManager { |
|
|
|
int random; |
|
|
|
int random; |
|
|
|
|
|
|
|
|
|
|
|
//Item can only be equipped in one slot, return animation for that slot
|
|
|
|
//Item can only be equipped in one slot, return animation for that slot
|
|
|
|
if(wb.item_eq_slots_or.size() == 1){ |
|
|
|
if (wb.item_eq_slots_or.size() == 1) { |
|
|
|
if (wb.item_eq_slots_or.iterator().next().equals(mbEnums.EquipSlotType.RHELD)) { |
|
|
|
if (wb.item_eq_slots_or.iterator().next().equals(mbEnums.EquipSlotType.RHELD)) { |
|
|
|
anim = wb.weapon_attack_anim_right.get(0)[0]; |
|
|
|
anim = wb.weapon_attack_anim_right.get(0)[0]; |
|
|
|
if (dpj != null) { |
|
|
|
if (dpj != null) { |
|
|
|
random = ThreadLocalRandom.current().nextInt(wb.weapon_attack_anim_right.size()); |
|
|
|
random = ThreadLocalRandom.current().nextInt(wb.weapon_attack_anim_right.size()); |
|
|
|
anim = wb.weapon_attack_anim_right.get(random)[0]; |
|
|
|
anim = wb.weapon_attack_anim_right.get(random)[0]; |
|
|
|
} |
|
|
|
} |
|
|
|
}else { |
|
|
|
} else { |
|
|
|
anim = wb.weapon_attack_anim_left.get(0)[0]; |
|
|
|
anim = wb.weapon_attack_anim_left.get(0)[0]; |
|
|
|
if (dpj != null) { |
|
|
|
if (dpj != null) { |
|
|
|
random = ThreadLocalRandom.current().nextInt(wb.weapon_attack_anim_left.size()); |
|
|
|
random = ThreadLocalRandom.current().nextInt(wb.weapon_attack_anim_left.size()); |
|
|
@ -578,7 +577,7 @@ public enum CombatManager { |
|
|
|
random = ThreadLocalRandom.current().nextInt(wb.weapon_attack_anim_right.size()); |
|
|
|
random = ThreadLocalRandom.current().nextInt(wb.weapon_attack_anim_right.size()); |
|
|
|
anim = wb.weapon_attack_anim_right.get(random)[0]; |
|
|
|
anim = wb.weapon_attack_anim_right.get(random)[0]; |
|
|
|
} |
|
|
|
} |
|
|
|
}else { |
|
|
|
} else { |
|
|
|
anim = wb.weapon_attack_anim_left.get(0)[0]; |
|
|
|
anim = wb.weapon_attack_anim_left.get(0)[0]; |
|
|
|
if (dpj != null) { |
|
|
|
if (dpj != null) { |
|
|
|
random = ThreadLocalRandom.current().nextInt(wb.weapon_attack_anim_left.size()); |
|
|
|
random = ThreadLocalRandom.current().nextInt(wb.weapon_attack_anim_left.size()); |
|
|
@ -588,8 +587,8 @@ public enum CombatManager { |
|
|
|
return anim; |
|
|
|
return anim; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static int getPassiveAnimation(mbEnums.PassiveType passiveType){ |
|
|
|
public static int getPassiveAnimation(mbEnums.PassiveType passiveType) { |
|
|
|
switch(passiveType){ |
|
|
|
switch (passiveType) { |
|
|
|
case Block: |
|
|
|
case Block: |
|
|
|
return COMBAT_BLOCK_ANIMATION; |
|
|
|
return COMBAT_BLOCK_ANIMATION; |
|
|
|
case Parry: |
|
|
|
case Parry: |
|
|
@ -604,7 +603,7 @@ public enum CombatManager { |
|
|
|
public static void setAutoAttackJob(AbstractCharacter attacker, mbEnums.EquipSlotType slot, long delay) { |
|
|
|
public static void setAutoAttackJob(AbstractCharacter attacker, mbEnums.EquipSlotType slot, long delay) { |
|
|
|
//calculate next allowed attack and update the timestamp
|
|
|
|
//calculate next allowed attack and update the timestamp
|
|
|
|
|
|
|
|
|
|
|
|
if(attacker.getTimestamps().containsKey("Attack" + slot.name()) && attacker.getTimestamps().get("Attack" + slot.name()) > System.currentTimeMillis()) |
|
|
|
if (attacker.getTimestamps().containsKey("Attack" + slot.name()) && attacker.getTimestamps().get("Attack" + slot.name()) > System.currentTimeMillis()) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
attacker.getTimestamps().put("Attack" + slot.name(), System.currentTimeMillis() + delay); |
|
|
|
attacker.getTimestamps().put("Attack" + slot.name(), System.currentTimeMillis() + delay); |
|
|
@ -621,6 +620,7 @@ public enum CombatManager { |
|
|
|
Logger.error("Unable to find Timers for Character " + attacker.getObjectUUID()); |
|
|
|
Logger.error("Unable to find Timers for Character " + attacker.getObjectUUID()); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static int calculatePetDamage(AbstractCharacter agent) { |
|
|
|
public static int calculatePetDamage(AbstractCharacter agent) { |
|
|
|
//damage calc for pet
|
|
|
|
//damage calc for pet
|
|
|
|
float range; |
|
|
|
float range; |
|
|
@ -635,6 +635,7 @@ public enum CombatManager { |
|
|
|
damage = min + ((ThreadLocalRandom.current().nextFloat() * range) + (ThreadLocalRandom.current().nextFloat() * range)) / 2; |
|
|
|
damage = min + ((ThreadLocalRandom.current().nextFloat() * range) + (ThreadLocalRandom.current().nextFloat() * range)) / 2; |
|
|
|
return (int) (damage * dmgMultiplier); |
|
|
|
return (int) (damage * dmgMultiplier); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static double getMinDmg(double min, AbstractCharacter agent) { |
|
|
|
public static double getMinDmg(double min, AbstractCharacter agent) { |
|
|
|
int primary = agent.getStatStrCurrent(); |
|
|
|
int primary = agent.getStatStrCurrent(); |
|
|
|
int secondary = agent.getStatDexCurrent(); |
|
|
|
int secondary = agent.getStatDexCurrent(); |
|
|
@ -642,6 +643,7 @@ public enum CombatManager { |
|
|
|
int masteryLevel = 0; |
|
|
|
int masteryLevel = 0; |
|
|
|
return min * (pow(0.0048 * primary + .049 * (primary - 0.75), 0.5) + pow(0.0066 * secondary + 0.064 * (secondary - 0.75), 0.5) + +0.01 * (focusLevel + masteryLevel)); |
|
|
|
return min * (pow(0.0048 * primary + .049 * (primary - 0.75), 0.5) + pow(0.0066 * secondary + 0.064 * (secondary - 0.75), 0.5) + +0.01 * (focusLevel + masteryLevel)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static double getMaxDmg(double max, AbstractCharacter agent) { |
|
|
|
public static double getMaxDmg(double max, AbstractCharacter agent) { |
|
|
|
int primary = agent.getStatStrCurrent(); |
|
|
|
int primary = agent.getStatStrCurrent(); |
|
|
|
int secondary = agent.getStatDexCurrent(); |
|
|
|
int secondary = agent.getStatDexCurrent(); |
|
|
|