mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-17 16:10:49 +01:00
[svn] Provide creature dual wield support.
Update glancing damage formula. Do not daze creatures when other creatures attack from the back (need to find a better way). Fix the damage calculation of +damage aura. --HG-- branch : trunk
This commit is contained in:
@@ -1234,11 +1234,13 @@ void Creature::SelectLevel(const CreatureInfo *cinfo)
|
||||
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg * damagemod);
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg * damagemod);
|
||||
|
||||
SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,cinfo->minrangedmg * damagemod);
|
||||
SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,cinfo->maxrangedmg * damagemod);
|
||||
SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg * damagemod);
|
||||
SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg * damagemod);
|
||||
SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, cinfo->minrangedmg * damagemod);
|
||||
SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, cinfo->maxrangedmg * damagemod);
|
||||
|
||||
SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->attackpower * damagemod);
|
||||
SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, cinfo->rangedattackpower * damagemod);
|
||||
}
|
||||
|
||||
float Creature::_GetHealthMod(int32 Rank)
|
||||
|
||||
@@ -993,17 +993,6 @@ void Player::Update( uint32 p_time )
|
||||
|
||||
Unit::Update( p_time );
|
||||
|
||||
// update player only attacks
|
||||
if(uint32 ranged_att = getAttackTimer(RANGED_ATTACK))
|
||||
{
|
||||
setAttackTimer(RANGED_ATTACK, (p_time >= ranged_att ? 0 : ranged_att - p_time) );
|
||||
}
|
||||
|
||||
if(uint32 off_att = getAttackTimer(OFF_ATTACK))
|
||||
{
|
||||
setAttackTimer(OFF_ATTACK, (p_time >= off_att ? 0 : off_att - p_time) );
|
||||
}
|
||||
|
||||
time_t now = time (NULL);
|
||||
|
||||
UpdatePvPFlag(now);
|
||||
|
||||
@@ -1750,8 +1750,6 @@ class TRINITY_DLL_SPEC Player : public Unit
|
||||
void SetCanParry(bool value);
|
||||
bool CanBlock() const { return m_canBlock; }
|
||||
void SetCanBlock(bool value);
|
||||
bool CanDualWield() const { return m_canDualWield; }
|
||||
void SetCanDualWield(bool value) { m_canDualWield = value; }
|
||||
|
||||
void SetRegularAttackTime();
|
||||
void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; }
|
||||
@@ -2240,7 +2238,6 @@ class TRINITY_DLL_SPEC Player : public Unit
|
||||
uint32 m_ArmorProficiency;
|
||||
bool m_canParry;
|
||||
bool m_canBlock;
|
||||
bool m_canDualWield;
|
||||
uint8 m_swingErrorMsg;
|
||||
float m_ammoDPS;
|
||||
////////////////////Rest System/////////////////////
|
||||
|
||||
@@ -3440,8 +3440,9 @@ void Spell::EffectDispel(uint32 i)
|
||||
|
||||
void Spell::EffectDualWield(uint32 /*i*/)
|
||||
{
|
||||
if (unitTarget->GetTypeId() == TYPEID_PLAYER)
|
||||
((Player*)unitTarget)->SetCanDualWield(true);
|
||||
unitTarget->SetCanDualWield(true);
|
||||
if(unitTarget->GetTypeId() == TYPEID_UNIT)
|
||||
((Creature*)unitTarget)->UpdateDamagePhysical(OFF_ATTACK);
|
||||
}
|
||||
|
||||
void Spell::EffectPull(uint32 /*i*/)
|
||||
|
||||
@@ -666,6 +666,7 @@ bool Creature::UpdateAllStats()
|
||||
{
|
||||
UpdateMaxHealth();
|
||||
UpdateAttackPowerAndDamage();
|
||||
UpdateAttackPowerAndDamage(true);
|
||||
|
||||
for(int i = POWER_MANA; i < MAX_POWERS; ++i)
|
||||
UpdateMaxPower(Powers(i));
|
||||
@@ -709,35 +710,62 @@ void Creature::UpdateMaxPower(Powers power)
|
||||
|
||||
void Creature::UpdateAttackPowerAndDamage(bool ranged)
|
||||
{
|
||||
if(ranged)
|
||||
return;
|
||||
|
||||
//automatically update weapon damage after attack power modification
|
||||
UpdateDamagePhysical(BASE_ATTACK);
|
||||
if(ranged)
|
||||
UpdateDamagePhysical(RANGED_ATTACK);
|
||||
else
|
||||
{
|
||||
UpdateDamagePhysical(BASE_ATTACK);
|
||||
UpdateDamagePhysical(OFF_ATTACK);
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::UpdateDamagePhysical(WeaponAttackType attType)
|
||||
{
|
||||
if(attType > BASE_ATTACK)
|
||||
return;
|
||||
UnitMods unitMod;
|
||||
switch(attType)
|
||||
{
|
||||
case BASE_ATTACK:
|
||||
default:
|
||||
unitMod = UNIT_MOD_DAMAGE_MAINHAND;
|
||||
break;
|
||||
case OFF_ATTACK:
|
||||
unitMod = UNIT_MOD_DAMAGE_OFFHAND;
|
||||
break;
|
||||
case RANGED_ATTACK:
|
||||
unitMod = UNIT_MOD_DAMAGE_RANGED;
|
||||
break;
|
||||
}
|
||||
|
||||
UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND;
|
||||
|
||||
float att_speed = float(GetAttackTime(BASE_ATTACK))/1000.0f;
|
||||
float att_speed = float(GetAttackTime(attType))/1000.0f;
|
||||
|
||||
float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed;
|
||||
float base_pct = GetModifierValue(unitMod, BASE_PCT);
|
||||
float total_value = GetModifierValue(unitMod, TOTAL_VALUE);
|
||||
float total_pct = GetModifierValue(unitMod, TOTAL_PCT);
|
||||
|
||||
float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE);
|
||||
float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE);
|
||||
float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE);
|
||||
float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE);
|
||||
|
||||
float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct ;
|
||||
float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct ;
|
||||
|
||||
SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage);
|
||||
SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage);
|
||||
switch(attType)
|
||||
{
|
||||
case BASE_ATTACK:
|
||||
default:
|
||||
SetStatFloatValue(UNIT_FIELD_MINDAMAGE,mindamage);
|
||||
SetStatFloatValue(UNIT_FIELD_MAXDAMAGE,maxdamage);
|
||||
break;
|
||||
case OFF_ATTACK:
|
||||
SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE,mindamage);
|
||||
SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE,maxdamage);
|
||||
break;
|
||||
case RANGED_ATTACK:
|
||||
SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,mindamage);
|
||||
SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,maxdamage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*#######################################
|
||||
|
||||
@@ -158,6 +158,7 @@ Unit::Unit()
|
||||
m_modAttackSpeedPct[RANGED_ATTACK] = 1.0f;
|
||||
|
||||
m_extraAttacks = 0;
|
||||
m_canDualWield = false;
|
||||
|
||||
m_state = 0;
|
||||
m_form = FORM_NONE;
|
||||
@@ -279,9 +280,11 @@ void Unit::Update( uint32 p_time )
|
||||
}
|
||||
|
||||
if(uint32 base_att = getAttackTimer(BASE_ATTACK))
|
||||
{
|
||||
setAttackTimer(BASE_ATTACK, (p_time >= base_att ? 0 : base_att - p_time) );
|
||||
}
|
||||
if(uint32 ranged_att = getAttackTimer(RANGED_ATTACK))
|
||||
setAttackTimer(RANGED_ATTACK, (p_time >= ranged_att ? 0 : ranged_att - p_time) );
|
||||
if(uint32 off_att = getAttackTimer(OFF_ATTACK))
|
||||
setAttackTimer(OFF_ATTACK, (p_time >= off_att ? 0 : off_att - p_time) );
|
||||
|
||||
// update abilities available only for fraction of time
|
||||
UpdateReactives( p_time );
|
||||
@@ -297,7 +300,7 @@ bool Unit::haveOffhandWeapon() const
|
||||
if(GetTypeId() == TYPEID_PLAYER)
|
||||
return ((Player*)this)->GetWeaponForAttack(OFF_ATTACK,true);
|
||||
else
|
||||
return false;
|
||||
return m_canDualWield;
|
||||
}
|
||||
|
||||
void Unit::SendMonsterMoveWithSpeedToCurrentDestination(Player* player)
|
||||
@@ -1769,7 +1772,8 @@ void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDama
|
||||
|
||||
/// If this is a creature and it attacks from behind it has a probability to daze it's victim
|
||||
if( (outcome==MELEE_HIT_CRIT || outcome==MELEE_HIT_CRUSHING || outcome==MELEE_HIT_NORMAL || outcome==MELEE_HIT_GLANCING) &&
|
||||
GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->GetCharmerOrOwnerGUID() && !pVictim->HasInArc(M_PI, this) )
|
||||
GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->GetCharmerOrOwnerGUID() && !pVictim->HasInArc(M_PI, this)
|
||||
&& pVictim->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
// -probability is between 0% and 40%
|
||||
// 20% base chance
|
||||
@@ -2056,54 +2060,10 @@ void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDama
|
||||
}
|
||||
case MELEE_HIT_GLANCING:
|
||||
{
|
||||
float reducePercent = 1.0f; //damage factor
|
||||
|
||||
// calculate base values and mods
|
||||
float baseLowEnd = 1.3;
|
||||
float baseHighEnd = 1.2;
|
||||
switch(getClass()) // lowering base values for casters
|
||||
{
|
||||
case CLASS_SHAMAN:
|
||||
case CLASS_PRIEST:
|
||||
case CLASS_MAGE:
|
||||
case CLASS_WARLOCK:
|
||||
case CLASS_DRUID:
|
||||
baseLowEnd -= 0.7;
|
||||
baseHighEnd -= 0.3;
|
||||
break;
|
||||
}
|
||||
|
||||
float maxLowEnd = 0.6;
|
||||
switch(getClass()) // upper for melee classes
|
||||
{
|
||||
case CLASS_WARRIOR:
|
||||
case CLASS_ROGUE:
|
||||
maxLowEnd = 0.91; //If the attacker is a melee class then instead the lower value of 0.91
|
||||
}
|
||||
|
||||
// calculate values
|
||||
int32 diff = int32(pVictim->GetDefenseSkillValue(this)) - int32(GetWeaponSkillValue(attType,pVictim));
|
||||
float lowEnd = baseLowEnd - ( 0.05f * diff );
|
||||
float highEnd = baseHighEnd - ( 0.03f * diff );
|
||||
|
||||
// apply max/min bounds
|
||||
if ( lowEnd < 0.01f ) //the low end must not go bellow 0.01f
|
||||
lowEnd = 0.01f;
|
||||
else if ( lowEnd > maxLowEnd ) //the smaller value of this and 0.6 is kept as the low end
|
||||
lowEnd = maxLowEnd;
|
||||
|
||||
if ( highEnd < 0.2f ) //high end limits
|
||||
highEnd = 0.2f;
|
||||
if ( highEnd > 0.99f )
|
||||
highEnd = 0.99f;
|
||||
|
||||
if(lowEnd > highEnd) // prevent negative range size
|
||||
lowEnd = highEnd;
|
||||
|
||||
reducePercent = lowEnd + rand_norm() * ( highEnd - lowEnd );
|
||||
|
||||
*damage = uint32(reducePercent * *damage);
|
||||
cleanDamage->damage += *damage;
|
||||
int32 leveldif = int32(pVictim->getLevel()) - int32(getLevel());
|
||||
if (leveldif > 3) leveldif = 3;
|
||||
*damage *= (1 - leveldif * 0.1f);
|
||||
cleanDamage->damage = *damage;
|
||||
*hitInfo |= HITINFO_GLANCING;
|
||||
break;
|
||||
}
|
||||
@@ -7575,7 +7535,9 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
|
||||
SpellModSpellDamage /= 100.0f;
|
||||
|
||||
float DoneActualBenefit = DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * SpellModSpellDamage * LvlPenalty;
|
||||
float TakenActualBenefit = TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty;
|
||||
float TakenActualBenefit = TakenAdvertisedBenefit;
|
||||
if(spellProto->SpellFamilyName)
|
||||
TakenActualBenefit *= (CastingTime / 3500.0f) * DotFactor * LvlPenalty;
|
||||
|
||||
float tmpDamage = (float(pdamage)+DoneActualBenefit)*DoneTotalMod;
|
||||
|
||||
|
||||
@@ -717,9 +717,12 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
|
||||
uint32 getAttackTimer(WeaponAttackType type) const { return m_attackTimer[type]; }
|
||||
bool isAttackReady(WeaponAttackType type = BASE_ATTACK) const { return m_attackTimer[type] == 0; }
|
||||
bool haveOffhandWeapon() const;
|
||||
bool CanDualWield() const { return m_canDualWield; }
|
||||
void SetCanDualWield(bool value) { m_canDualWield = value; }
|
||||
bool canReachWithAttack(Unit *pVictim) const;
|
||||
bool IsWithinCombatDist(Unit *obj, float dist2compare) const;
|
||||
uint32 m_extraAttacks;
|
||||
bool m_canDualWield;
|
||||
|
||||
void _addAttacker(Unit *pAttacker) // must be called only from Unit::Attack(Unit*)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user