@ -23,6 +23,8 @@ import engine.powers.effectmodifiers.AbstractEffectModifier;
import engine.server.MBServerStatics ;
import engine.server.MBServerStatics ;
import org.pmw.tinylog.Logger ;
import org.pmw.tinylog.Logger ;
import java.awt.geom.Point2D ;
import java.awt.geom.Rectangle2D ;
import java.util.EnumSet ;
import java.util.EnumSet ;
import java.util.concurrent.ConcurrentHashMap ;
import java.util.concurrent.ConcurrentHashMap ;
import java.util.concurrent.ThreadLocalRandom ;
import java.util.concurrent.ThreadLocalRandom ;
@ -38,9 +40,13 @@ public enum CombatManager {
if ( attacker = = null | | target = = null | | ! attacker . isAlive ( ) | | ! target . isAlive ( ) )
if ( attacker = = null | | target = = null | | ! attacker . isAlive ( ) | | ! target . isAlive ( ) )
return ;
return ;
if ( attacker . getObjectType ( ) . equals ( mbEnums . GameObjectType . Mob ) )
if ( ( ( Mob ) attacker ) . nextAttackTime > System . currentTimeMillis ( ) )
return ;
switch ( target . getObjectType ( ) ) {
switch ( target . getObjectType ( ) ) {
case Building :
case Building :
if ( ( ( Building ) target ) . isVulnerable ( ) = = false )
if ( ! ( ( Building ) target ) . isVulnerable ( ) )
return ;
return ;
break ;
break ;
case PlayerCharacter :
case PlayerCharacter :
@ -59,33 +65,54 @@ public enum CombatManager {
if ( mainWeapon = = null & & offWeapon = = null ) {
if ( mainWeapon = = null & & offWeapon = = null ) {
//no weapons equipped, punch with both fists
//no weapons equipped, punch with both fists
processAttack ( attacker , target , mbEnums . EquipSlotType . RHELD ) ;
processAttack ( attacker , target , mbEnums . EquipSlotType . RHELD ) ;
if ( attacker . getObjectType ( ) . equals ( mbEnums . GameObjectType . PlayerCharacter ) )
processAttack ( attacker , target , mbEnums . EquipSlotType . LHELD ) ;
return ;
}
if ( mainWeapon ! = null & & offWeapon = = null ) {
//swing right hand only
processAttack ( attacker , target , mbEnums . EquipSlotType . RHELD ) ;
return ;
}
if ( mainWeapon = = null & & offWeapon ! = null & & ! offWeapon . template . item_skill_required . containsKey ( "Block" ) ) {
//swing left hand only
processAttack ( attacker , target , mbEnums . EquipSlotType . LHELD ) ;
processAttack ( attacker , target , mbEnums . EquipSlotType . LHELD ) ;
} else if ( mainWeapon = = null & & offWeapon ! = null & & offWeapon . template . item_skill_required . containsKey ( "Block" ) ) {
return ;
}
if ( mainWeapon = = null & & offWeapon ! = null & & offWeapon . template . item_skill_required . containsKey ( "Block" ) ) {
//no weapon equipped with a shield, punch with one hand
//no weapon equipped with a shield, punch with one hand
processAttack ( attacker , target , mbEnums . EquipSlotType . RHELD ) ;
processAttack ( attacker , target , mbEnums . EquipSlotType . RHELD ) ;
} else if ( mainWeapon ! = null & & offWeapon ! = null & & offWeapon . template . item_skill_required . containsKey ( "Block" ) ) {
return ;
}
if ( mainWeapon ! = null & & offWeapon ! = null & & offWeapon . template . item_skill_required . containsKey ( "Block" ) ) {
//one weapon equipped with a shield, swing with one hand
//one weapon equipped with a shield, swing with one hand
processAttack ( attacker , target , mbEnums . EquipSlotType . RHELD ) ;
processAttack ( attacker , target , mbEnums . EquipSlotType . RHELD ) ;
} else if ( mainWeapon ! = null & & offWeapon ! = null & & offWeapon . template . item_skill_required . containsKey ( "Block" ) = = false ) {
return ;
}
if ( mainWeapon ! = null & & offWeapon ! = null & & ! offWeapon . template . item_skill_required . containsKey ( "Block" ) ) {
//two weapons equipped, swing both hands
//two weapons equipped, swing both hands
processAttack ( attacker , target , mbEnums . EquipSlotType . RHELD ) ;
processAttack ( attacker , target , mbEnums . EquipSlotType . RHELD ) ;
processAttack ( attacker , target , mbEnums . EquipSlotType . LHELD ) ;
if ( attacker . getObjectType ( ) . equals ( mbEnums . GameObjectType . PlayerCharacter ) )
} else if ( mainWeapon = = null & & offWeapon ! = null & & offWeapon . template . item_skill_required . containsKey ( "Block" ) = = false ) {
processAttack ( attacker , target , mbEnums . EquipSlotType . LHELD ) ;
//swing left hand only
processAttack ( attacker , target , mbEnums . EquipSlotType . LHELD ) ;
} else if ( mainWeapon ! = null & & offWeapon = = null ) {
//swing left hand only
processAttack ( attacker , target , mbEnums . EquipSlotType . RHELD ) ;
}
}
}
}
public static void processAttack ( AbstractCharacter attacker , AbstractWorldObject target , mbEnums . EquipSlotType slot ) {
public static void processAttack ( AbstractCharacter attacker , AbstractWorldObject target , mbEnums . EquipSlotType slot ) {
// heck if character can even attack yet
if ( attacker . getObjectType ( ) . equals ( mbEnums . GameObjectType . PlayerCharacter ) ) {
if ( ! attacker . isCombat ( ) )
return ;
if ( attacker . getTimestamps ( ) . containsKey ( "Attack" + slot . name ( ) ) )
if ( attacker . getTimestamps ( ) . get ( "Attack" + slot . name ( ) ) ! = null & & attacker . getTimestamps ( ) . get ( "Attack" + slot . name ( ) ) < System . currentTimeMillis ( ) ) {
if ( System . currentTimeMillis ( ) < attacker . getTimestamps ( ) . get ( "Attack" + slot . name ( ) ) )
setAutoAttackJob ( attacker , slot , 1000 ) ;
return ;
return ;
}
}
// check if character is in range to attack target
// check if character is in range to attack target
@ -109,202 +136,284 @@ public enum CombatManager {
float distanceSquared = attacker . loc . distanceSquared ( target . loc ) ;
float distanceSquared = attacker . loc . distanceSquared ( target . loc ) ;
if ( distanceSquared > attackRange * attackRange )
boolean inRange = false ;
return ;
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 * attackRange )
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 ) * 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 ;
}
// take stamina away from attacker
//get delay for the auto attack job
long delay = 5000 ;
if ( weapon ! = null ) {
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
attacker . cancelOnAttackSwing ( ) ;
int wepSpeed = ( int ) ( weapon . template . item_weapon_wepspeed ) ;
//declare relevant variables
if ( weapon . getBonusPercent ( mbEnums . ModType . WeaponSpeed , mbEnums . SourceType . None ) ! = 0f ) //add weapon speed bonus
wepSpeed * = ( 1 + weapon . getBonus ( mbEnums . ModType . WeaponSpeed , mbEnums . SourceType . None ) ) ;
int min = attacker . minDamageHandOne ;
if ( attacker . getBonuses ( ) ! = null & & attacker . getBonuses ( ) . getFloatPercentAll ( mbEnums . ModType . AttackDelay , mbEnums . SourceType . None ) ! = 0f ) //add effects speed bonus
int max = attacker . maxDamageHandOne ;
wepSpeed * = ( 1 + attacker . getBonuses ( ) . getFloatPercentAll ( mbEnums . ModType . AttackDelay , mbEnums . SourceType . None ) ) ;
int atr = attacker . atrHandOne ;
//get the proper stats based on which slot is attacking
if ( wepSpeed < 10 )
wepSpeed = 10 ; //Old was 10, but it can be reached lower with legit buffs,effects.
if ( slot = = mbEnums . EquipSlotType . LHELD ) {
delay = wepSpeed * 100L ;
min = attacker . minDamageHandTwo ;
max = attacker . maxDamageHandTwo ;
atr = attacker . atrHandTwo ;
}
}
int def = 0 ;
if ( attacker . getObjectType ( ) . equals ( mbEnums . GameObjectType . Mob ) )
( ( Mob ) attacker ) . nextAttackTime = System . currentTimeMillis ( ) + delay ;
if ( AbstractCharacter . IsAbstractCharacter ( target ) )
if ( inRange ) {
def = ( ( AbstractCharacter ) target ) . defenseRating ;
//calculate hit chance based off ATR and DEF
//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 ) ;
}
}
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 ( target . getObjectType ( ) = = mbEnums . GameObjectType . Building )
//check if Out of Stamina
hitChance = 100 ;
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 ( 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 ) ;
int passiveAnim = getSwingAnimation ( null , null , slot . equals ( mbEnums . EquipSlotType . RHELD ) ) ;
//cancel things that are cancelled by an attack
if ( attacker . charItemManager . getEquipped ( ) . get ( slot ) ! = null ) {
passiveAnim = getSwingAnimation ( attacker . charItemManager . getEquipped ( ) . get ( slot ) . template , null , true ) ;
}
if ( ThreadLocalRandom . current ( ) . nextInt ( 100 ) > hitChance ) {
attacker . cancelOnAttackSwing ( ) ;
TargetedActionMsg msg = new TargetedActionMsg ( attacker , target , 0f , passiveAnim ) ;
if ( target . getObjectType ( ) = = mbEnums . GameObjectType . PlayerCharacter )
//declare relevant variables
DispatchMessage . dispatchMsgToInterestArea ( target , msg , mbEnums . DispatchChannel . PRIMARY , MBServerStatics . CHARACTER_LOAD_RANGE , true , false ) ;
else
DispatchMessage . sendToAllInRange ( attacker , msg ) ;
return ;
int min = attacker . minDamageHandOne ;
}
int max = attacker . maxDamageHandOne ;
int atr = attacker . atrHandOne ;
//calculate passive chances only if target is AbstractCharacter
//get the proper stats based on which slot is attacking
if ( EnumSet . of ( mbEnums . GameObjectType . PlayerCharacter , mbEnums . GameObjectType . NPC , mbEnums . GameObjectType . Mob ) . contains ( target . getObjectType ( ) ) ) {
if ( slot = = mbEnums . EquipSlotType . LHELD ) {
mbEnums . PassiveType passiveType = mbEnums . PassiveType . None ;
min = attacker . minDamageHandTwo ;
int hitRoll = ThreadLocalRandom . current ( ) . nextInt ( 100 ) ;
max = attacker . maxDamageHandTwo ;
atr = attacker . atrHandTwo ;
}
float dodgeChance = ( ( AbstractCharacter ) target ) . getPassiveChance ( "Dodge" , attacker . getLevel ( ) , true ) ;
int def = 0 ;
float blockChance = ( ( AbstractCharacter ) target ) . getPassiveChance ( "Block" , attacker . getLevel ( ) , true ) ;
float parryChance = ( ( AbstractCharacter ) target ) . getPassiveChance ( "Parry" , attacker . getLevel ( ) , true ) ;
// Passive chance clamped at 75
if ( AbstractCharacter . IsAbstractCharacter ( target ) )
def = ( ( AbstractCharacter ) target ) . defenseRating ;
dodgeChance = Math . max ( 0 , Math . min ( 75 , dodgeChance ) ) ;
//calculate hit chance based off ATR and DEF
blockChance = Math . max ( 0 , Math . min ( 75 , blockChance ) ) ;
parryChance = Math . max ( 0 , Math . min ( 75 , parryChance ) ) ;
if ( hitRoll < dodgeChance )
int hitChance ;
passiveType = mbEnums . PassiveType . Dodge ;
if ( def = = 0 )
else if ( hitRoll < blockChance )
def = 1 ;
passiveType = mbEnums . PassiveType . Block ;
float dif = atr * 1f / def ;
else if ( hitRoll < parryChance )
passiveType = mbEnums . PassiveType . Parry ;
if ( dif < = 0 . 8f )
hitChance = 4 ;
else
hitChance = ( ( int ) ( 450 * ( dif - 0 . 8f ) ) + 4 ) ;
if ( passiveType . equals ( mbEnums . PassiveType . None ) = = false ) {
if ( target . getObjectType ( ) = = mbEnums . GameObjectType . Building )
TargetedActionMsg msg = new TargetedActionMsg ( attacker , passiveAnim , target , passiveType . value ) ;
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 ) ;
}
if ( ThreadLocalRandom . current ( ) . nextInt ( 100 ) > hitChance ) {
TargetedActionMsg msg = new TargetedActionMsg ( attacker , target , 0f , passiveAnim ) ;
if ( target . getObjectType ( ) = = mbEnums . GameObjectType . PlayerCharacter )
if ( target . getObjectType ( ) = = mbEnums . GameObjectType . PlayerCharacter )
DispatchMessage . dispatchMsgToInterestArea ( target , msg , mbEnums . DispatchChannel . PRIMARY , MBServerStatics . CHARACTER_LOAD_RANGE , true , false ) ;
DispatchMessage . dispatchMsgToInterestArea ( target , msg , mbEnums . DispatchChannel . PRIMARY , MBServerStatics . CHARACTER_LOAD_RANGE , true , false ) ;
else
else
DispatchMessage . sendToAllInRange ( attacker , msg ) ;
DispatchMessage . sendToAllInRange ( attacker , msg ) ;
//set auto attack job
setAutoAttackJob ( attacker , slot , delay ) ;
return ;
return ;
}
}
}
//calculate the base damage
//calculate passive chances only if target is AbstractCharacter
int damage = ThreadLocalRandom . current ( ) . nextInt ( min , max + 1 ) ;
if ( damage = = 0 )
return ;
//get the damage type
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 ) ;
mbEnums . DamageType damageType ;
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 ) ;
if ( attacker . charItemManager . getEquipped ( ) . get ( slot ) = = null ) {
// Passive chance clamped at 75
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
dodgeChance = Math . max ( 0 , Math . min ( 75 , dodgeChance ) ) ;
blockChance = Math . max ( 0 , Math . min ( 75 , blockChance ) ) ;
parryChance = Math . max ( 0 , Math . min ( 75 , parryChance ) ) ;
Resists resists ;
if ( hitRoll < dodgeChance )
passiveType = mbEnums . PassiveType . Dodge ;
else if ( hitRoll < blockChance )
passiveType = mbEnums . PassiveType . Block ;
else if ( hitRoll < parryChance )
passiveType = mbEnums . PassiveType . Parry ;
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 ) ) {
if ( ! passiveType . equals ( mbEnums . PassiveType . None ) ) {
AbstractCharacter absTarget = ( AbstractCharacter ) target ;
TargetedActionMsg msg = new TargetedActionMsg ( attacker , passiveAnim , target , passiveType . value ) ;
//check damage shields
if ( target . getObjectType ( ) = = mbEnums . GameObjectType . PlayerCharacter )
DispatchMessage . dispatchMsgToInterestArea ( target , msg , mbEnums . DispatchChannel . PRIMARY , MBServerStatics . CHARACTER_LOAD_RANGE , true , false ) ;
else
DispatchMessage . sendToAllInRange ( attacker , msg ) ;
PlayerBonuses bonuses = absTarget . getBonuses ( ) ;
//set auto attack job
setAutoAttackJob ( attacker , slot , delay ) ;
return ;
}
}
if ( bonuses ! = null ) {
//calculate the base damage
int damage = ThreadLocalRandom . current ( ) . nextInt ( min , max + 1 ) ;
if ( damage = = 0 ) {
//set auto attack job
setAutoAttackJob ( attacker , slot , delay ) ;
return ;
}
//get the damage type
ConcurrentHashMap < AbstractEffectModifier , DamageShield > damageShields = bonuses . getDamageShields ( ) ;
mbEnums . DamageType damageType ;
float total = 0 ;
for ( DamageShield ds : damageShields . values ( ) ) {
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 amount to damage back
//get resists
float amount ;
Resists resists ;
if ( ds . usePercent ( ) )
if ( ! AbstractCharacter . IsAbstractCharacter ( target ) )
amount = damage * ds . getAmount ( ) / 100 ;
resists = ( ( Building ) target ) . getResists ( ) ; //this is a building
else
else
amount = ds . getAmount ( ) ;
resists = ( ( AbstractCharacter ) target ) . getResists ( ) ; //this is a character
//get resisted damage for damagetype
if ( AbstractCharacter . IsAbstractCharacter ( target ) ) {
AbstractCharacter absTarget = ( AbstractCharacter ) target ;
if ( resists ! = null )
//check damage shields
amount = resists . getResistedDamage ( absTarget , attacker , ds . getDamageType ( ) , amount , 0 ) ;
total + = amount ;
}
if ( total > 0 ) {
PlayerBonuses bonuses = absTarget . getBonuses ( ) ;
//apply Damage back
attacker . modifyHealth ( - total , absTarget , true ) ;
TargetedActionMsg cmm = new TargetedActionMsg ( attacker , attacker , total , 0 ) ;
DispatchMessage . sendToAllInRange ( target , cmm ) ;
}
}
if ( resist s ! = null ) {
if ( bonuses ! = null ) {
//check for damage type immunities
ConcurrentHashMap < AbstractEffectModifier , DamageShield > damageShields = bonuses . getDamageShields ( ) ;
float total = 0 ;
if ( resists . immuneTo ( damageType ) )
for ( DamageShield ds : damageShields . values ( ) ) {
return ;
//calculate resisted damage including fortitude
//get amount to damage back
damage = ( int ) resists . getResistedDamage ( attacker , ( AbstractCharacter ) target , damageType , damage , 0 ) ;
float amount ;
}
}
//remove damage from target health
if ( ds . usePercent ( ) )
amount = damage * ds . getAmount ( ) / 100 ;
else
amount = ds . getAmount ( ) ;
if ( damage > 0 ) {
//get resisted damage for damagetype
if ( AbstractCharacter . IsAbstractCharacter ( target ) )
if ( resists ! = null )
( ( AbstractCharacter ) target ) . modifyHealth ( - damage , attacker , true ) ;
amount = resists . getResistedDamage ( absTarget , attacker , ds . getDamageType ( ) , amount , 0 ) ;
else
total + = amount ;
( ( Building ) target ) . setCurrentHitPoints ( target . getCurrentHitpoints ( ) - damage ) ;
}
int attackAnim = getSwingAnimation ( null , null , slot . equals ( mbEnums . EquipSlotType . RHELD ) ) ;
if ( total > 0 ) {
if ( attacker . charItemManager . getEquipped ( ) . get ( slot ) ! = null ) {
//apply Damage back
attackAnim = getSwingAnimation ( attacker . charItemManager . getEquipped ( ) . get ( slot ) . template , null , slot . equals ( mbEnums . EquipSlotType . RHELD ) ) ;
attacker . modifyHealth ( - total , absTarget , true ) ;
TargetedActionMsg cmm = new TargetedActionMsg ( attacker , attacker , total , 0 ) ;
DispatchMessage . sendToAllInRange ( target , cmm ) ;
}
}
if ( resists ! = null ) {
//check for damage type immunities
if ( resists . immuneTo ( damageType ) ) {
//set auto attack job
setAutoAttackJob ( attacker , slot , delay ) ;
return ;
}
//calculate resisted damage including fortitude
damage = ( int ) resists . getResistedDamage ( attacker , ( AbstractCharacter ) target , damageType , damage , 0 ) ;
}
}
//remove damage from target health
if ( damage > 0 ) {
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 ) {
if ( attacker . getObjectType ( ) . equals ( mbEnums . GameObjectType . PlayerCharacter ) ) {
DeferredPowerJob weaponPower = ( ( PlayerCharacter ) attacker ) . getWeaponPower ( ) ;
attackAnim = getSwingAnimation ( attacker . charItemManager . getEquipped ( ) . get ( slot ) . template , weaponPower , slot . equals ( mbEnums . EquipSlotType . RHELD ) ) ;
} else {
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 ) ) {
@ -318,39 +427,9 @@ public enum CombatManager {
( ( PlayerCharacter ) attacker ) . setWeaponPower ( dpj ) ;
( ( PlayerCharacter ) attacker ) . setWeaponPower ( dpj ) ;
}
}
}
}
//calculate next allowed attack and update the timestamp
long delay = 20 * 100 ;
//set auto attack job
setAutoAttackJob ( attacker , slot , delay ) ;
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 < String , JobContainer > 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 ( ) ) ;
}
}
@ -411,116 +490,51 @@ public enum CombatManager {
public static int getSwingAnimation ( ItemTemplate wb , DeferredPowerJob dpj , boolean mainHand ) {
public static int getSwingAnimation ( ItemTemplate wb , DeferredPowerJob dpj , boolean mainHand ) {
int token = 0 ;
int token ;
if ( dpj ! = null )
if ( dpj ! = null ) {
token = ( dpj . getPower ( ) ! = null ) ? dpj . getPower ( ) . getToken ( ) : 0 ;
if ( token = = 563721004 ) //kick animation
token = ( dpj . getPower ( ) ! = null ) ? dpj . getPower ( ) . getToken ( ) : 0 ;
return 79 ;
if ( wb = = null )
return 75 ;
ItemTemplate template = wb ;
if ( mainHand ) {
if ( template . weapon_attack_anim_right . size ( ) > 0 ) {
int animation ;
int random = ThreadLocalRandom . current ( ) . nextInt ( template . weapon_attack_anim_right . size ( ) ) ;
try {
animation = template . weapon_attack_anim_right . get ( random ) [ 0 ] ;
return animation ;
} catch ( Exception e ) {
Logger . error ( e . getMessage ( ) ) ;
return template . weapon_attack_anim_right . get ( 0 ) [ 0 ] ;
}
} else if ( template . weapon_attack_anim_left . size ( ) > 0 ) {
int animation ;
int random = ThreadLocalRandom . current ( ) . nextInt ( template . weapon_attack_anim_left . size ( ) ) ;
try {
if ( token = = 563721004 ) //kick animation
animation = template . weapon_attack_anim_left . get ( random ) [ 0 ] ;
return 79 ;
return animation ;
} catch ( Exception e ) {
if ( wb ! = null ) {
Logger . error ( e . getMessage ( ) ) ;
if ( mainHand ) {
return template . weapon_attack_anim_right . get ( 0 ) [ 0 ] ;
int random = ThreadLocalRandom . current ( ) . nextInt ( wb . weapon_attack_anim_right . size ( ) ) ;
int anim = wb . weapon_attack_anim_right . get ( random ) [ 0 ] ;
return anim ;
} else {
int random = ThreadLocalRandom . current ( ) . nextInt ( wb . weapon_attack_anim_left . size ( ) ) ;
return wb . weapon_attack_anim_left . get ( random ) [ 0 ] ;
}
}
}
}
} else {
}
if ( template . weapon_attack_anim_left . size ( ) > 0 ) {
int animation ;
int random = ThreadLocalRandom . current ( ) . nextInt ( template . weapon_attack_anim_left . size ( ) ) ;
try {
animation = template . weapon_attack_anim_left . get ( random ) [ 0 ] ;
return animation ;
} catch ( Exception e ) {
Logger . error ( e . getMessage ( ) ) ;
return template . weapon_attack_anim_right . get ( 0 ) [ 0 ] ;
}
} else if ( template . weapon_attack_anim_left . size ( ) > 0 ) {
int animation ;
if ( wb = = null )
int random = ThreadLocalRandom . current ( ) . nextInt ( template . weapon_attack_anim_left . size ( ) ) ;
return 75 ;
try {
if ( mainHand )
animation = template . weapon_attack_anim_left . get ( random ) [ 0 ] ;
return wb . weapon_attack_anim_right . get ( 0 ) [ 0 ] ;
return animation ;
else
} catch ( Exception e ) {
return wb . weapon_attack_anim_left . get ( 0 ) [ 0 ] ;
Logger . error ( e . getMessage ( ) ) ;
return template . weapon_attack_anim_right . get ( 0 ) [ 0 ] ;
}
}
}
public static void setAutoAttackJob ( AbstractCharacter attacker , mbEnums . EquipSlotType slot , long delay ) {
}
//calculate next allowed attack and update the timestamp
attacker . getTimestamps ( ) . put ( "Attack" + slot . name ( ) , System . currentTimeMillis ( ) + delay ) ;
String required = template . item_skill_used ;
//handle auto attack job creation
String mastery = wb . item_skill_mastery_used ;
ConcurrentHashMap < String , JobContainer > timers = attacker . getTimers ( ) ;
if ( required . equals ( "Unarmed Combat" ) )
if ( timers ! = null ) {
return 75 ;
AttackJob aj = new AttackJob ( attacker , slot . ordinal ( ) , true ) ;
else if ( required . equals ( "Sword" ) ) {
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 ( ) ) ;
if ( ItemManager . isTwoHanded ( template ) )
return 105 ;
else
return 98 ;
} else if ( required . equals ( "Staff" ) | | required . equals ( "Pole Arm" ) ) {
return 85 ;
} else if ( required . equals ( "Spear" ) ) {
return 92 ;
} else if ( required . equals ( "Hammer" ) | | required . equals ( "Axe" ) ) {
if ( ItemManager . isTwoHanded ( template ) ) {
return 105 ;
} else if ( mastery . equals ( "Throwing" ) ) {
return 115 ;
} else {
return 100 ;
}
} else if ( required . equals ( "Dagger" ) ) {
if ( mastery . equals ( "Throwing" ) ) {
return 117 ;
} else {
return 81 ;
}
} else if ( required . equals ( "Crossbow" ) ) {
return 110 ;
} else if ( required . equals ( "Bow" ) ) {
return 109 ;
} else if ( ItemManager . isTwoHanded ( template ) ) {
return 105 ;
} else {
return 100 ;
}
}
}
}
}