Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Core/Items): Implemented elemental weapon damage. Source: Trinit… #13050

Merged
merged 9 commits into from
Oct 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/server/game/Entities/Creature/Creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2156,7 +2156,7 @@ void Creature::LoadSpellTemplateImmunity()
}
}

bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo)
bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell)
{
if (!spellInfo)
return false;
Expand All @@ -2178,7 +2178,7 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo)
if (immunedToAllEffects)
return true;

return Unit::IsImmunedToSpell(spellInfo);
return Unit::IsImmunedToSpell(spellInfo, spell);
}

bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const
Expand Down
6 changes: 3 additions & 3 deletions src/server/game/Entities/Creature/Creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class Creature : public Unit, public GridObject<Creature>, public MovableMapObje
[[nodiscard]] bool IsValidTrainerForPlayer(Player* player, uint32* npcFlags = nullptr) const;
bool CanCreatureAttack(Unit const* victim, bool skipDistCheck = false) const;
void LoadSpellTemplateImmunity();
bool IsImmunedToSpell(SpellInfo const* spellInfo) override;
bool IsImmunedToSpell(SpellInfo const* spellInfo, Spell const* spell = nullptr) override;

[[nodiscard]] bool HasMechanicTemplateImmunity(uint32 mask) const;
// redefine Unit::IsImmunedToSpell
Expand Down Expand Up @@ -155,7 +155,7 @@ class Creature : public Unit, public GridObject<Creature>, public MovableMapObje
return (getLevel() / 2 + uint32(GetStat(STAT_STRENGTH) / 20));
}

[[nodiscard]] SpellSchoolMask GetMeleeDamageSchoolMask() const override { return m_meleeDamageSchoolMask; }
[[nodiscard]] SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType /*attackType*/ = BASE_ATTACK, uint8 /*damageIndex*/ = 0) const override { return m_meleeDamageSchoolMask; }
void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = SpellSchoolMask(1 << school); }

void _AddCreatureSpellCooldown(uint32 spell_id, uint16 categoryId, uint32 end_time);
Expand All @@ -178,7 +178,7 @@ class Creature : public Unit, public GridObject<Creature>, public MovableMapObje
void UpdateMaxHealth() override;
void UpdateMaxPower(Powers power) override;
void UpdateAttackPowerAndDamage(bool ranged = false) override;
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) override;
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex) override;

void SetCanDualWield(bool value) override;
[[nodiscard]] int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; }
Expand Down
97 changes: 54 additions & 43 deletions src/server/game/Entities/Player/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6740,21 +6740,11 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (proto->ArcaneRes)
HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply);

WeaponAttackType attType = BASE_ATTACK;

if (slot == EQUIPMENT_SLOT_RANGED && (
proto->InventoryType == INVTYPE_RANGED || proto->InventoryType == INVTYPE_THROWN ||
proto->InventoryType == INVTYPE_RANGEDRIGHT))
{
attType = RANGED_ATTACK;
}
else if (slot == EQUIPMENT_SLOT_OFFHAND)
uint8 attType = Player::GetAttackBySlot(slot);
if (attType != MAX_ATTACK)
{
attType = OFF_ATTACK;
}

if (CanUseAttackType(attType))
_ApplyWeaponDamage(slot, proto, ssv, apply);
}

// Druids get feral AP bonus from weapon dps (also use DPS from ScalingStatValue)
if (getClass() == CLASS_DRUID)
Expand Down Expand Up @@ -6797,45 +6787,56 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
ssv = ScalingStatValue ? sScalingStatValuesStore.LookupEntry(ssd_level) : nullptr;
}

WeaponAttackType attType = BASE_ATTACK;
float damage = 0.0f;

if (slot == EQUIPMENT_SLOT_RANGED && (
proto->InventoryType == INVTYPE_RANGED || proto->InventoryType == INVTYPE_THROWN ||
proto->InventoryType == INVTYPE_RANGEDRIGHT))
uint8 attType = Player::GetAttackBySlot(slot);
if (!IsInFeralForm() && apply && !CanUseAttackType(attType))
{
attType = RANGED_ATTACK;
return;
}
else if (slot == EQUIPMENT_SLOT_OFFHAND)

for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
{
attType = OFF_ATTACK;
}
float minDamage = proto->Damage[i].DamageMin;
float maxDamage = proto->Damage[i].DamageMax;

float minDamage = proto->Damage[0].DamageMin;
float maxDamage = proto->Damage[0].DamageMax;
// If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage
if (ssv)
{
int32 extraDPS = ssv->getDPSMod(ScalingStatValue);
if (extraDPS)
{
float average = extraDPS * proto->Delay / 1000.0f;
minDamage = 0.7f * average;
maxDamage = 1.3f * average;
}
}

