Index: game/SpellEffects.cpp =================================================================== --- game/SpellEffects.cpp (revision 5609) +++ game/SpellEffects.cpp (working copy) @@ -3451,7 +3451,12 @@ //if miss/parry, no eff=0 automatically by func DoAttackDamage //if crit eff = (bonus + weapon) * 2 //In a word, bonus + weapon will be calculated together in cases of miss, armor reduce, crit, etc. - bonus += m_caster->CalculateDamage (m_attackType); + bool normalized = false; + for (j = 0; j <3;j++) + if (m_spellInfo->Effect[j] == SPELL_EFFECT_NORMALIZED_WEAPON_DMG) + normalized = true; + + bonus += m_caster->CalculateDamage (attType, normalized); switch(m_spellInfo->SpellFamilyName) { @@ -3462,7 +3467,7 @@ { Item* item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); if (item && item->GetProto()->Class == ITEM_CLASS_WEAPON && !item->IsBroken() && ((Player*)m_caster)->IsUseEquipedWeapon(false)) - bonus += m_caster->CalculateDamage (OFF_ATTACK); + bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized); } break; } Index: game/Unit.cpp =================================================================== --- game/Unit.cpp (revision 5609) +++ game/Unit.cpp (working copy) @@ -2456,7 +2456,7 @@ return; } - uint32 damage = CalculateDamage (attType); + uint32 damage = CalculateDamage (attType, false); DoAttackDamage (pVictim, &damage, &cleanDamage, &blocked_dmg, meleeSchool, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, attType); @@ -2741,13 +2741,107 @@ return MELEE_HIT_NORMAL; } -uint32 Unit::CalculateDamage (WeaponAttackType attType) +float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized) { - float min_damage, max_damage; + uint8 slot = EQUIPMENT_SLOT_MAINHAND; + if (!normalized || GetTypeId() != TYPEID_PLAYER) + return (float(GetAttackTime(attType))/1000.0f); + switch (attType) { + case OFF_ATTACK: + slot = EQUIPMENT_SLOT_OFFHAND; + break; case RANGED_ATTACK: + slot = EQUIPMENT_SLOT_RANGED; + break; + } + + Item *Weapon = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot); + + if (!Weapon) + return 2.5; + + switch (Weapon->GetProto()->SubClass) + { + case ITEM_SUBCLASS_WEAPON_DAGGER: + return 1.7; + case ITEM_SUBCLASS_WEAPON_BOW: + case ITEM_SUBCLASS_WEAPON_GUN: + case ITEM_SUBCLASS_WEAPON_THROWN: + case ITEM_SUBCLASS_WEAPON_CROSSBOW: + return 2.8; + case ITEM_SUBCLASS_WEAPON_SWORD2: + case ITEM_SUBCLASS_WEAPON_POLEARM: + case ITEM_SUBCLASS_WEAPON_AXE2: + case ITEM_SUBCLASS_WEAPON_MACE2: + case ITEM_SUBCLASS_WEAPON_STAFF: + case ITEM_SUBCLASS_WEAPON_SPEAR: + return 3.3; + } + + return 2.4; + +} + +uint32 Unit::CalculateDamage (WeaponAttackType attType, bool normalized) +{ + float min_damage, max_damage; + + if (GetTypeId()==TYPEID_PLAYER) + { + UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND; + UnitMods attPower = UNIT_MOD_ATTACK_POWER; + + switch(attType) + { + case BASE_ATTACK: break; + case OFF_ATTACK: + unitMod = UNIT_MOD_DAMAGE_OFFHAND; + break; + case RANGED_ATTACK: + unitMod = UNIT_MOD_DAMAGE_RANGED; + attPower = UNIT_MOD_ATTACK_POWER_RANGED; + break; + } + + float att_speed = GetAPMultiplier(attType,normalized); + + 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(attType, MINDAMAGE); + float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE); + + if (((Player *)this)->IsInFeralForm()) //check if player is druid and in cat or bear forms + { + uint32 lvl = getLevel(); + if ( lvl > 60 ) lvl = 60; + + weapon_mindamage = lvl*0.85*att_speed; + weapon_maxdamage = lvl*1.25*att_speed; + } + else if(!((Player *)this)->IsUseEquipedWeapon(attType==BASE_ATTACK)) //check if player not in form but still can't use weapon (broken/etc) + { + weapon_mindamage = BASE_MINDAMAGE; + weapon_maxdamage = BASE_MAXDAMAGE; + } + else if(attType == RANGED_ATTACK) //add ammo DPS to ranged damage + { + weapon_mindamage += ((Player *)this)->GetAmmoDPS() * att_speed; + weapon_maxdamage += ((Player *)this)->GetAmmoDPS() * att_speed; + } + + min_damage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct ; + max_damage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct ; + + } + else switch (attType) + { + case RANGED_ATTACK: min_damage = GetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE); max_damage = GetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE); break; @@ -7675,8 +7769,13 @@ APbonus += (*i)->GetModifier()->m_amount; } + bool normalized = false; + for (uint8 i = 0; i<3;i++) + if (spellProto->Effect[i] == SPELL_EFFECT_NORMALIZED_WEAPON_DMG) + normalized = true; + if (APbonus!=0) // Can be negative - DoneFlatBenefit += int32(APbonus/14.0f * GetAttackTime(attType)/1000); + DoneFlatBenefit += int32(APbonus/14.0f * GetAPMultiplier(attType,normalized)/1000); // ..taken AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN); Index: game/Unit.h =================================================================== --- game/Unit.h (revision 5609) +++ game/Unit.h (working copy) @@ -1015,7 +1015,8 @@ void RemoveGameObject(uint32 spellid, bool del); DynamicObject *GetDynObject(uint32 spellId, uint32 effIndex); DynamicObject *GetDynObject(uint32 spellId); - uint32 CalculateDamage(WeaponAttackType attType); + float GetAPMultiplier(WeaponAttackType attType, bool normalized); + uint32 CalculateDamage(WeaponAttackType attType, bool normalized); void ModifyAuraState(AuraState flag, bool apply); bool HasAuraState(AuraState flag) const { return HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); } void UnsummonAllTotems();