// If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage
if (ssv)
{
int32 extraDPS = ssv->getDPSMod(ScalingStatValue);
if (extraDPS)
if (apply)
{
float average = extraDPS * proto->Delay / 1000.0f;
minDamage = 0.7f * average;
maxDamage = 1.3f * average;
if (minDamage > 0.f)
{
SetBaseWeaponDamage(WeaponAttackType(attType), MINDAMAGE, minDamage, i);
}

if (maxDamage > 0.f)
{
SetBaseWeaponDamage(WeaponAttackType(attType), MAXDAMAGE, maxDamage, i);
}
}
}

if (minDamage > 0)
if (!apply)
{
damage = apply ? minDamage : BASE_MINDAMAGE;
SetBaseWeaponDamage(attType, MINDAMAGE, damage);
}
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
{
SetBaseWeaponDamage(WeaponAttackType(attType), MINDAMAGE, 0.f, i);
SetBaseWeaponDamage(WeaponAttackType(attType), MAXDAMAGE, 0.f, i);
}

if (maxDamage > 0)
{
damage = apply ? maxDamage : BASE_MAXDAMAGE;
SetBaseWeaponDamage(attType, MAXDAMAGE, damage);
if (attType == BASE_ATTACK)
{
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, BASE_MINDAMAGE);
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, BASE_MAXDAMAGE);
}
}

if (proto->Delay && !IsInFeralForm())
Expand All @@ -6852,8 +6853,18 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
if (IsInFeralForm())
return;

if (CanModifyStats() && (damage || proto->Delay))
UpdateDamagePhysical(attType);
if (CanModifyStats() && (GetWeaponDamageRange(WeaponAttackType(attType), MAXDAMAGE) || proto->Delay))
UpdateDamagePhysical(WeaponAttackType(attType));
}

SpellSchoolMask Player::GetMeleeDamageSchoolMask(WeaponAttackType attackType /*= BASE_ATTACK*/, uint8 damageIndex /*= 0*/) const
{
if (Item const* weapon = GetWeaponForAttack(attackType, true))
{
return SpellSchoolMask(1 << weapon->GetTemplate()->Damage[damageIndex].DamageType);
}

return SPELL_SCHOOL_MASK_NORMAL;
}

void Player::_ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply)
Expand Down
4 changes: 3 additions & 1 deletion src/server/game/Entities/Player/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -1905,7 +1905,7 @@ class Player : public Unit, public GridObject<Player>
void UpdateRating(CombatRating cr);
void UpdateAllRatings();

void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) override;
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex) override;

void UpdateDefenseBonusesMod();
inline void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);}
Expand Down Expand Up @@ -2147,6 +2147,8 @@ class Player : public Unit, public GridObject<Player>

void ResetAllPowers();

SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType attackType = BASE_ATTACK, uint8 damageIndex = 0) const override;

void _ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply);
void _ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply);
void _ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply);
Expand Down
51 changes: 40 additions & 11 deletions src/server/game/Entities/Unit/StatSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,25 +59,31 @@ void Unit::UpdateAllResistances()

void Unit::UpdateDamagePhysical(WeaponAttackType attType)
{
float minDamage = 0.0f;
float maxDamage = 0.0f;
float totalMin = 0.f;
float totalMax = 0.f;

CalculateMinMaxDamage(attType, false, true, minDamage, maxDamage);
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
{
float tmpMin, tmpMax;
CalculateMinMaxDamage(attType, false, true, tmpMin, tmpMax, i);
totalMin += tmpMin;
totalMax += tmpMax;
}

switch (attType)
{
case BASE_ATTACK:
default:
SetStatFloatValue(UNIT_FIELD_MINDAMAGE, minDamage);
SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxDamage);
SetStatFloatValue(UNIT_FIELD_MINDAMAGE, totalMin);
SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, totalMax);
break;
case OFF_ATTACK:
SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, minDamage);
SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, maxDamage);
SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, totalMin);
SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, totalMax);
break;
case RANGED_ATTACK:
SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, minDamage);
SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, maxDamage);
SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, totalMin);
SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, totalMax);
break;
}
}
Expand Down Expand Up @@ -525,8 +531,23 @@ void Player::UpdateShieldBlockValue()
SetUInt32Value(PLAYER_SHIELD_BLOCK, GetShieldBlockValue());
}

void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage)
void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex)
{
// Only proto damage, not affected by any mods
if (damageIndex != 0)
{
minDamage = 0.0f;
maxDamage = 0.0f;

if (!IsInFeralForm() && CanUseAttackType(attType))
{
minDamage = GetWeaponDamageRange(attType, MINDAMAGE, damageIndex);
maxDamage = GetWeaponDamageRange(attType, MAXDAMAGE, damageIndex);
}

return;
}

UnitMods unitMod;

switch (attType)
Expand Down Expand Up @@ -1075,8 +1096,16 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
}
}

void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage)
void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex /*= 0*/)
{
// creatures only have one damage
if (damageIndex != 0)
{
minDamage = 0.f;
maxDamage = 0.f;
return;
}

UnitMods unitMod;
float variance = 1.0f;
switch (attType)
Expand Down