aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/characters_database.sql7
-rw-r--r--sql/updates/characters/3.3.5/2018_01_13_00_characters.sql7
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp10
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp6
-rw-r--r--src/server/game/Entities/Player/Player.cpp18
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp955
-rw-r--r--src/server/game/Entities/Unit/Unit.h43
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp360
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h20
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp120
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h26
-rw-r--r--src/server/game/Spells/Spell.cpp23
-rw-r--r--src/server/game/Spells/SpellEffects.cpp50
-rw-r--r--src/server/game/Spells/SpellMgr.cpp23
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp18
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp2
-rw-r--r--src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp2
-rw-r--r--src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp4
-rw-r--r--src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp2
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp2
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp2
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp2
-rw-r--r--src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp2
-rw-r--r--src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp2
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp6
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp4
-rw-r--r--src/server/scripts/Northrend/zone_borean_tundra.cpp2
-rw-r--r--src/server/scripts/Northrend/zone_grizzly_hills.cpp2
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp2
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp2
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp6
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp2
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp2
-rw-r--r--src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp2
-rw-r--r--src/server/scripts/Outland/zone_shadowmoon_valley.cpp2
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp30
-rw-r--r--src/server/scripts/Spells/spell_druid.cpp2
-rw-r--r--src/server/scripts/Spells/spell_hunter.cpp5
-rw-r--r--src/server/scripts/Spells/spell_priest.cpp7
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp4
-rw-r--r--src/server/scripts/Spells/spell_warlock.cpp2
-rw-r--r--src/server/scripts/Spells/spell_warrior.cpp2
65 files changed, 951 insertions, 885 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 75fb30efcaa..734c6673400 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -543,6 +543,8 @@ CREATE TABLE `character_aura` (
`maxDuration` int(11) NOT NULL DEFAULT '0',
`remainTime` int(11) NOT NULL DEFAULT '0',
`remainCharges` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `critChance` float NOT NULL DEFAULT '0',
+ `applyResilience` tinyint(3) NOT NULL DEFAULT '0',
PRIMARY KEY (`guid`,`casterGuid`,`spell`,`effectMask`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -2317,6 +2319,8 @@ CREATE TABLE `pet_aura` (
`maxDuration` int(11) NOT NULL DEFAULT '0',
`remainTime` int(11) NOT NULL DEFAULT '0',
`remainCharges` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `critChance` float NOT NULL DEFAULT '0',
+ `applyResilience` tinyint(3) NOT NULL DEFAULT '0',
PRIMARY KEY (`guid`,`casterGuid`,`spell`,`effectMask`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Pet System';
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -2616,7 +2620,8 @@ INSERT INTO `updates` VALUES
('2017_04_12_01_characters.sql','5A8A1215E3A2356722F52CD7A64BBE03D21FBEA3','ARCHIVED','2017-04-12 00:00:00',0),
('2017_04_19_00_characters.sql','CE06FA9005C8A8EE4BDD925520278A5D83E87485','RELEASED','2017-04-19 00:07:40',25),
('2017_10_29_00_characters.sql','6209D716E22C391F1FB464221D9F25AF','RELEASED','2017-04-19 00:07:40',25),
-('2017_11_27_00_characters.sql','6FF1F84B8985ADFC7FF97F0BF8E53403CF13C320','RELEASED','2017-11-27 22:08:42',0);
+('2017_11_27_00_characters.sql','6FF1F84B8985ADFC7FF97F0BF8E53403CF13C320','RELEASED','2017-11-27 22:08:42',0),
+('2018_01_13_00_characters.sql','E3C0DA9995BA71ED5A267294470CD03DC51862DD','RELEASED','2018-01-13 00:00:00',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/updates/characters/3.3.5/2018_01_13_00_characters.sql b/sql/updates/characters/3.3.5/2018_01_13_00_characters.sql
new file mode 100644
index 00000000000..10000251269
--- /dev/null
+++ b/sql/updates/characters/3.3.5/2018_01_13_00_characters.sql
@@ -0,0 +1,7 @@
+ALTER TABLE `character_aura`
+ADD COLUMN `critChance` FLOAT NOT NULL DEFAULT '0' AFTER `remainCharges`,
+ADD COLUMN `applyResilience` TINYINT(3) NOT NULL DEFAULT '0' AFTER `critChance`;
+
+ALTER TABLE `pet_aura`
+ADD COLUMN `critChance` FLOAT NOT NULL DEFAULT '0' AFTER `remainCharges`,
+ADD COLUMN `applyResilience` TINYINT(3) NOT NULL DEFAULT '0' AFTER `critChance`;
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp
index a31fa944c47..50bc9baa428 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp
@@ -71,7 +71,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_GROUP_MEMBER, "SELECT guid FROM group_member WHERE memberGuid = ?", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_CHARACTER_INSTANCE, "SELECT id, permanent, map, difficulty, extendState, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_AURAS, "SELECT casterGuid, spell, effectMask, recalculateMask, stackCount, amount0, amount1, amount2, "
- "base_amount0, base_amount1, base_amount2, maxDuration, remainTime, remainCharges FROM character_aura WHERE guid = ?", CONNECTION_ASYNC);
+ "base_amount0, base_amount1, base_amount2, maxDuration, remainTime, remainCharges, critChance, applyResilience FROM character_aura WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_SPELL, "SELECT spell, active, disabled FROM character_spell WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS, "SELECT quest, status, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, "
"itemcount1, itemcount2, itemcount3, itemcount4, playercount FROM character_queststatus WHERE guid = ? AND status <> 0", CONNECTION_ASYNC);
@@ -243,8 +243,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_EQUIP_SET, "DELETE FROM character_equipmentsets WHERE setguid=?", CONNECTION_ASYNC);
// Auras
- PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, casterGuid, spell, effectMask, recalculateMask, stackCount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxDuration, remainTime, remainCharges) "
- "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, casterGuid, spell, effectMask, recalculateMask, stackCount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxDuration, remainTime, remainCharges, critChance, applyResilience) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
// Account data
PrepareStatement(CHAR_SEL_ACCOUNT_DATA, "SELECT type, time, data FROM account_data WHERE accountId = ?", CONNECTION_ASYNC);
@@ -573,7 +573,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME_BY_OWNER, "DELETE FROM character_pet_declinedname WHERE owner = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME, "DELETE FROM character_pet_declinedname WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_PET_DECLINEDNAME, "INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_PET_AURA, "SELECT casterGuid, spell, effectMask, recalculateMask, stackCount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxDuration, remainTime, remainCharges FROM pet_aura WHERE guid = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_PET_AURA, "SELECT casterGuid, spell, effectMask, recalculateMask, stackCount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxDuration, remainTime, remainCharges, critChance, applyResilience FROM pet_aura WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_PET_SPELL, "SELECT spell, active FROM pet_spell WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_PET_SPELL_COOLDOWN, "SELECT spell, time, categoryId, categoryEnd FROM pet_spell_cooldown WHERE guid = ? AND time > UNIX_TIMESTAMP()", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_PET_DECLINED_NAME, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_pet_declinedname WHERE owner = ? AND id = ?", CONNECTION_SYNCH);
@@ -584,7 +584,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_PET_SPELL_BY_SPELL, "DELETE FROM pet_spell WHERE guid = ? and spell = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_PET_SPELL, "INSERT INTO pet_spell (guid, spell, active) VALUES (?, ?, ?)", CONNECTION_BOTH);
PrepareStatement(CHAR_INS_PET_AURA, "INSERT INTO pet_aura (guid, casterGuid, spell, effectMask, recalculateMask, stackCount, amount0, amount1, amount2, "
- "base_amount0, base_amount1, base_amount2, maxDuration, remainTime, remainCharges) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_BOTH);
+ "base_amount0, base_amount1, base_amount2, maxDuration, remainTime, remainCharges, critChance, applyResilience) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND id = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT_2, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND entry = ? AND (slot = ? OR slot > ?)", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_PET_BY_SLOT, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND (slot = ? OR slot > ?) ", CONNECTION_SYNCH);
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index abd82bf7f4a..29c275a0922 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -1177,6 +1177,8 @@ void Pet::_LoadAuras(uint32 timediff)
int32 maxduration = fields[11].GetInt32();
int32 remaintime = fields[12].GetInt32();
uint8 remaincharges = fields[13].GetUInt8();
+ float critChance = fields[14].GetFloat();
+ bool applyResilience = fields[15].GetBool();
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid);
if (!spellInfo)
@@ -1210,7 +1212,7 @@ void Pet::_LoadAuras(uint32 timediff)
aura->Remove();
continue;
}
- aura->SetLoadedState(maxduration, remaintime, remaincharges, stackcount, recalculatemask, &damage[0]);
+ aura->SetLoadedState(maxduration, remaintime, remaincharges, stackcount, recalculatemask, critChance, applyResilience, &damage[0]);
aura->ApplyForTargets();
TC_LOG_DEBUG("entities.pet", "Added aura spellid %u, effectmask %u", spellInfo->Id, effmask);
}
@@ -1275,6 +1277,8 @@ void Pet::_SaveAuras(SQLTransaction& trans)
stmt->setInt32(index++, itr->second->GetMaxDuration());
stmt->setInt32(index++, itr->second->GetDuration());
stmt->setUInt8(index++, itr->second->GetCharges());
+ stmt->setFloat(index++, itr->second->GetCritChance());
+ stmt->setBool (index++, itr->second->CanApplyResilience());
trans->Append(stmt);
}
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 862f36b8dfc..b98daee4fd3 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -771,7 +771,7 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
case DAMAGE_SLIME:
{
DamageInfo dmgInfo(this, this, damage, nullptr, type == DAMAGE_LAVA ? SPELL_SCHOOL_MASK_FIRE : SPELL_SCHOOL_MASK_NATURE, DIRECT_DAMAGE, BASE_ATTACK);
- CalcAbsorbResist(dmgInfo);
+ Unit::CalcAbsorbResist(dmgInfo);
absorb = dmgInfo.GetAbsorb();
resist = dmgInfo.GetResist();
damage = dmgInfo.GetDamage();
@@ -781,7 +781,7 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
break;
}
- DealDamageMods(this, damage, &absorb);
+ Unit::DealDamageMods(this, damage, &absorb);
WorldPacket data(SMSG_ENVIRONMENTALDAMAGELOG, (21));
data << uint64(GetGUID());
@@ -791,7 +791,7 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
data << uint32(resist);
SendMessageToSet(&data, true);
- uint32 final_damage = DealDamage(this, damage, nullptr, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ uint32 final_damage = Unit::DealDamage(this, this, damage, nullptr, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
if (!IsAlive())
{
@@ -17769,8 +17769,8 @@ void Player::_LoadAuras(PreparedQueryResult result, uint32 timediff)
/* 0 1 2 3 4 5 6 7 8 9 10
QueryResult* result = CharacterDatabase.PQuery("SELECT casterGuid, spell, effectMask, recalculateMask, stackCount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2,
- 11 12 13
- maxDuration, remainTime, remainCharges FROM character_aura WHERE guid = '%u'", GetGUID().GetCounter());
+ 11 12 13 14 15
+ maxDuration, remainTime, remainCharges, critChance, applyResilience FROM character_aura WHERE guid = '%u'", GetGUID().GetCounter());
*/
if (result)
@@ -17794,6 +17794,8 @@ void Player::_LoadAuras(PreparedQueryResult result, uint32 timediff)
int32 maxduration = fields[11].GetInt32();
int32 remaintime = fields[12].GetInt32();
uint8 remaincharges = fields[13].GetUInt8();
+ float critChance = fields[14].GetFloat();
+ bool applyResilience = fields[15].GetBool();
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid);
if (!spellInfo)
@@ -17831,7 +17833,7 @@ void Player::_LoadAuras(PreparedQueryResult result, uint32 timediff)
continue;
}
- aura->SetLoadedState(maxduration, remaintime, remaincharges, stackcount, recalculatemask, &damage[0]);
+ aura->SetLoadedState(maxduration, remaintime, remaincharges, stackcount, recalculatemask, critChance, applyResilience, &damage[0]);
aura->ApplyForTargets();
TC_LOG_DEBUG("entities.player", "Player::_LoadAuras: Added aura (SpellID: %u, EffectMask: %u) to player '%s (%s)",
spellInfo->Id, effmask, GetName().c_str(), GetGUID().ToString().c_str());
@@ -19517,7 +19519,9 @@ void Player::_SaveAuras(SQLTransaction& trans)
stmt->setInt32(index++, baseDamage[2]);
stmt->setInt32(index++, itr->second->GetMaxDuration());
stmt->setInt32(index++, itr->second->GetDuration());
- stmt->setUInt8(index, itr->second->GetCharges());
+ stmt->setUInt8(index++, itr->second->GetCharges());
+ stmt->setFloat(index++, itr->second->GetCritChance());
+ stmt->setBool (index++, itr->second->CanApplyResilience());
trans->Append(stmt);
}
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index d74b36c1e84..271cd465709 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1594,6 +1594,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 GetBaseSpellPowerBonus() const { return m_baseSpellPower; }
int32 GetSpellPenetrationItemMod() const { return m_spellPenetrationItemMod; }
+ bool CanApplyResilience() const override { return true; }
+
float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const;
void UpdateBlockPercentage();
void UpdateCritPercentage(WeaponAttackType attType);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 811be1e2076..5020baa928f 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -625,7 +625,7 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons
|| HasBreakableByDamageAuraType(SPELL_AURA_TRANSFORM, excludeAura));
}
-void Unit::DealDamageMods(Unit const* victim, uint32 &damage, uint32* absorb) const
+/*static*/ void Unit::DealDamageMods(Unit const* victim, uint32& damage, uint32* absorb)
{
if (!victim || !victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()))
{
@@ -635,20 +635,20 @@ void Unit::DealDamageMods(Unit const* victim, uint32 &damage, uint32* absorb) co
}
}
-uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss)
+/*static*/ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss)
{
uint32 rage_damage = damage + (cleanDamage ? cleanDamage->absorbed_damage : 0);
if (victim->IsAIEnabled)
- victim->GetAI()->DamageTaken(this, damage);
+ victim->GetAI()->DamageTaken(attacker, damage);
- if (IsAIEnabled)
- GetAI()->DamageDealt(victim, damage, damagetype);
+ if (attacker && attacker->IsAIEnabled)
+ attacker->GetAI()->DamageDealt(victim, damage, damagetype);
// Hook for OnDamage Event
- sScriptMgr->OnDamage(this, victim, damage);
+ sScriptMgr->OnDamage(attacker, victim, damage);
- if (victim->GetTypeId() == TYPEID_PLAYER && this != victim)
+ if (victim->GetTypeId() == TYPEID_PLAYER && attacker != victim)
{
// Signal to pets that their owner was attacked - except when DOT.
if (damagetype != DOT)
@@ -656,7 +656,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
for (Unit* controlled : victim->m_Controlled)
if (Creature* cControlled = controlled->ToCreature())
if (cControlled->IsAIEnabled)
- cControlled->AI()->OwnerAttackedBy(this);
+ cControlled->AI()->OwnerAttackedBy(attacker);
}
if (victim->ToPlayer()->GetCommandStatus(CHEAT_GOD))
@@ -674,16 +674,20 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
else
victim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TAKE_DAMAGE, 0);
- // interrupt spells with SPELL_INTERRUPT_FLAG_ABORT_ON_DMG on absorbed damage (no dots)
- if (!damage && damagetype != DOT && cleanDamage && cleanDamage->absorbed_damage)
- if (victim != this && victim->GetTypeId() == TYPEID_PLAYER)
- if (Spell* spell = victim->m_currentSpells[CURRENT_GENERIC_SPELL])
- if (spell->getState() == SPELL_STATE_PREPARING)
- {
- uint32 interruptFlags = spell->m_spellInfo->InterruptFlags;
- if ((interruptFlags & SPELL_INTERRUPT_FLAG_ABORT_ON_DMG) != 0)
- victim->InterruptNonMeleeSpells(false);
- }
+ // interrupt spells with SPELL_INTERRUPT_FLAG_ABORT_ON_DMG on absorbed damage (no dots)
+ if (!damage && damagetype != DOT && cleanDamage && cleanDamage->absorbed_damage)
+ {
+ if (victim != attacker && victim->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (Spell* spell = victim->m_currentSpells[CURRENT_GENERIC_SPELL])
+ if (spell->getState() == SPELL_STATE_PREPARING)
+ {
+ uint32 interruptFlags = spell->m_spellInfo->InterruptFlags;
+ if ((interruptFlags & SPELL_INTERRUPT_FLAG_ABORT_ON_DMG) != 0)
+ victim->InterruptNonMeleeSpells(false);
+ }
+ }
+ }
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
@@ -706,13 +710,13 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
uint32 share = CalculatePct(damage, (*i)->GetAmount());
/// @todo check packets if damage is done by victim, or by attacker of victim
- DealDamageMods(shareDamageTarget, share, nullptr);
- DealDamage(shareDamageTarget, share, nullptr, NODAMAGE, spell->GetSchoolMask(), spell, false);
+ Unit::DealDamageMods(shareDamageTarget, share, nullptr);
+ Unit::DealDamage(attacker, shareDamageTarget, share, nullptr, NODAMAGE, spell->GetSchoolMask(), spell, false);
}
}
// Rage from Damage made (only from direct weapon damage)
- if (cleanDamage && damagetype == DIRECT_DAMAGE && this != victim && getPowerType() == POWER_RAGE)
+ if (attacker && cleanDamage && damagetype == DIRECT_DAMAGE && attacker != victim && attacker->getPowerType() == POWER_RAGE)
{
uint32 weaponSpeedHitFactor;
@@ -721,11 +725,11 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
case BASE_ATTACK:
case OFF_ATTACK:
{
- weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType) / 1000.0f * (cleanDamage->attackType == BASE_ATTACK ? 3.5f : 1.75f));
+ weaponSpeedHitFactor = uint32(attacker->GetAttackTime(cleanDamage->attackType) / 1000.0f * (cleanDamage->attackType == BASE_ATTACK ? 3.5f : 1.75f));
if (cleanDamage->hitOutCome == MELEE_HIT_CRIT)
weaponSpeedHitFactor *= 2;
- RewardRage(rage_damage, weaponSpeedHitFactor, true);
+ attacker->RewardRage(rage_damage, weaponSpeedHitFactor, true);
break;
}
case RANGED_ATTACK:
@@ -744,18 +748,18 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
return 0;
}
- TC_LOG_DEBUG("entities.unit", "DealDamageStart");
-
uint32 health = victim->GetHealth();
- TC_LOG_DEBUG("entities.unit", "%s dealt %u damage to %s", GetGUID().ToString().c_str(), damage, victim->GetGUID().ToString().c_str());
// duel ends when player has 1 or less hp
bool duel_hasEnded = false;
bool duel_wasMounted = false;
if (victim->GetTypeId() == TYPEID_PLAYER && victim->ToPlayer()->duel && damage >= (health-1))
{
+ if (!attacker)
+ return 0;
+
// prevent kill only if killed in duel and killed by opponent or opponent controlled creature
- if (victim->ToPlayer()->duel->opponent == this || victim->ToPlayer()->duel->opponent->GetGUID() == GetOwnerGUID())
+ if (victim->ToPlayer()->duel->opponent == attacker || victim->ToPlayer()->duel->opponent->GetGUID() == attacker->GetOwnerGUID())
damage = health - 1;
duel_hasEnded = true;
@@ -766,8 +770,11 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (victimRider && victimRider->duel && victimRider->duel->isMounted)
{
+ if (!attacker)
+ return 0;
+
// prevent kill only if killed in duel and killed by opponent or opponent controlled creature
- if (victimRider->duel->opponent == this || victimRider->duel->opponent->GetGUID() == GetCharmerGUID())
+ if (victimRider->duel->opponent == attacker || victimRider->duel->opponent->GetGUID() == attacker->GetCharmerGUID())
damage = health - 1;
duel_wasMounted = true;
@@ -775,17 +782,18 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
}
}
- if (GetTypeId() == TYPEID_PLAYER && this != victim)
+ if (attacker && attacker != victim)
{
- Player* killer = ToPlayer();
-
- // in bg, count dmg if victim is also a player
- if (victim->GetTypeId() == TYPEID_PLAYER)
- if (Battleground* bg = killer->GetBattleground())
- bg->UpdatePlayerScore(killer, SCORE_DAMAGE_DONE, damage);
+ if (Player* killer = attacker->ToPlayer())
+ {
+ // in bg, count dmg if victim is also a player
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ if (Battleground* bg = killer->GetBattleground())
+ bg->UpdatePlayerScore(killer, SCORE_DAMAGE_DONE, damage);
- killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE, health > damage ? damage : health, 0, victim);
- killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT, damage);
+ killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE, health > damage ? damage : health, 0, victim);
+ killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT, damage);
+ }
}
if (victim->GetTypeId() == TYPEID_PLAYER)
@@ -793,25 +801,21 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
else if (!victim->IsControlledByPlayer() || victim->IsVehicle())
{
if (!victim->ToCreature()->hasLootRecipient())
- victim->ToCreature()->SetLootRecipient(this);
+ victim->ToCreature()->SetLootRecipient(attacker);
- if (IsControlledByPlayer() || (ToTempSummon() && ToTempSummon()->GetSummoner() && ToTempSummon()->GetSummoner()->GetTypeId() == TYPEID_PLAYER))
+ if (!attacker || attacker->IsControlledByPlayer() || (attacker->ToTempSummon() && attacker->ToTempSummon()->GetSummoner() && attacker->ToTempSummon()->GetSummoner()->GetTypeId() == TYPEID_PLAYER))
victim->ToCreature()->LowerPlayerDamageReq(health < damage ? health : damage);
}
if (health <= damage)
{
- TC_LOG_DEBUG("entities.unit", "DealDamage: victim just died");
-
- if (victim->GetTypeId() == TYPEID_PLAYER && victim != this)
+ if (victim->GetTypeId() == TYPEID_PLAYER && victim != attacker)
victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, health);
- Kill(victim, durabilityLoss);
+ Unit::Kill(attacker, victim, durabilityLoss);
}
else
{
- TC_LOG_DEBUG("entities.unit", "DealDamageAlive");
-
if (victim->GetTypeId() == TYPEID_PLAYER)
victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, damage);
@@ -826,7 +830,8 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (damagetype != DOT && damage > 0 && !victim->GetOwnerGUID().IsPlayer() && (!spellProto || !spellProto->HasAura(SPELL_AURA_DAMAGE_SHIELD)))
victim->ToCreature()->SetLastDamagedTime(GameTime::GetGameTime() + MAX_AGGRO_RESET_TIME);
- victim->GetThreatManager().AddThreat(this, float(damage), spellProto);
+ if (attacker)
+ victim->GetThreatManager().AddThreat(attacker, float(damage), spellProto);
}
else // victim is a player
{
@@ -839,29 +844,31 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
}
// Rage from damage received
- if (this != victim && victim->getPowerType() == POWER_RAGE)
+ if (attacker != victim && victim->getPowerType() == POWER_RAGE)
{
rage_damage = damage + (cleanDamage ? cleanDamage->absorbed_damage : 0);
victim->RewardRage(rage_damage, 0, false);
}
- if (GetTypeId() == TYPEID_PLAYER)
+ if (attacker && attacker->GetTypeId() == TYPEID_PLAYER)
{
// random durability for items (HIT DONE)
if (roll_chance_f(sWorld->getRate(RATE_DURABILITY_LOSS_DAMAGE)))
{
EquipmentSlots slot = EquipmentSlots(urand(0, EQUIPMENT_SLOT_END-1));
- ToPlayer()->DurabilityPointLossForEquipSlot(slot);
+ attacker->ToPlayer()->DurabilityPointLossForEquipSlot(slot);
}
}
if (damagetype != NODAMAGE && damage)
{
- if (victim != this && victim->GetTypeId() == TYPEID_PLAYER && // does not support creature push_back
+ if (victim != attacker && victim->GetTypeId() == TYPEID_PLAYER && // does not support creature push_back
(!spellProto || !(spellProto->HasAttribute(SPELL_ATTR7_NO_PUSHBACK_ON_DAMAGE) || spellProto->HasAttribute(SPELL_ATTR3_TREAT_AS_PERIODIC))))
{
if (damagetype != DOT)
+ {
if (Spell* spell = victim->m_currentSpells[CURRENT_GENERIC_SPELL])
+ {
if (spell->getState() == SPELL_STATE_PREPARING)
{
uint32 interruptFlags = spell->m_spellInfo->InterruptFlags;
@@ -870,14 +877,18 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
else if (interruptFlags & SPELL_INTERRUPT_FLAG_PUSH_BACK)
spell->Delayed();
}
+ }
+ }
if (Spell* spell = victim->m_currentSpells[CURRENT_CHANNELED_SPELL])
+ {
if (spell->getState() == SPELL_STATE_CASTING)
{
uint32 channelInterruptFlags = spell->m_spellInfo->ChannelInterruptFlags;
if (((channelInterruptFlags & CHANNEL_FLAG_DELAY) != 0) && (damagetype != DOT))
spell->DelayedChannel();
}
+ }
}
}
@@ -901,8 +912,6 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
}
}
- TC_LOG_DEBUG("entities.unit", "DealDamageEnd returned %d damage", damage);
-
return damage;
}
@@ -970,8 +979,8 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
// Spells with SPELL_ATTR4_FIXED_DAMAGE ignore resilience because their damage is based off another spell's damage.
if (!spellInfo->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
{
- if (IsDamageReducedByArmor(damageSchoolMask, spellInfo))
- damage = CalcArmorReducedDamage(victim, damage, spellInfo, attackType);
+ if (Unit::IsDamageReducedByArmor(damageSchoolMask, spellInfo))
+ damage = Unit::CalcArmorReducedDamage(this, victim, damage, spellInfo, attackType);
bool blocked = false;
// Per-school calc
@@ -1035,10 +1044,8 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
damage -= damageInfo->blocked;
}
- if (attackType != RANGED_ATTACK)
- ApplyResilience(victim, nullptr, &damage, crit, CR_CRIT_TAKEN_MELEE);
- else
- ApplyResilience(victim, nullptr, &damage, crit, CR_CRIT_TAKEN_RANGED);
+ if (CanApplyResilience())
+ Unit::ApplyResilience(victim, nullptr, &damage, crit, (attackType == RANGED_ATTACK ? CR_CRIT_TAKEN_RANGED : CR_CRIT_TAKEN_MELEE));
break;
}
// Magical Attacks
@@ -1049,10 +1056,11 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
if (crit)
{
damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
- damage = SpellCriticalDamageBonus(spellInfo, damage, victim);
+ damage = Unit::SpellCriticalDamageBonus(this, spellInfo, damage, victim);
}
- ApplyResilience(victim, nullptr, &damage, crit, CR_CRIT_TAKEN_SPELL);
+ if (CanApplyResilience())
+ Unit::ApplyResilience(victim, nullptr, &damage, crit, CR_CRIT_TAKEN_SPELL);
break;
}
default:
@@ -1069,7 +1077,7 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
damageInfo->damage = damage;
DamageInfo dmgInfo(*damageInfo, SPELL_DIRECT_DAMAGE, BASE_ATTACK, PROC_HIT_NONE);
- CalcAbsorbResist(dmgInfo);
+ Unit::CalcAbsorbResist(dmgInfo);
damageInfo->absorb = dmgInfo.GetAbsorb();
damageInfo->resist = dmgInfo.GetResist();
@@ -1103,7 +1111,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss)
// Call default DealDamage
CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(victim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss);
+ Unit::DealDamage(this, victim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss);
}
/// @todo for melee need create structure as in
@@ -1167,9 +1175,9 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
sScriptMgr->ModifyMeleeDamage(damageInfo->target, damageInfo->attacker, damage);
// Calculate armor reduction
- if (IsDamageReducedByArmor((SpellSchoolMask)(damageInfo->damageSchoolMask)))
+ if (Unit::IsDamageReducedByArmor((SpellSchoolMask)(damageInfo->damageSchoolMask)))
{
- damageInfo->damage = CalcArmorReducedDamage(damageInfo->target, damage, nullptr, damageInfo->attackType);
+ damageInfo->damage = Unit::CalcArmorReducedDamage(damageInfo->attacker, damageInfo->target, damage, nullptr, damageInfo->attackType);
damageInfo->cleanDamage += damage - damageInfo->damage;
}
else
@@ -1278,7 +1286,8 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
int32 resilienceReduction = damageInfo->damage;
// attackType is checked already for BASE_ATTACK or OFF_ATTACK so it can't be RANGED_ATTACK here
- ApplyResilience(victim, nullptr, &resilienceReduction, (damageInfo->hitOutCome == MELEE_HIT_CRIT), CR_CRIT_TAKEN_MELEE);
+ if (CanApplyResilience())
+ Unit::ApplyResilience(victim, nullptr, &resilienceReduction, (damageInfo->hitOutCome == MELEE_HIT_CRIT), CR_CRIT_TAKEN_MELEE);
resilienceReduction = damageInfo->damage - resilienceReduction;
damageInfo->damage -= resilienceReduction;
damageInfo->cleanDamage += resilienceReduction;
@@ -1289,7 +1298,7 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
damageInfo->procVictim |= PROC_FLAG_TAKEN_DAMAGE;
// Calculate absorb & resists
DamageInfo dmgInfo(*damageInfo);
- CalcAbsorbResist(dmgInfo);
+ Unit::CalcAbsorbResist(dmgInfo);
damageInfo->absorb = dmgInfo.GetAbsorb();
damageInfo->resist = dmgInfo.GetResist();
@@ -1353,7 +1362,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
// Call default DealDamage
CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, damageInfo->attackType, damageInfo->hitOutCome);
- DealDamage(victim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damageSchoolMask), nullptr, durabilityLoss);
+ Unit::DealDamage(this, victim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damageSchoolMask), nullptr, durabilityLoss);
// If this is a creature and it attacks from behind it has a probability to daze it's victim
if ((damageInfo->hitOutCome == MELEE_HIT_CRIT || damageInfo->hitOutCome == MELEE_HIT_CRUSHING || damageInfo->hitOutCome == MELEE_HIT_NORMAL || damageInfo->hitOutCome == MELEE_HIT_GLANCING) &&
@@ -1412,12 +1421,12 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
uint32 damage = aurEff->GetAmount();
if (Unit* caster = aurEff->GetCaster())
{
- damage = caster->SpellDamageBonusDone(this, spellInfo, damage, SPELL_DIRECT_DAMAGE);
+ damage = caster->SpellDamageBonusDone(this, spellInfo, damage, SPELL_DIRECT_DAMAGE, { });
damage = SpellDamageBonusTaken(caster, spellInfo, damage, SPELL_DIRECT_DAMAGE);
}
// No Unit::CalcAbsorbResist here - opcode doesn't send that data - this damage is probably not affected by that
- victim->DealDamageMods(this, damage, nullptr);
+ Unit::DealDamageMods(this, damage, nullptr);
/// @todo Move this to a packet handler
WorldPacket data(SMSG_SPELLDAMAGESHIELD, 8 + 8 + 4 + 4 + 4 + 4 + 4);
@@ -1430,7 +1439,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
data << uint32(spellInfo->SchoolMask);
victim->SendMessageToSet(&data, true);
- victim->DealDamage(this, damage, nullptr, SPELL_DIRECT_DAMAGE, spellInfo->GetSchoolMask(), spellInfo, true);
+ Unit::DealDamage(victim, this, damage, nullptr, SPELL_DIRECT_DAMAGE, spellInfo->GetSchoolMask(), spellInfo, true);
}
}
}
@@ -1443,7 +1452,7 @@ void Unit::HandleEmoteCommand(uint32 anim_id)
SendMessageToSet(&data, true);
}
-bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* spellInfo /*= nullptr*/, int8 effIndex /*= -1*/)
+/*static*/ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* spellInfo /*= nullptr*/, int8 effIndex /*= -1*/)
{
// only physical spells damage gets reduced by armor
if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0)
@@ -1466,72 +1475,75 @@ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* s
return true;
}
-uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType) const
+/*static*/ uint32 Unit::CalcArmorReducedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellInfo const* spellInfo, uint8 attackerLevel /*= 0*/, WeaponAttackType attackType /*= MAX_ATTACK*/)
{
float armor = float(victim->GetArmor());
// Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura
- armor += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_NORMAL);
-
- if (spellInfo)
- if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_IGNORE_ARMOR, armor);
-
- AuraEffectList const& resIgnoreAurasAb = GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST);
- for (AuraEffectList::const_iterator j = resIgnoreAurasAb.begin(); j != resIgnoreAurasAb.end(); ++j)
+ if (attacker)
{
- if ((*j)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL && (*j)->IsAffectedOnSpell(spellInfo))
- armor = std::floor(AddPct(armor, -(*j)->GetAmount()));
- }
+ armor += attacker->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_NORMAL);
- AuraEffectList const& resIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
- for (AuraEffectList::const_iterator j = resIgnoreAuras.begin(); j != resIgnoreAuras.end(); ++j)
- {
- if ((*j)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
- armor = std::floor(AddPct(armor, -(*j)->GetAmount()));
- }
+ if (spellInfo)
+ if (Player* modOwner = attacker->GetSpellModOwner())
+ modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_IGNORE_ARMOR, armor);
- // Apply Player CR_ARMOR_PENETRATION rating and buffs from stances\specializations etc.
- if (GetTypeId() == TYPEID_PLAYER)
- {
- float arpPct = ToPlayer()->GetRatingBonusValue(CR_ARMOR_PENETRATION);
+ AuraEffectList const& resIgnoreAurasAb = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST);
+ for (AuraEffect const* aurEff : resIgnoreAurasAb)
+ {
+ if (aurEff->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL && aurEff->IsAffectedOnSpell(spellInfo))
+ armor = std::floor(AddPct(armor, -aurEff->GetAmount()));
+ }
- Item const* weapon = ToPlayer()->GetWeaponForAttack(attackType, true);
- arpPct += GetTotalAuraModifier(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT, [weapon](AuraEffect const* aurEff) -> bool
+ AuraEffectList const& resIgnoreAuras = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
+ for (AuraEffect const* aurEff : resIgnoreAuras)
{
- return aurEff->GetSpellInfo()->IsItemFitToSpellRequirements(weapon);
- });
+ if (aurEff->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
+ armor = std::floor(AddPct(armor, -aurEff->GetAmount()));
+ }
- // no more than 100%
- RoundToInterval(arpPct, 0.f, 100.f);
+ // Apply Player CR_ARMOR_PENETRATION rating and buffs from stances\specializations etc.
+ if (attacker->GetTypeId() == TYPEID_PLAYER)
+ {
+ float arpPct = attacker->ToPlayer()->GetRatingBonusValue(CR_ARMOR_PENETRATION);
- float maxArmorPen = 0.f;
- if (victim->getLevel() < 60)
- maxArmorPen = float(400 + 85 * victim->getLevel());
- else
- maxArmorPen = 400 + 85 * victim->getLevel() + 4.5f * 85 * (victim->getLevel() - 59);
+ Item const* weapon = attacker->ToPlayer()->GetWeaponForAttack(attackType, true);
+ arpPct += attacker->GetTotalAuraModifier(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT, [weapon](AuraEffect const* aurEff) -> bool
+ {
+ return aurEff->GetSpellInfo()->IsItemFitToSpellRequirements(weapon);
+ });
- // Cap armor penetration to this number
- maxArmorPen = std::min((armor + maxArmorPen) / 3.f, armor);
- // Figure out how much armor do we ignore
- armor -= CalculatePct(maxArmorPen, arpPct);
+ // no more than 100%
+ RoundToInterval(arpPct, 0.f, 100.f);
+
+ float maxArmorPen = 0.f;
+ if (victim->getLevel() < 60)
+ maxArmorPen = float(400 + 85 * victim->getLevel());
+ else
+ maxArmorPen = 400 + 85 * victim->getLevel() + 4.5f * 85 * (victim->getLevel() - 59);
+
+ // Cap armor penetration to this number
+ maxArmorPen = std::min((armor + maxArmorPen) / 3.f, armor);
+ // Figure out how much armor do we ignore
+ armor -= CalculatePct(maxArmorPen, arpPct);
+ }
}
if (armor < 0.0f)
armor = 0.0f;
- float levelModifier = getLevel();
- if (levelModifier > 59)
- levelModifier = levelModifier + 4.5f * (levelModifier - 59);
+ float levelModifier = attacker ? attacker->getLevel() : attackerLevel;
+ if (levelModifier > 59.f)
+ levelModifier = levelModifier + 4.5f * (levelModifier - 59.f);
- float damageReduction = 0.1f * armor / (8.5f * levelModifier + 40);
+ float damageReduction = 0.1f * armor / (8.5f * levelModifier + 40.f);
damageReduction /= (1.0f + damageReduction);
RoundToInterval(damageReduction, 0.f, 0.75f);
return std::max<uint32>(damage * (1.0f - damageReduction), 1);
}
-uint32 Unit::CalcSpellResistedDamage(Unit* victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const* spellInfo) const
+/*static*/ uint32 Unit::CalcSpellResistedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const* spellInfo)
{
// Magic damage, check for resists
if (!(schoolMask & SPELL_SCHOOL_MASK_MAGIC))
@@ -1552,8 +1564,7 @@ uint32 Unit::CalcSpellResistedDamage(Unit* victim, uint32 damage, SpellSchoolMas
return 0;
}
- float const averageResist = CalculateAverageResistReduction(schoolMask, victim, spellInfo);
-
+ float const averageResist = Unit::CalculateAverageResistReduction(attacker, schoolMask, victim, spellInfo);
float discreteResistProbability[11] = { };
if (averageResist <= 0.1f)
{
@@ -1579,14 +1590,17 @@ uint32 Unit::CalcSpellResistedDamage(Unit* victim, uint32 damage, SpellSchoolMas
if (damageResisted > 0.0f) // if any damage was resisted
{
int32 ignoredResistance = 0;
- ignoredResistance += GetTotalAuraModifier(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST, [schoolMask, spellInfo](AuraEffect const* aurEff) -> bool
+ if (attacker)
{
- if ((aurEff->GetMiscValue() & schoolMask) && aurEff->IsAffectedOnSpell(spellInfo))
- return true;
- return false;
- });
+ ignoredResistance += attacker->GetTotalAuraModifier(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST, [schoolMask, spellInfo](AuraEffect const* aurEff) -> bool
+ {
+ if ((aurEff->GetMiscValue() & schoolMask) && aurEff->IsAffectedOnSpell(spellInfo))
+ return true;
+ return false;
+ });
- ignoredResistance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_IGNORE_TARGET_RESIST, schoolMask);
+ ignoredResistance += attacker->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_IGNORE_TARGET_RESIST, schoolMask);
+ }
ignoredResistance = std::min<int32>(ignoredResistance, 100);
ApplyPct(damageResisted, 100 - ignoredResistance);
@@ -1594,7 +1608,7 @@ uint32 Unit::CalcSpellResistedDamage(Unit* victim, uint32 damage, SpellSchoolMas
// Spells with melee and magic school mask, decide whether resistance or armor absorb is higher
if (spellInfo && spellInfo->HasAttribute(SPELL_ATTR0_CU_SCHOOLMASK_NORMAL_WITH_MAGIC))
{
- uint32 damageAfterArmor = CalcArmorReducedDamage(victim, damage, spellInfo, BASE_ATTACK);
+ uint32 damageAfterArmor = Unit::CalcArmorReducedDamage(attacker, victim, damage, spellInfo, BASE_ATTACK);
float armorReduction = damage - damageAfterArmor;
// pick the lower one, the weakest resistance counts
@@ -1606,20 +1620,22 @@ uint32 Unit::CalcSpellResistedDamage(Unit* victim, uint32 damage, SpellSchoolMas
return uint32(damageResisted);
}
-float Unit::CalculateAverageResistReduction(SpellSchoolMask schoolMask, Unit const* victim, SpellInfo const* spellInfo) const
+/*static*/ float Unit::CalculateAverageResistReduction(Unit const* attacker, SpellSchoolMask schoolMask, Unit const* victim, SpellInfo const* spellInfo)
{
float victimResistance = float(victim->GetResistance(schoolMask));
-
- // pets inherit 100% of masters penetration
- // excluding traps
- Player const* player = GetSpellModOwner();
- if (player && GetEntry() != WORLD_TRIGGER)
+ if (attacker)
{
- victimResistance += float(player->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
- victimResistance -= float(player->GetSpellPenetrationItemMod());
+ // pets inherit 100% of masters penetration
+ // excluding traps
+ Player const* player = attacker->GetSpellModOwner();
+ if (player && attacker->GetEntry() != WORLD_TRIGGER)
+ {
+ victimResistance += float(player->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
+ victimResistance -= float(player->GetSpellPenetrationItemMod());
+ }
+ else
+ victimResistance += float(attacker->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
}
- else
- victimResistance += float(GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
// holy resistance exists in pve and comes from level difference, ignore template values
if (schoolMask & SPELL_SCHOOL_MASK_HOLY)
@@ -1632,8 +1648,8 @@ float Unit::CalculateAverageResistReduction(SpellSchoolMask schoolMask, Unit con
victimResistance = std::max(victimResistance, 0.0f);
// level-based resistance does not apply to binary spells, and cannot be overcome by spell penetration
- if (!spellInfo || !spellInfo->HasAttribute(SPELL_ATTR0_CU_BINARY_SPELL))
- victimResistance += std::max((float(victim->getLevelForTarget(this)) - float(getLevelForTarget(victim))) * 5.0f, 0.0f);
+ if (attacker && (!spellInfo || !spellInfo->HasAttribute(SPELL_ATTR0_CU_BINARY_SPELL)))
+ victimResistance += std::max((float(victim->getLevelForTarget(attacker)) - float(attacker->getLevelForTarget(victim))) * 5.0f, 0.0f);
static uint32 const BOSS_LEVEL = 83;
static float const BOSS_RESISTANCE_CONSTANT = 510.0f;
@@ -1648,26 +1664,30 @@ float Unit::CalculateAverageResistReduction(SpellSchoolMask schoolMask, Unit con
return victimResistance / (victimResistance + resistanceConstant);
}
-void Unit::CalcAbsorbResist(DamageInfo& damageInfo)
+/*static*/ void Unit::CalcAbsorbResist(DamageInfo& damageInfo)
{
if (!damageInfo.GetVictim() || !damageInfo.GetVictim()->IsAlive() || !damageInfo.GetDamage())
return;
- uint32 resistedDamage = CalcSpellResistedDamage(damageInfo.GetVictim(), damageInfo.GetDamage(), damageInfo.GetSchoolMask(), damageInfo.GetSpellInfo());
+ uint32 resistedDamage = Unit::CalcSpellResistedDamage(damageInfo.GetAttacker(), damageInfo.GetVictim(), damageInfo.GetDamage(), damageInfo.GetSchoolMask(), damageInfo.GetSpellInfo());
damageInfo.ResistDamage(resistedDamage);
// Ignore Absorption Auras
- float auraAbsorbMod(GetMaxPositiveAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL, damageInfo.GetSchoolMask()));
- auraAbsorbMod = std::max(auraAbsorbMod, static_cast<float>(GetMaxPositiveAuraModifier(SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL, [&damageInfo](AuraEffect const* aurEff) -> bool
+ float auraAbsorbMod = 0.f;
+ if (Unit* attacker = damageInfo.GetAttacker())
{
- if (!(aurEff->GetMiscValue() & damageInfo.GetSchoolMask()))
- return false;
+ auraAbsorbMod = attacker->GetMaxPositiveAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL, damageInfo.GetSchoolMask());
+ auraAbsorbMod = std::max(auraAbsorbMod, static_cast<float>(attacker->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL, [&damageInfo](AuraEffect const* aurEff) -> bool
+ {
+ if (!(aurEff->GetMiscValue() & damageInfo.GetSchoolMask()))
+ return false;
- if (!aurEff->IsAffectedOnSpell(damageInfo.GetSpellInfo()))
- return false;
+ if (!aurEff->IsAffectedOnSpell(damageInfo.GetSpellInfo()))
+ return false;
- return true;
- })));
+ return true;
+ })));
+ }
RoundToInterval(auraAbsorbMod, 0.0f, 100.0f);
@@ -1785,7 +1805,7 @@ void Unit::CalcAbsorbResist(DamageInfo& damageInfo)
damageInfo.ModifyDamage(absorbIgnoringDamage);
// split damage auras - only when not damaging self
- if (damageInfo.GetVictim() != this)
+ if (damageInfo.GetVictim() != damageInfo.GetAttacker())
{
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
@@ -1820,12 +1840,13 @@ void Unit::CalcAbsorbResist(DamageInfo& damageInfo)
uint32 splitted = splitDamage;
uint32 splitted_absorb = 0;
- DealDamageMods(caster, splitted, &splitted_absorb);
+ Unit::DealDamageMods(caster, splitted, &splitted_absorb);
- SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted, damageInfo.GetSchoolMask(), splitted_absorb, 0, false, 0, false);
+ if (Unit* attacker = damageInfo.GetAttacker())
+ attacker->SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted, damageInfo.GetSchoolMask(), splitted_absorb, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, damageInfo.GetSchoolMask(), (*itr)->GetSpellInfo(), false);
+ Unit::DealDamage(damageInfo.GetAttacker(), caster, splitted, &cleanDamage, DIRECT_DAMAGE, damageInfo.GetSchoolMask(), (*itr)->GetSpellInfo(), false);
}
// We're going to call functions which can modify content of the list during iteration over it's elements
@@ -1864,20 +1885,21 @@ void Unit::CalcAbsorbResist(DamageInfo& damageInfo)
}
uint32 split_absorb = 0;
- DealDamageMods(caster, splitDamage, &split_absorb);
+ Unit::DealDamageMods(caster, splitDamage, &split_absorb);
- SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitDamage, damageInfo.GetSchoolMask(), split_absorb, 0, false, 0, false);
+ if (Unit* attacker = damageInfo.GetAttacker())
+ attacker->SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitDamage, damageInfo.GetSchoolMask(), split_absorb, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(splitDamage, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, damageInfo.GetSchoolMask(), (*itr)->GetSpellInfo(), false);
+ Unit::DealDamage(damageInfo.GetAttacker(), caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, damageInfo.GetSchoolMask(), (*itr)->GetSpellInfo(), false);
// break 'Fear' and similar auras
- ProcSkillsAndAuras(caster, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_HIT, PROC_HIT_NONE, nullptr, &damageInfo, nullptr);
+ Unit::ProcSkillsAndAuras(damageInfo.GetAttacker(), caster, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_HIT, PROC_HIT_NONE, nullptr, &damageInfo, nullptr);
}
}
}
-void Unit::CalcHealAbsorb(HealInfo& healInfo) const
+/*static*/ void Unit::CalcHealAbsorb(HealInfo& healInfo)
{
if (!healInfo.GetHeal())
return;
@@ -1971,13 +1993,13 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr
CalcDamageInfo damageInfo;
CalculateMeleeDamage(victim, 0, &damageInfo, attType);
// Send log damage message to client
- DealDamageMods(victim, damageInfo.damage, &damageInfo.absorb);
+ Unit::DealDamageMods(victim, damageInfo.damage, &damageInfo.absorb);
SendAttackStateUpdate(&damageInfo);
DealMeleeDamage(&damageInfo, true);
DamageInfo dmgInfo(damageInfo);
- ProcSkillsAndAuras(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, PROC_SPELL_TYPE_NONE, PROC_SPELL_PHASE_NONE, dmgInfo.GetHitMask(), nullptr, &dmgInfo, nullptr);
+ Unit::ProcSkillsAndAuras(damageInfo.attacker, damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, PROC_SPELL_TYPE_NONE, PROC_SPELL_PHASE_NONE, dmgInfo.GetHitMask(), nullptr, &dmgInfo, nullptr);
if (GetTypeId() == TYPEID_PLAYER)
TC_LOG_DEBUG("entities.unit", "AttackerStateUpdate: (Player) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.",
@@ -2055,7 +2077,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(Unit const* victim, WeaponAttackTy
int32 miss_chance = int32(MeleeSpellMissChance(victim, attType, attackerWeaponSkill - victimMaxSkillValueForLevel, 0) * 100.0f);
// Critical hit chance
- int32 crit_chance = int32(GetUnitCriticalChance(attType, victim) * 100.0f);
+ int32 crit_chance = int32(GetUnitCriticalChanceAgainst(attType, victim) * 100.0f);
int32 dodge_chance = int32(GetUnitDodgeChance(attType, victim) * 100.0f);
int32 block_chance = int32(GetUnitBlockChance(attType, victim) * 100.0f);
@@ -2534,7 +2556,7 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo
// resistance chance for binary spells, equals to average damage reduction of non-binary spell
if (spellInfo->HasAttribute(SPELL_ATTR0_CU_BINARY_SPELL) && (spellInfo->GetSchoolMask() & SPELL_SCHOOL_MASK_MAGIC))
- resist_chance += int32(CalculateAverageResistReduction(spellInfo->GetSchoolMask(), victim, spellInfo) * 10000.f); // 100 for spell calculations, and 100 for return value percentage
+ resist_chance += int32(Unit::CalculateAverageResistReduction(this, spellInfo->GetSchoolMask(), victim, spellInfo) * 10000.f); // 100 for spell calculations, and 100 for return value percentage
}
// Roll chance
@@ -2781,14 +2803,9 @@ float Unit::GetUnitBlockChance(WeaponAttackType attType, Unit const* victim) con
return std::max(chance, 0.0f);
}
-float Unit::GetUnitCriticalChance(WeaponAttackType attackType, Unit const* victim) const
+float Unit::GetUnitCriticalChanceDone(WeaponAttackType attackType) const
{
- int32 const attackerWeaponSkill = GetWeaponSkillValue(attackType, victim);
- int32 const victimDefenseSkill = victim->GetDefenseSkillValue(this);
- int32 const skillDiff = victimDefenseSkill - attackerWeaponSkill;
-
- float chance = 0.0f;
- float skillBonus = 0.0f;
+ float chance = 0.f;
if (GetTypeId() == TYPEID_PLAYER)
{
switch (attackType)
@@ -2818,29 +2835,40 @@ float Unit::GetUnitCriticalChance(WeaponAttackType attackType, Unit const* victi
}
}
+ return chance;
+}
+
+float Unit::GetUnitCriticalChanceTaken(Unit const* attacker, WeaponAttackType attackType, float critDone) const
+{
+ int32 const attackerWeaponSkill = attacker->GetWeaponSkillValue(attackType, this);
+ int32 const victimDefenseSkill = GetDefenseSkillValue(attacker);
+ int32 const skillDiff = victimDefenseSkill - attackerWeaponSkill;
+
+ float skillBonus = 0.0f;
+ float chance = critDone;
+
// flat aura mods
if (attackType == RANGED_ATTACK)
- chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE);
+ chance += GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE);
else
- chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE);
+ chance += GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE);
- chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER, [this](AuraEffect const* aurEff) -> bool
+ chance += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER, [attacker](AuraEffect const* aurEff) -> bool
{
- if (aurEff->GetCasterGUID() == GetGUID())
+ if (aurEff->GetCasterGUID() == attacker->GetGUID())
return true;
return false;
});
- chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE);
-
// reduce crit chance from Rating for players
- if (attackType != RANGED_ATTACK)
- ApplyResilience(victim, &chance, nullptr, false, CR_CRIT_TAKEN_MELEE);
- else
- ApplyResilience(victim, &chance, nullptr, false, CR_CRIT_TAKEN_RANGED);
+ if (attacker->CanApplyResilience())
+ Unit::ApplyResilience(this, &chance, nullptr, false, (attackType == RANGED_ATTACK ? CR_CRIT_TAKEN_RANGED : CR_CRIT_TAKEN_MELEE));
+
+ // applied after resilience
+ chance += GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE);
// Apply crit chance from defense skill
- if (victim->GetTypeId() == TYPEID_PLAYER)
+ if (GetTypeId() == TYPEID_PLAYER)
skillBonus = -skillDiff * 0.04f;
else
{
@@ -2850,7 +2878,13 @@ float Unit::GetUnitCriticalChance(WeaponAttackType attackType, Unit const* victi
}
chance += skillBonus;
- return std::max(chance, 0.0f);
+ return std::max(chance, 0.f);
+}
+
+float Unit::GetUnitCriticalChanceAgainst(WeaponAttackType attackType, Unit const* victim) const
+{
+ float chance = GetUnitCriticalChanceDone(attackType);
+ return victim->GetUnitCriticalChanceTaken(this, attackType, chance);
}
uint32 Unit::GetWeaponSkillValue(WeaponAttackType attType, Unit const* target) const
@@ -3442,7 +3476,6 @@ void Unit::_ApplyAura(AuraApplication * aurApp, uint8 effMask)
if (aurApp->GetRemoveMode())
return;
- aura->HandleAuraSpecificPeriodics(aurApp, caster);
aura->HandleAuraSpecificMods(aurApp, caster, true, false);
// apply effects of the aura
@@ -3953,7 +3986,7 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, U
caster->GetSingleCastAuras().push_back(aura);
}
// FIXME: using aura->GetMaxDuration() maybe not blizzlike but it fixes stealing of spells like Innervate
- newAura->SetLoadedState(aura->GetMaxDuration(), int32(dur), stealCharge ? 1 : aura->GetCharges(), 1, recalculateMask, &damage[0]);
+ newAura->SetLoadedState(aura->GetMaxDuration(), int32(dur), stealCharge ? 1 : aura->GetCharges(), 1, recalculateMask, aura->GetCritChance(), aura->CanApplyResilience(), &damage[0]);
newAura->ApplyForTargets();
}
}
@@ -5215,16 +5248,17 @@ void Unit::SendSpellNonMeleeDamageLog(Unit* target, uint32 SpellID, uint32 Damag
SendSpellNonMeleeDamageLog(&log);
}
-void Unit::ProcSkillsAndAuras(Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo)
+/*static*/ void Unit::ProcSkillsAndAuras(Unit* actor, Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo)
{
WeaponAttackType attType = damageInfo ? damageInfo->GetAttackType() : BASE_ATTACK;
- if (typeMaskActor)
- ProcSkillsAndReactives(false, actionTarget, typeMaskActor, hitMask, attType);
+ if (typeMaskActor && actor)
+ actor->ProcSkillsAndReactives(false, actionTarget, typeMaskActor, hitMask, attType);
if (typeMaskActionTarget && actionTarget)
- actionTarget->ProcSkillsAndReactives(true, this, typeMaskActionTarget, hitMask, attType);
+ actionTarget->ProcSkillsAndReactives(true, actor, typeMaskActionTarget, hitMask, attType);
- TriggerAurasProcOnEvent(actionTarget, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
+ if (actor)
+ actor->TriggerAurasProcOnEvent(actionTarget, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
}
void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo)
@@ -6340,39 +6374,45 @@ void Unit::SetCharm(Unit* charm, bool apply)
UpdatePetCombatState();
}
-void Unit::DealHeal(HealInfo& healInfo)
+/*static*/ void Unit::DealHeal(HealInfo& healInfo)
{
int32 gain = 0;
+ Unit* healer = healInfo.GetHealer();
Unit* victim = healInfo.GetTarget();
uint32 addhealth = healInfo.GetHeal();
- if (victim->IsAIEnabled)
- victim->GetAI()->HealReceived(this, addhealth);
+ if (healer)
+ {
+ if (victim->IsAIEnabled)
+ victim->GetAI()->HealReceived(healer, addhealth);
- if (IsAIEnabled)
- GetAI()->HealDone(victim, addhealth);
+ if (healer->IsAIEnabled)
+ healer->GetAI()->HealDone(victim, addhealth);
+ }
if (addhealth)
gain = victim->ModifyHealth(int32(addhealth));
// Hook for OnHeal Event
- sScriptMgr->OnHeal(this, victim, (uint32&)gain);
+ sScriptMgr->OnHeal(healer, victim, (uint32&)gain);
- Unit* unit = this;
+ Unit* unit = healer;
+ if (healer && healer->GetTypeId() == TYPEID_UNIT && healer->IsTotem())
+ unit = healer->GetOwner();
- if (GetTypeId() == TYPEID_UNIT && IsTotem())
- unit = GetOwner();
-
- if (Player* player = unit->ToPlayer())
+ if (unit)
{
- if (Battleground* bg = player->GetBattleground())
- bg->UpdatePlayerScore(player, SCORE_HEALING_DONE, gain);
+ if (Player* player = unit->ToPlayer())
+ {
+ if (Battleground* bg = player->GetBattleground())
+ bg->UpdatePlayerScore(player, SCORE_HEALING_DONE, gain);
- // use the actual gain, as the overheal shall not be counted, skip gain 0 (it ignored anyway in to criteria)
- if (gain)
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, victim);
+ // use the actual gain, as the overheal shall not be counted, skip gain 0 (it ignored anyway in to criteria)
+ if (gain)
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, victim);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST, addhealth);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST, addhealth);
+ }
}
if (Player* player = victim->ToPlayer())
@@ -6615,9 +6655,8 @@ void Unit::SendHealSpellLog(HealInfo& healInfo, bool critical /*= false*/)
int32 Unit::HealBySpell(HealInfo& healInfo, bool critical /*= false*/)
{
// calculate heal absorb and reduce healing
- CalcHealAbsorb(healInfo);
-
- DealHeal(healInfo);
+ Unit::CalcHealAbsorb(healInfo);
+ Unit::DealHeal(healInfo);
SendHealSpellLog(healInfo, critical);
return healInfo.GetEffectiveHeal();
}
@@ -6647,7 +6686,7 @@ void Unit::EnergizeBySpell(Unit* victim, SpellInfo const* spellInfo, int32 damag
victim->GetThreatManager().ForwardThreatForAssistingMe(this, float(damage)/2, spellInfo, true);
}
-uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack) const
+uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, Optional<float> const& donePctTotal, uint32 stack /*= 1*/) const
{
if (!spellProto || !victim || damagetype == DIRECT_DAMAGE)
return pdamage;
@@ -6659,20 +6698,20 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
// For totems get damage bonus from owner
if (GetTypeId() == TYPEID_UNIT && IsTotem())
if (Unit* owner = GetOwner())
- return owner->SpellDamageBonusDone(victim, spellProto, pdamage, damagetype);
+ return owner->SpellDamageBonusDone(victim, spellProto, pdamage, damagetype, donePctTotal, stack);
float ApCoeffMod = 1.0f;
int32 DoneTotal = 0;
+ float DoneTotalMod = donePctTotal ? *donePctTotal : SpellDamagePctDone(victim, spellProto, damagetype);
// done scripted mod (take it from owner)
Unit const* owner = GetOwner() ? GetOwner() : this;
- AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
+ DoneTotal += owner->GetTotalAuraModifier(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS, [spellProto](AuraEffect const* aurEff) -> bool
{
- if (!(*i)->IsAffectedOnSpell(spellProto))
- continue;
+ if (!aurEff->IsAffectedOnSpell(spellProto))
+ return false;
- switch ((*i)->GetMiscValue())
+ switch (aurEff->GetMiscValue())
{
case 4418: // Increased Shock Damage
case 4554: // Increased Lightning Damage
@@ -6682,12 +6721,17 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
case 5148: // Idol of the Shooting Star
case 6008: // Increased Lightning Damage
case 8627: // Totem of Hex
- {
- DoneTotal += (*i)->GetAmount();
+ return true;
+ default:
break;
- }
}
- }
+
+ return false;
+ });
+
+ // Some spells don't benefit from pct done mods
+ if (!spellProto->HasAttribute(SPELL_ATTR6_LIMIT_PCT_DAMAGE_MODS))
+ DoneTotal += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS, victim->GetCreatureTypeMask());
// Custom scripted damage
switch (spellProto->SpellFamilyName)
@@ -6711,7 +6755,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
case 49638:
if (SpellInfo const* proto = sSpellMgr->GetSpellInfo(itr->first))
AddPct(ApCoeffMod, proto->Effects[EFFECT_0].CalcValue());
- break;
+ break;
}
}
}
@@ -6765,18 +6809,11 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
}
- float tmpDamage = (int32(pdamage) + DoneTotal);
+ float tmpDamage = float(int32(pdamage) + DoneTotal) * DoneTotalMod;
- // DOTs calculated in AuraEffect::PeriodicDamageAurasTick
- // Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods.
- if (damagetype != DOT)
- {
- tmpDamage *= SpellDamagePctDone(victim, spellProto, damagetype);
-
- // apply spellmod to Done damage (flat and pct)
- if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, tmpDamage);
- }
+ // apply spellmod to Done damage (flat and pct)
+ if (Player* modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
return uint32(std::max(tmpDamage, 0.0f));
}
@@ -6786,13 +6823,18 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage
if (!spellProto || !victim || damagetype == DIRECT_DAMAGE)
return 1.0f;
+ // Some spells don't benefit from done mods
+ if (spellProto->HasAttribute(SPELL_ATTR3_NO_DONE_BONUS))
+ return 1.0f;
+
// Some spells don't benefit from pct done mods
if (spellProto->HasAttribute(SPELL_ATTR6_LIMIT_PCT_DAMAGE_MODS))
return 1.0f;
- // For totems pct done mods are calculated when its calculation is run on the player in SpellDamageBonusDone.
+ // For totems get damage bonus from owner
if (GetTypeId() == TYPEID_UNIT && IsTotem())
- return 1.0f;
+ if (Unit* owner = GetOwner())
+ return owner->SpellDamagePctDone(victim, spellProto, damagetype);
// Done total percent damage auras
float DoneTotalMod = 1.0f;
@@ -7221,94 +7263,84 @@ int32 Unit::SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const
return GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, schoolMask);
}
-bool Unit::IsSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType /*= BASE_ATTACK*/) const
+float Unit::SpellCritChanceDone(SpellInfo const* spellInfo, SpellSchoolMask schoolMask, WeaponAttackType attackType /*= BASE_ATTACK*/) const
{
- return roll_chance_f(GetUnitSpellCriticalChance(victim, spellProto, schoolMask, attackType));
-}
-
-float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType /*= BASE_ATTACK*/) const
-{
- //! Mobs can't crit with spells. Player Totems can
- //! Fire Elemental (from totem) can too - but this part is a hack and needs more research
- if (GetGUID().IsCreatureOrVehicle() && !(IsTotem() && GetOwnerGUID().IsPlayer()) && GetEntry() != 15438)
+ //! Mobs can't crit with spells. (Except player controlled)
+ if (GetTypeId() == TYPEID_UNIT && !GetSpellModOwner())
return 0.0f;
// not critting spell
- if (spellProto->HasAttribute(SPELL_ATTR2_CANT_CRIT))
+ if (spellInfo->HasAttribute(SPELL_ATTR2_CANT_CRIT))
return 0.0f;
float crit_chance = 0.0f;
- switch (spellProto->DmgClass)
+ switch (spellInfo->DmgClass)
{
- case SPELL_DAMAGE_CLASS_NONE:
- // We need more spells to find a general way (if there is any)
- switch (spellProto->Id)
- {
- case 379: // Earth Shield
- case 33778: // Lifebloom Final Bloom
- case 64844: // Divine Hymn
- case 71607: // Item - Bauble of True Blood 10m
- case 71646: // Item - Bauble of True Blood 25m
- break;
- default:
- return 0.0f;
- }
- // Do not add a break here, case fallthrough is intentional! Adding a break will make above spells unable to crit.
case SPELL_DAMAGE_CLASS_MAGIC:
{
if (schoolMask & SPELL_SCHOOL_MASK_NORMAL)
crit_chance = 0.0f;
// For other schools
else if (GetTypeId() == TYPEID_PLAYER)
- {
crit_chance = GetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1 + GetFirstSchoolInMask(schoolMask));
-
- // register aura mod, this is needed for Arcane Potency
- if (Spell* spell = ToPlayer()->m_spellModTakingSpell)
- {
- std::vector<Aura*> affectingAuras;
- (void)GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE, [&affectingAuras](AuraEffect const* aurEff) -> bool
- {
- affectingAuras.push_back(aurEff->GetBase());
- return true;
- });
-
- (void)GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, [&affectingAuras, schoolMask](AuraEffect const* aurEff) -> bool
- {
- if ((aurEff->GetMiscValue() & schoolMask) != 0)
- {
- affectingAuras.push_back(aurEff->GetBase());
- return true;
- }
-
- return false;
- });
-
- for (Aura* aura : affectingAuras)
- spell->m_appliedMods.insert(aura);
- }
- }
else
{
crit_chance = (float)m_baseSpellCritChance;
crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask);
}
+ break;
+ }
+ case SPELL_DAMAGE_CLASS_MELEE:
+ case SPELL_DAMAGE_CLASS_RANGED:
+ {
+ crit_chance += GetUnitCriticalChanceDone(attackType);
+ crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask);
+ break;
+ }
+ case SPELL_DAMAGE_CLASS_NONE:
+ default:
+ return 0.0f;
+ }
+ // percent done
+ // only players use intelligence for critical chance computations
+ if (Player* modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance);
+
+ return std::max(crit_chance, 0.0f);
+}
+
+float Unit::SpellCritChanceTaken(Unit const* caster, SpellInfo const* spellInfo, SpellSchoolMask schoolMask, float doneChance, WeaponAttackType attackType /*= BASE_ATTACK*/) const
+{
+ // not critting spell
+ if (spellInfo->HasAttribute(SPELL_ATTR2_CANT_CRIT))
+ return 0.0f;
+
+ float crit_chance = doneChance;
+ switch (spellInfo->DmgClass)
+ {
+ case SPELL_DAMAGE_CLASS_MAGIC:
+ {
// taken
- if (victim)
+ if (!spellInfo->IsPositive())
{
- if (!spellProto->IsPositive())
- {
- // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE
- crit_chance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE, schoolMask);
- // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE
- crit_chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE);
- ApplyResilience(victim, &crit_chance, nullptr, false, CR_CRIT_TAKEN_SPELL);
- }
- // scripted (increase crit chance ... against ... target by x%
- AuraEffectList const& mOverrideClassScript = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
+ // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE
+ crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE, schoolMask);
+
+ if (caster && caster->CanApplyResilience())
+ Unit::ApplyResilience(this, &crit_chance, nullptr, false, CR_CRIT_TAKEN_SPELL);
+
+ // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE
+ // applied after resilience
+ crit_chance += GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE);
+ }
+
+ // scripted (increase crit chance ... against ... target by x%
+ if (caster)
+ {
+ AuraEffectList const& mOverrideClassScript = caster->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for (AuraEffect const* aurEff : mOverrideClassScript)
{
- if (!aurEff->IsAffectedOnSpell(spellProto))
+ if (!aurEff->IsAffectedOnSpell(spellInfo))
continue;
float modChance = 0.f;
@@ -7320,18 +7352,18 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto
modChance += 17.f;
case 849: // Shatter (Rank 1)
modChance += 17.f;
- if (!victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
+ if (!HasAuraState(AURA_STATE_FROZEN, spellInfo, caster))
break;
crit_chance += modChance;
break;
case 7917: // Glyph of Shadowburn
- if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
+ if (HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellInfo, caster))
crit_chance += aurEff->GetAmount();
break;
case 7997: // Renewed Hope
case 7998:
- if (victim->HasAura(6788))
+ if (HasAura(6788))
crit_chance += aurEff->GetAmount();
break;
default:
@@ -7339,61 +7371,61 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto
}
}
// Custom crit by class
- switch (spellProto->SpellFamilyName)
+ switch (spellInfo->SpellFamilyName)
{
case SPELLFAMILY_MAGE:
// Glyph of Fire Blast
- if (spellProto->SpellFamilyFlags[0] == 0x2 && spellProto->SpellIconID == 12)
- if (victim->HasAuraWithMechanic((1 << MECHANIC_STUN) | (1 << MECHANIC_KNOCKOUT)))
- if (AuraEffect const* aurEff = GetAuraEffect(56369, EFFECT_0))
+ if (spellInfo->SpellFamilyFlags[0] == 0x2 && spellInfo->SpellIconID == 12)
+ if (HasAuraWithMechanic((1 << MECHANIC_STUN) | (1 << MECHANIC_KNOCKOUT)))
+ if (AuraEffect const* aurEff = caster->GetAuraEffect(56369, EFFECT_0))
crit_chance += aurEff->GetAmount();
break;
case SPELLFAMILY_DRUID:
// Improved Faerie Fire
- if (victim->HasAuraState(AURA_STATE_FAERIE_FIRE))
- if (AuraEffect const* aurEff = GetDummyAuraEffect(SPELLFAMILY_DRUID, 109, 0))
+ if (HasAuraState(AURA_STATE_FAERIE_FIRE))
+ if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 109, 0))
crit_chance += aurEff->GetAmount();
// cumulative effect - don't break
// Starfire
- if (spellProto->SpellFamilyFlags[0] & 0x4 && spellProto->SpellIconID == 1485)
+ if (spellInfo->SpellFamilyFlags[0] & 0x4 && spellInfo->SpellIconID == 1485)
{
// Improved Insect Swarm
- if (AuraEffect const* aurEff = GetDummyAuraEffect(SPELLFAMILY_DRUID, 1771, 0))
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00000002, 0, 0))
+ if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 1771, 0))
+ if (GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00000002, 0, 0))
crit_chance += aurEff->GetAmount();
- break;
+ break;
}
break;
case SPELLFAMILY_ROGUE:
// Shiv-applied poisons can't crit
- if (FindCurrentSpellBySpellId(5938))
+ if (caster->FindCurrentSpellBySpellId(5938))
crit_chance = 0.0f;
break;
case SPELLFAMILY_PALADIN:
// Flash of light
- if (spellProto->SpellFamilyFlags[0] & 0x40000000)
+ if (spellInfo->SpellFamilyFlags[0] & 0x40000000)
{
// Sacred Shield
- if (AuraEffect const* aura = victim->GetAuraEffect(58597, 1, GetGUID()))
+ if (AuraEffect const* aura = GetAuraEffect(58597, 1, GetGUID()))
crit_chance += aura->GetAmount();
break;
}
// Exorcism
- else if (spellProto->GetCategory() == 19)
+ else if (spellInfo->GetCategory() == 19)
{
- if (victim->GetCreatureTypeMask() & CREATURE_TYPEMASK_DEMON_OR_UNDEAD)
+ if (GetCreatureTypeMask() & CREATURE_TYPEMASK_DEMON_OR_UNDEAD)
return 100.0f;
break;
}
break;
case SPELLFAMILY_SHAMAN:
// Lava Burst
- if (spellProto->SpellFamilyFlags[1] & 0x00001000)
+ if (spellInfo->SpellFamilyFlags[1] & 0x00001000)
{
- if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0, 0, GetGUID()))
- if (victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE) > -100)
+ if (GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0, 0, GetGUID()))
+ if (GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE) > -100)
return 100.0f;
break;
}
@@ -7401,67 +7433,61 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto
}
// Spell crit suppression
- if (victim->GetTypeId() == TYPEID_UNIT)
+ if (GetTypeId() == TYPEID_UNIT)
{
- int32 const levelDiff = static_cast<int32>(victim->getLevelForTarget(this)) - getLevel();
+ int32 const levelDiff = static_cast<int32>(getLevelForTarget(caster)) - caster->getLevel();
crit_chance -= levelDiff * 0.7f;
}
}
break;
}
case SPELL_DAMAGE_CLASS_MELEE:
- if (victim)
+ {
+ // Custom crit by class
+ if (caster)
{
- // Custom crit by class
- switch (spellProto->SpellFamilyName)
+ switch (spellInfo->SpellFamilyName)
{
case SPELLFAMILY_DRUID:
// Rend and Tear - bonus crit chance for Ferocious Bite on bleeding targets
- if (spellProto->SpellFamilyFlags[0] & 0x00800000
- && spellProto->SpellIconID == 1680
- && victim->HasAuraState(AURA_STATE_BLEEDING))
+ if (spellInfo->SpellFamilyFlags[0] & 0x00800000
+ && spellInfo->SpellIconID == 1680
+ && HasAuraState(AURA_STATE_BLEEDING))
{
- if (AuraEffect const* rendAndTear = GetDummyAuraEffect(SPELLFAMILY_DRUID, 2859, 1))
+ if (AuraEffect const* rendAndTear = caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 2859, 1))
crit_chance += rendAndTear->GetAmount();
break;
}
break;
case SPELLFAMILY_WARRIOR:
// Victory Rush
- if (spellProto->SpellFamilyFlags[1] & 0x100)
+ if (spellInfo->SpellFamilyFlags[1] & 0x100)
{
// Glyph of Victory Rush
- if (AuraEffect const* aurEff = GetAuraEffect(58382, 0))
+ if (AuraEffect const* aurEff = caster->GetAuraEffect(58382, 0))
crit_chance += aurEff->GetAmount();
break;
}
break;
}
}
+ }
/// Intentional fallback. Calculate critical strike chance for both Ranged and Melee spells
case SPELL_DAMAGE_CLASS_RANGED:
- {
- if (victim)
- {
- crit_chance += GetUnitCriticalChance(attackType, victim);
- crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask);
- }
+ if (caster)
+ crit_chance = GetUnitCriticalChanceTaken(caster, attackType, crit_chance);
break;
- }
+ case SPELL_DAMAGE_CLASS_NONE:
default:
- return 0.0f;
+ return 0.f;
}
- // percent done
- // only players use intelligence for critical chance computations
- if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance);
// for this types the bonus was already added in GetUnitCriticalChance, do not add twice
- if (spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE && spellProto->DmgClass != SPELL_DAMAGE_CLASS_RANGED)
+ if (caster && spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE && spellInfo->DmgClass != SPELL_DAMAGE_CLASS_RANGED)
{
- crit_chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER, [this, spellProto](AuraEffect const* aurEff) -> bool
+ crit_chance += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER, [caster, spellInfo](AuraEffect const* aurEff) -> bool
{
- if (aurEff->GetCasterGUID() == GetGUID() && aurEff->IsAffectedOnSpell(spellProto))
+ if (aurEff->GetCasterGUID() == caster->GetGUID() && aurEff->IsAffectedOnSpell(spellInfo))
return true;
return false;
});
@@ -7470,7 +7496,7 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto
return std::max(crit_chance, 0.0f);
}
-uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim)
+/*static*/ uint32 Unit::SpellCriticalDamageBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit* victim)
{
// Calculate critical bonus
int32 crit_bonus = damage;
@@ -7488,29 +7514,32 @@ uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage
break;
}
- crit_mod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellProto->GetSchoolMask()) - 1.0f) * 100;
+ if (caster)
+ {
+ crit_mod += (caster->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellProto->GetSchoolMask()) - 1.0f) * 100;
- if (victim)
- crit_mod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, victim->GetCreatureTypeMask());
+ if (victim)
+ crit_mod += caster->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, victim->GetCreatureTypeMask());
- if (crit_bonus != 0)
- AddPct(crit_bonus, crit_mod);
+ if (crit_bonus != 0)
+ AddPct(crit_bonus, crit_mod);
- crit_bonus -= damage;
+ crit_bonus -= damage;
- if (damage > uint32(crit_bonus))
- {
- // adds additional damage to critBonus (from talents)
- if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
- }
+ if (damage > uint32(crit_bonus))
+ {
+ // adds additional damage to critBonus (from talents)
+ if (Player* modOwner = caster->GetSpellModOwner())
+ modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
+ }
- crit_bonus += damage;
+ crit_bonus += damage;
+ }
return crit_bonus;
}
-uint32 Unit::SpellCriticalHealingBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim)
+/*static*/ uint32 Unit::SpellCriticalHealingBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit* victim)
{
// Calculate critical bonus
int32 crit_bonus;
@@ -7526,26 +7555,30 @@ uint32 Unit::SpellCriticalHealingBonus(SpellInfo const* spellProto, uint32 damag
break;
}
- if (victim)
+ if (caster)
{
- uint32 creatureTypeMask = victim->GetCreatureTypeMask();
- crit_bonus = int32(crit_bonus * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask));
+ if (victim)
+ {
+ uint32 creatureTypeMask = victim->GetCreatureTypeMask();
+ crit_bonus = int32(crit_bonus * caster->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask));
+ }
}
if (crit_bonus > 0)
damage += crit_bonus;
- damage = int32(float(damage) * GetTotalAuraMultiplier(SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT));
+ if (caster)
+ damage = int32(float(damage) * caster->GetTotalAuraMultiplier(SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT));
return damage;
}
-uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack) const
+uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, Optional<float> const& donePctTotal, uint32 stack /*= 1*/) const
{
// For totems get healing bonus from owner (statue isn't totem in fact)
if (GetTypeId() == TYPEID_UNIT && IsTotem())
if (Unit* owner = GetOwner())
- return owner->SpellHealingBonusDone(victim, spellProto, healamount, damagetype, stack);
+ return owner->SpellHealingBonusDone(victim, spellProto, healamount, damagetype, donePctTotal, stack);
// No bonus healing for potion spells
if (spellProto->SpellFamilyName == SPELLFAMILY_POTION)
@@ -7553,20 +7586,22 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
float ApCoeffMod = 1.0f;
int32 DoneTotal = 0;
+ float DoneTotalMod = donePctTotal ? *donePctTotal : SpellHealingPctDone(victim, spellProto);
// done scripted mod (take it from owner)
Unit const* owner = GetOwner() ? GetOwner() : this;
AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
+ for (AuraEffect const* aurEff : mOverrideClassScript)
{
- if (!(*i)->IsAffectedOnSpell(spellProto))
+ if (!aurEff->IsAffectedOnSpell(spellProto))
continue;
- switch ((*i)->GetMiscValue())
+
+ switch (aurEff->GetMiscValue())
{
case 4415: // Increased Rejuvenation Healing
case 4953:
case 3736: // Hateful Totem of the Third Wind / Increased Lesser Healing Wave / LK Arena (4/5/6) Totem of the Third Wind / Savage Totem of the Third Wind
- DoneTotal += (*i)->GetAmount();
+ DoneTotal += aurEff->GetAmount();
break;
default:
break;
@@ -7669,26 +7704,28 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
DoneTotal = 0;
}
- float heal = float(int32(healamount) + DoneTotal);
+ float heal = float(int32(healamount) + DoneTotal) * DoneTotalMod;
- // DOTs calculated in AuraEffect::HandlePeriodicHealAurasTick
- // Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods.
- if (damagetype != DOT)
- {
- heal *= SpellHealingPctDone(victim, spellProto);
-
- // apply spellmod to Done amount
- if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, heal);
- }
+ // apply spellmod to Done amount
+ if (Player* modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal);
return uint32(std::max(heal, 0.0f));
}
float Unit::SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const
{
- // For totems pct done mods are calculated when its calculation is run on the player in SpellHealingBonusDone.
+ // For totems get healing bonus from owner
if (GetTypeId() == TYPEID_UNIT && IsTotem())
+ if (Unit* owner = GetOwner())
+ return owner->SpellHealingPctDone(victim, spellProto);
+
+ // Some spells don't benefit from done mods
+ if (spellProto->HasAttribute(SPELL_ATTR3_NO_DONE_BONUS))
+ return 1.0f;
+
+ // Some spells don't benefit from done mods
+ if (spellProto->HasAttribute(SPELL_ATTR6_LIMIT_PCT_HEALING_MODS))
return 1.0f;
// No bonus healing for potion spells
@@ -7703,27 +7740,28 @@ float Unit::SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const
// done scripted mod (take it from owner)
Unit const* owner = GetOwner() ? GetOwner() : this;
AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
+ for (AuraEffect const* aurEff : mOverrideClassScript)
{
- if (!(*i)->IsAffectedOnSpell(spellProto))
+ if (!aurEff->IsAffectedOnSpell(spellProto))
continue;
- switch ((*i)->GetMiscValue())
+
+ switch (aurEff->GetMiscValue())
{
case 21: // Test of Faith
case 6935:
case 6918:
if (victim->HealthBelowPct(50))
- AddPct(DoneTotalMod, (*i)->GetAmount());
+ AddPct(DoneTotalMod, aurEff->GetAmount());
break;
case 7798: // Glyph of Regrowth
{
if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40, 0, 0))
- AddPct(DoneTotalMod, (*i)->GetAmount());
+ AddPct(DoneTotalMod, aurEff->GetAmount());
break;
}
case 8477: // Nourish Heal Boost
{
- int32 stepPercent = (*i)->GetAmount();
+ int32 stepPercent = aurEff->GetAmount();
int32 modPercent = 0;
AuraApplicationMap const& victimAuras = victim->GetAppliedAuras();
for (AuraApplicationMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
@@ -7731,6 +7769,7 @@ float Unit::SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const
Aura const* aura = itr->second->GetBase();
if (aura->GetCasterGUID() != GetGUID())
continue;
+
SpellInfo const* m_spell = aura->GetSpellInfo();
if (m_spell->SpellFamilyName != SPELLFAMILY_DRUID ||
!(m_spell->SpellFamilyFlags[1] & 0x00000010 || m_spell->SpellFamilyFlags[0] & 0x50))
@@ -7742,8 +7781,8 @@ float Unit::SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const
}
case 7871: // Glyph of Lesser Healing Wave
{
- if (victim->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0, 0x00000400, 0, GetGUID()))
- AddPct(DoneTotalMod, (*i)->GetAmount());
+ if (victim->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0, 0x00000400, 0))
+ AddPct(DoneTotalMod, aurEff->GetAmount());
break;
}
default:
@@ -11591,14 +11630,20 @@ bool Unit::InitTamedPet(Pet* pet, uint8 level, uint32 spell_id)
return true;
}
-void Unit::Kill(Unit* victim, bool durabilityLoss)
+/*static*/ void Unit::Kill(Unit* attacker, Unit* victim, bool durabilityLoss /*= true*/)
{
// Prevent killing unit twice (and giving reward from kill twice)
if (!victim->GetHealth())
return;
+ if (attacker && !attacker->IsInMap(victim))
+ attacker = nullptr;
+
// find player: owner of controlled `this` or `this` itself maybe
- Player* player = GetCharmerOrOwnerPlayerOrPlayerItself();
+ Player* player = nullptr;
+ if (attacker)
+ player = attacker->GetCharmerOrOwnerPlayerOrPlayerItself();
+
Creature* creature = victim->ToCreature();
bool isRewardAllowed = true;
@@ -11689,48 +11734,44 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
}
// Do KILL and KILLED procs. KILL proc is called only for the unit who landed the killing blow (and its owner - for pets and totems) regardless of who tapped the victim
- if (IsPet() || IsTotem())
+ if (attacker && (attacker->IsPet() || attacker->IsTotem()))
{
// proc only once for victim
- if (Unit* owner = GetOwner())
- owner->ProcSkillsAndAuras(victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr);
+ if (Unit* owner = attacker->GetOwner())
+ Unit::ProcSkillsAndAuras(owner, victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr);
}
if (!victim->IsCritter())
- ProcSkillsAndAuras(victim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr);
+ Unit::ProcSkillsAndAuras(attacker, victim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr);
// Proc auras on death - must be before aura/combat remove
- victim->ProcSkillsAndAuras(victim, PROC_FLAG_NONE, PROC_FLAG_DEATH, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr);
+ Unit::ProcSkillsAndAuras(victim, victim, PROC_FLAG_NONE, PROC_FLAG_DEATH, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr);
// update get killing blow achievements, must be done before setDeathState to be able to require auras on target
// and before Spirit of Redemption as it also removes auras
- if (Player* killerPlayer = GetCharmerOrOwnerPlayerOrPlayerItself())
- killerPlayer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, victim);
+ if (attacker)
+ if (Player* killerPlayer = attacker->GetCharmerOrOwnerPlayerOrPlayerItself())
+ killerPlayer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, victim);
+ // Spirit of Redemption
// if talent known but not triggered (check priest class for speedup check)
bool spiritOfRedemption = false;
if (victim->GetTypeId() == TYPEID_PLAYER && victim->getClass() == CLASS_PRIEST)
{
- AuraEffectList const& dummyAuras = victim->GetAuraEffectsByType(SPELL_AURA_DUMMY);
- for (AuraEffectList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
+ if (AuraEffect const* aurEff = victim->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 1654, EFFECT_0))
{
- if ((*itr)->GetSpellInfo()->SpellIconID == 1654)
- {
- AuraEffect const* aurEff = *itr;
- // save value before aura remove
- uint32 ressSpellId = victim->GetUInt32Value(PLAYER_SELF_RES_SPELL);
- if (!ressSpellId)
- ressSpellId = victim->ToPlayer()->GetResurrectionSpellId();
- // Remove all expected to remove at death auras (most important negative case like DoT or periodic triggers)
- victim->RemoveAllAurasOnDeath();
- // restore for use at real death
- victim->SetUInt32Value(PLAYER_SELF_RES_SPELL, ressSpellId);
+ // save value before aura remove
+ uint32 ressSpellId = victim->GetUInt32Value(PLAYER_SELF_RES_SPELL);
+ if (!ressSpellId)
+ ressSpellId = victim->ToPlayer()->GetResurrectionSpellId();
+ // Remove all expected to remove at death auras (most important negative case like DoT or periodic triggers)
+ victim->RemoveAllAurasOnDeath();
+ // restore for use at real death
+ victim->SetUInt32Value(PLAYER_SELF_RES_SPELL, ressSpellId);
- // FORM_SPIRITOFREDEMPTION and related auras
- victim->CastSpell(victim, 27827, aurEff);
- spiritOfRedemption = true;
- break;
- }
+ // FORM_SPIRITOFREDEMPTION and related auras
+ victim->CastSpell(victim, 27827, aurEff);
+ spiritOfRedemption = true;
}
}
@@ -11767,8 +11808,8 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
plrVictim->SendDirectMessage(&data);
}
// Call KilledUnit for creatures
- if (GetTypeId() == TYPEID_UNIT && IsAIEnabled)
- ToCreature()->AI()->KilledUnit(victim);
+ if (attacker && attacker->GetTypeId() == TYPEID_UNIT && attacker->IsAIEnabled)
+ attacker->ToCreature()->AI()->KilledUnit(victim);
// last damage from non duel opponent or opponent controlled creature
if (plrVictim->duel)
@@ -11794,31 +11835,30 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
}
// Call KilledUnit for creatures, this needs to be called after the lootable flag is set
- if (GetTypeId() == TYPEID_UNIT && IsAIEnabled)
- ToCreature()->AI()->KilledUnit(victim);
+ if (attacker && attacker->GetTypeId() == TYPEID_UNIT && attacker->IsAIEnabled)
+ attacker->ToCreature()->AI()->KilledUnit(victim);
// Call creature just died function
if (creature->IsAIEnabled)
- creature->AI()->JustDied(this);
+ creature->AI()->JustDied(attacker);
if (TempSummon* summon = creature->ToTempSummon())
if (Unit* summoner = summon->GetSummoner())
if (summoner->ToCreature() && summoner->IsAIEnabled)
- summoner->ToCreature()->AI()->SummonedCreatureDies(creature, this);
+ summoner->ToCreature()->AI()->SummonedCreatureDies(creature, attacker);
// Dungeon specific stuff, only applies to players killing creatures
if (creature->GetInstanceId())
{
Map* instanceMap = creature->GetMap();
- Player* creditedPlayer = GetCharmerOrOwnerPlayerOrPlayerItself();
- /// @todo do instance binding anyway if the charmer/owner is offline
- if (instanceMap->IsDungeon() && (creditedPlayer || this == victim))
+ /// @todo do instance binding anyway if the charmer/owner is offline
+ if (instanceMap->IsDungeon() && ((attacker && attacker->GetCharmerOrOwnerPlayerOrPlayerItself()) || attacker == victim))
{
if (instanceMap->IsRaidOrHeroicDungeon())
{
if (creature->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
- ((InstanceMap*)instanceMap)->PermBindAllPlayers();
+ instanceMap->ToInstanceMap()->PermBindAllPlayers();
}
else
{
@@ -11835,7 +11875,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
// outdoor pvp things, do these after setting the death state, else the player activity notify won't work... doh...
// handle player kill only if not suicide (spirit of redemption for example)
- if (player && this != victim)
+ if (player && attacker != victim)
{
if (OutdoorPvP* pvp = player->GetOutdoorPvP())
pvp->HandleKill(player, victim);
@@ -11861,26 +11901,29 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
}
// achievement stuff
- if (victim->GetTypeId() == TYPEID_PLAYER)
+ if (attacker && victim->GetTypeId() == TYPEID_PLAYER)
{
- if (GetTypeId() == TYPEID_UNIT)
- victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry());
- else if (GetTypeId() == TYPEID_PLAYER && victim != this)
- victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1, ToPlayer()->GetTeam());
+ if (attacker->GetTypeId() == TYPEID_UNIT)
+ victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, attacker->GetEntry());
+ else if (attacker->GetTypeId() == TYPEID_PLAYER && victim != attacker)
+ victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1, attacker->ToPlayer()->GetTeam());
}
// Hook for OnPVPKill Event
- if (Player* killerPlr = ToPlayer())
- {
- if (Player* killedPlr = victim->ToPlayer())
- sScriptMgr->OnPVPKill(killerPlr, killedPlr);
- else if (Creature* killedCre = victim->ToCreature())
- sScriptMgr->OnCreatureKill(killerPlr, killedCre);
- }
- else if (Creature* killerCre = ToCreature())
+ if (attacker)
{
- if (Player* killed = victim->ToPlayer())
- sScriptMgr->OnPlayerKilledByCreature(killerCre, killed);
+ if (Player* killerPlr = attacker->ToPlayer())
+ {
+ if (Player* killedPlr = victim->ToPlayer())
+ sScriptMgr->OnPVPKill(killerPlr, killedPlr);
+ else if (Creature* killedCre = victim->ToCreature())
+ sScriptMgr->OnCreatureKill(killerPlr, killedCre);
+ }
+ else if (Creature* killerCre = attacker->ToCreature())
+ {
+ if (Player* killed = victim->ToPlayer())
+ sScriptMgr->OnPlayerKilledByCreature(killerCre, killed);
+ }
}
}
@@ -12649,23 +12692,26 @@ void Unit::SendPlaySpellImpact(ObjectGuid guid, uint32 id)
SendMessageToSet(&data, false);
}
-void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool isCrit, CombatRating type) const
+bool Unit::CanApplyResilience() const
+{
+ return !IsVehicle() && GetOwnerGUID().IsPlayer();
+}
+
+/*static*/ void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool isCrit, CombatRating type)
{
// player mounted on multi-passenger mount is also classified as vehicle
- if (IsVehicle() || (victim->IsVehicle() && victim->GetTypeId() != TYPEID_PLAYER))
+ if (victim->IsVehicle() && victim->GetTypeId() != TYPEID_PLAYER)
return;
- Unit const* source = nullptr;
- if (GetTypeId() == TYPEID_PLAYER)
- source = this;
- else if (GetTypeId() == TYPEID_UNIT && GetOwner() && GetOwner()->GetTypeId() == TYPEID_PLAYER)
- source = GetOwner();
-
Unit const* target = nullptr;
if (victim->GetTypeId() == TYPEID_PLAYER)
target = victim;
- else if (victim->GetTypeId() == TYPEID_UNIT && victim->GetOwner() && victim->GetOwner()->GetTypeId() == TYPEID_PLAYER)
- target = victim->GetOwner();
+ else // victim->GetTypeId() == TYPEID_UNIT
+ {
+ if (Unit* owner = victim->GetOwner())
+ if (owner->GetTypeId() == TYPEID_PLAYER)
+ target = owner;
+ }
if (!target)
return;
@@ -12676,7 +12722,7 @@ void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool
// Crit chance reduction works against nonpets
if (crit)
*crit -= target->GetMeleeCritChanceReduction();
- if (source && damage)
+ if (damage)
{
if (isCrit)
*damage -= target->GetMeleeCritDamageReduction(*damage);
@@ -12687,7 +12733,7 @@ void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool
// Crit chance reduction works against nonpets
if (crit)
*crit -= target->GetRangedCritChanceReduction();
- if (source && damage)
+ if (damage)
{
if (isCrit)
*damage -= target->GetRangedCritDamageReduction(*damage);
@@ -12698,7 +12744,7 @@ void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool
// Crit chance reduction works against nonpets
if (crit)
*crit -= target->GetSpellCritChanceReduction();
- if (source && damage)
+ if (damage)
{
if (isCrit)
*damage -= target->GetSpellCritDamageReduction(*damage);
@@ -12710,6 +12756,15 @@ void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool
}
}
+int32 Unit::CalculateAOEAvoidance(int32 damage, uint32 schoolMask, Unit* caster) const
+{
+ damage = int32(float(damage) * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, schoolMask));
+ if (caster->GetTypeId() == TYPEID_UNIT)
+ damage = int32(float(damage) * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, schoolMask));
+
+ return damage;
+}
+
// Melee based spells can be miss, parry or dodge on this step
// Crit or block - determined on damage calculation phase! (and can be both in some time)
float Unit::MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 6adf01b367c..407168b4dab 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -846,7 +846,7 @@ class TC_GAME_API Unit : public WorldObject
uint32 GetResistance(SpellSchools school) const { return GetUInt32Value(UNIT_FIELD_RESISTANCES+school); }
uint32 GetResistance(SpellSchoolMask mask) const;
void SetResistance(SpellSchools school, int32 val) { SetStatInt32Value(UNIT_FIELD_RESISTANCES+school, val); }
- float CalculateAverageResistReduction(SpellSchoolMask schoolMask, Unit const* victim, SpellInfo const* spellInfo = nullptr) const;
+ static float CalculateAverageResistReduction(Unit const* attacker, SpellSchoolMask schoolMask, Unit const* victim, SpellInfo const* spellInfo = nullptr);
uint32 GetHealth() const { return GetUInt32Value(UNIT_FIELD_HEALTH); }
uint32 GetMaxHealth() const { return GetUInt32Value(UNIT_FIELD_MAXHEALTH); }
@@ -921,13 +921,13 @@ class TC_GAME_API Unit : public WorldObject
void Dismount();
uint32 GetMaxSkillValueForLevel(Unit const* target = nullptr) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
- void DealDamageMods(Unit const* victim, uint32 &damage, uint32* absorb) const;
- uint32 DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage = nullptr, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = nullptr, bool durabilityLoss = true);
- void Kill(Unit* victim, bool durabilityLoss = true);
- void KillSelf(bool durabilityLoss = true) { Kill(this, durabilityLoss); }
- void DealHeal(HealInfo& healInfo);
+ static void DealDamageMods(Unit const* victim, uint32& damage, uint32* absorb);
+ static uint32 DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage = nullptr, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = nullptr, bool durabilityLoss = true);
+ static void Kill(Unit* attacker, Unit* victim, bool durabilityLoss = true);
+ void KillSelf(bool durabilityLoss = true) { Unit::Kill(this, this, durabilityLoss); }
+ static void DealHeal(HealInfo& healInfo);
- void ProcSkillsAndAuras(Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget,
+ static void ProcSkillsAndAuras(Unit* actor, Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget,
uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell,
DamageInfo* damageInfo, HealInfo* healInfo);
@@ -964,7 +964,10 @@ class TC_GAME_API Unit : public WorldObject
uint32 GetRangedDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_RANGED, 2.0f, 100.0f, damage); }
uint32 GetSpellDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_CRIT_TAKEN_SPELL, 2.0f, 100.0f, damage); }
- void ApplyResilience(Unit const* victim, float* crit, int32* damage, bool isCrit, CombatRating type) const;
+ virtual bool CanApplyResilience() const;
+ static void ApplyResilience(Unit const* victim, float* crit, int32* damage, bool isCrit, CombatRating type);
+
+ int32 CalculateAOEAvoidance(int32 damage, uint32 schoolMask, Unit* caster) const;
float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const;
SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo) const;
@@ -975,7 +978,9 @@ class TC_GAME_API Unit : public WorldObject
float GetUnitParryChance(WeaponAttackType attType, Unit const* victim) const;
float GetUnitBlockChance(WeaponAttackType attType, Unit const* victim) const;
float GetUnitMissChance(WeaponAttackType attType) const;
- float GetUnitCriticalChance(WeaponAttackType attackType, Unit const* victim) const;
+ float GetUnitCriticalChanceDone(WeaponAttackType attackType) const;
+ float GetUnitCriticalChanceTaken(Unit const* attacker, WeaponAttackType attackType, float critDone) const;
+ float GetUnitCriticalChanceAgainst(WeaponAttackType attackType, Unit const* victim) const;
int32 GetMechanicResistChance(SpellInfo const* spellInfo) const;
bool CanUseAttackType(uint8 attacktype) const;
@@ -1500,12 +1505,12 @@ class TC_GAME_API Unit : public WorldObject
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const;
int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const;
- uint32 SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1) const;
+ uint32 SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, Optional<float> const& donePctTotal, uint32 stack = 1) const;
float SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype) const;
uint32 SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1) const;
int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const;
int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) const;
- uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1) const;
+ uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, Optional<float> const& donePctTotal, uint32 stack = 1) const;
float SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const;
uint32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1) const;
@@ -1514,10 +1519,10 @@ class TC_GAME_API Unit : public WorldObject
bool isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType = BASE_ATTACK);
bool isBlockCritical();
- bool IsSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const;
- float GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const;
- uint32 SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim);
- uint32 SpellCriticalHealingBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim);
+ float SpellCritChanceDone(SpellInfo const* spellInfo, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const;
+ float SpellCritChanceTaken(Unit const* caster, SpellInfo const* spellInfo, SpellSchoolMask schoolMask, float doneChance, WeaponAttackType attackType = BASE_ATTACK) const;
+ static uint32 SpellCriticalDamageBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit* victim);
+ static uint32 SpellCriticalHealingBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit* victim);
void SetLastManaUse(uint32 spellCastTime) { m_lastManaUse = spellCastTime; }
bool IsUnderLastManaUseEffect() const;
@@ -1538,10 +1543,10 @@ class TC_GAME_API Unit : public WorldObject
virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit* caster) const; // redefined in Creature
static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = nullptr, int8 effIndex = -1);
- uint32 CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK) const;
- uint32 CalcSpellResistedDamage(Unit* victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const* spellInfo) const;
- void CalcAbsorbResist(DamageInfo& damageInfo);
- void CalcHealAbsorb(HealInfo& healInfo) const;
+ static uint32 CalcArmorReducedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellInfo const* spellInfo, uint8 attackerLevel = 0, WeaponAttackType attackType = MAX_ATTACK);
+ static uint32 CalcSpellResistedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const* spellInfo);
+ static void CalcAbsorbResist(DamageInfo& damageInfo);
+ static void CalcHealAbsorb(HealInfo& healInfo);
void UpdateSpeed(UnitMoveType mtype);
float GetSpeed(UnitMoveType mtype) const;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 58266fc3559..f093b2cc508 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -381,13 +381,12 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* caster):
m_base(base), m_spellInfo(base->GetSpellInfo()),
m_baseAmount(baseAmount ? *baseAmount : m_spellInfo->Effects[effIndex].BasePoints),
-m_bonusAmount(0), m_critChance(0.0f), m_donePct(1.0f),
-m_spellmod(nullptr), _periodicTimer(0), _amplitude(0), _ticksDone(0), m_effIndex(effIndex),
+_amount(), m_spellmod(nullptr), _periodicTimer(0), _amplitude(0), _ticksDone(0), m_effIndex(effIndex),
m_canBeRecalculated(true), m_isPeriodic(false)
{
CalculatePeriodic(caster, true, false);
- m_amount = CalculateAmount(caster);
+ _amount = CalculateAmount(caster);
CalculateSpellMod();
}
@@ -493,6 +492,24 @@ int32 AuraEffect::CalculateAmount(Unit* caster)
break;
}
+ if (caster)
+ {
+ switch (GetAuraType())
+ {
+ case SPELL_AURA_PERIODIC_DAMAGE:
+ case SPELL_AURA_PERIODIC_LEECH:
+ if (GetBase()->GetType() == UNIT_AURA_TYPE)
+ amount = caster->SpellDamageBonusDone(GetBase()->GetUnitOwner(), GetSpellInfo(), amount, DOT, GetBase()->GetDonePct());
+ break;
+ case SPELL_AURA_PERIODIC_HEAL:
+ if (GetBase()->GetType() == UNIT_AURA_TYPE)
+ amount = caster->SpellHealingBonusDone(GetBase()->GetUnitOwner(), GetSpellInfo(), amount, DOT, GetBase()->GetDonePct());
+ break;
+ default:
+ break;
+ }
+ }
+
GetBase()->CallScriptEffectCalcAmountHandlers(this, amount, m_canBeRecalculated);
amount *= GetBase()->GetStackAmount();
return amount;
@@ -643,7 +660,7 @@ void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply)
if (handleMask & AURA_EFFECT_HANDLE_CHANGE_AMOUNT)
{
if (!mark)
- m_amount = newAmount;
+ _amount = newAmount;
else
SetAmount(newAmount);
CalculateSpellMod();
@@ -799,17 +816,9 @@ void AuraEffect::Update(uint32 diff, Unit* caster)
}
}
-bool AuraEffect::CanPeriodicTickCrit(Unit const* caster) const
+float AuraEffect::GetCritChanceFor(Unit const* caster, Unit const* target) const
{
- ASSERT(caster);
- if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_ABILITY_PERIODIC_CRIT, m_spellInfo))
- return true;
-
- // Rupture - since 3.3.3 can crit
- if (m_spellInfo->SpellIconID == 500 && m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
- return true;
-
- return false;
+ return target->SpellCritChanceTaken(caster, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), GetBase()->GetCritChance(), GetSpellInfo()->GetAttackType());
}
bool AuraEffect::IsAffectedOnSpell(SpellInfo const* spell) const
@@ -2942,7 +2951,7 @@ void AuraEffect::HandleAuraControlVehicle(AuraApplication const* aurApp, uint8 m
// so this break such spells or most of them.
// Current formula about m_amount: effect base points + dieside - 1
// TO DO: Reasearch more about 0/0 and fix it.
- caster->_EnterVehicle(target->GetVehicleKit(), m_amount - 1, aurApp);
+ caster->_EnterVehicle(target->GetVehicleKit(), GetAmount() - 1, aurApp);
}
else
{
@@ -2951,7 +2960,7 @@ void AuraEffect::HandleAuraControlVehicle(AuraApplication const* aurApp, uint8 m
if (GetId() == 53111) // Devour Humanoid
{
- target->Kill(caster);
+ Unit::Kill(target, caster);
if (caster->GetTypeId() == TYPEID_UNIT)
caster->ToCreature()->DespawnOrUnsummon();
}
@@ -3381,7 +3390,7 @@ void AuraEffect::HandleModPercentStat(AuraApplication const* aurApp, uint8 mode,
if (GetMiscValue() == i || GetMiscValue() == -1)
{
if (apply)
- target->ApplyStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount));
+ target->ApplyStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(GetAmount()));
else
{
float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_PERCENT_STAT, [i](AuraEffect const* aurEff) -> bool
@@ -3930,7 +3939,7 @@ void AuraEffect::HandleModCombatSpeedPct(AuraApplication const* aurApp, uint8 mo
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply);
target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(spellGroupVal), !apply);
}
- target->ApplyCastTimePercentMod(float(m_amount), apply);
+ target->ApplyCastTimePercentMod(float(GetAmount()), apply);
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply);
target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(GetAmount()), apply);
@@ -4708,7 +4717,7 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod
//Adding items
uint32 noSpaceForCount = 0;
- uint32 count = m_amount;
+ uint32 count = GetAmount();
ItemPosCountVec dest;
InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellInfo()->Effects[m_effIndex].ItemType, count, &noSpaceForCount);
@@ -4756,7 +4765,7 @@ void AuraEffect::HandleForceReaction(AuraApplication const* aurApp, uint8 mode,
return;
uint32 factionId = GetMiscValue();
- ReputationRank factionRank = ReputationRank(m_amount);
+ ReputationRank factionRank = ReputationRank(GetAmount());
player->GetReputationMgr().ApplyForceReaction(factionId, factionRank, apply);
player->GetReputationMgr().SendForceReactions();
@@ -4836,7 +4845,7 @@ void AuraEffect::HandleAuraConvertRune(AuraApplication const* aurApp, uint8 mode
if (player->getClass() != CLASS_DEATH_KNIGHT)
return;
- uint32 runes = m_amount;
+ uint32 runes = GetAmount();
// convert number of runes specified in aura amount of rune type in miscvalue to runetype in miscvalueb
if (apply)
{
@@ -5060,7 +5069,10 @@ void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit*
void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
{
- if (!caster || !target->IsAlive())
+ // dynobj auras must always have a caster
+ ASSERT(GetSpellInfo()->Effects[GetEffIndex()].Effect != SPELL_EFFECT_PERSISTENT_AREA_AURA || caster);
+
+ if (!target->IsAlive())
return;
if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo()))
@@ -5076,104 +5088,100 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- // AOE spells are not affected by the new periodic system.
- bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA);
// ignore negative values (can be result apply spellmods to aura damage
- uint32 damage = std::max(GetAmount() + GetBonusAmount(), 0); // if isAreaAura == true, GetBonusAmount == 0.
+ uint32 damage = std::max(GetAmount(), 0);
// Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage);
if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
{
- if (isAreaAura)
- damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()) * caster->SpellDamagePctDone(target, m_spellInfo, DOT);
- else
- damage = std::max(int32(damage * GetDonePct()), 0);
-
- if (Player* modOwner = caster->GetSpellModOwner())
- modOwner->ApplySpellMod(GetSpellInfo()->Id, SPELLMOD_DOT, damage);
-
- damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
-
- // Calculate armor mitigation
- if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex()))
- {
- uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellInfo());
- cleanDamage.mitigated_damage += damage - damageReductedArmor;
- damage = damageReductedArmor;
- }
+ // leave only target depending bonuses, rest is handled in calculate amount
+ if (GetBase()->GetType() == DYNOBJ_AURA_TYPE)
+ damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, { }, GetBase()->GetStackAmount());
- // Curse of Agony damage-per-tick calculation
- if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellInfo()->SpellFamilyFlags[0] & 0x400) && GetSpellInfo()->SpellIconID == 544)
- {
- uint32 totalTicks = GetTotalTicks();
- // 1..4 ticks, 1/2 from normal tick damage
- if (_ticksDone <= totalTicks / 3)
- damage = damage / 2;
- // 9..12 ticks, 3/2 from normal tick damage
- else if (_ticksDone > totalTicks * 2 / 3)
- damage += (damage + 1) / 2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
- // 5..8 ticks have normal tick damage
- }
- // There is a Chance to make a Soul Shard when Drain soul does damage
- if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000))
+ switch (GetSpellInfo()->SpellFamilyName)
{
- if (caster->GetTypeId() == TYPEID_PLAYER && caster->ToPlayer()->isHonorOrXPTarget(target))
+ case SPELLFAMILY_WARLOCK:
{
- if (roll_chance_i(20))
+ // Curse of Agony damage-per-tick calculation
+ if ((GetSpellInfo()->SpellFamilyFlags[0] & 0x400) && GetSpellInfo()->SpellIconID == 544)
+ {
+ uint32 totalTicks = GetTotalTicks();
+ // 1..4 ticks, 1/2 from normal tick damage
+ if (_ticksDone <= totalTicks / 3)
+ damage = damage / 2;
+ // 9..12 ticks, 3/2 from normal tick damage
+ else if (_ticksDone > totalTicks * 2 / 3)
+ damage += (damage + 1) / 2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
+ // 5..8 ticks have normal tick damage
+ }
+ // There is a Chance to make a Soul Shard when Drain soul does damage
+ else if ((GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000))
{
- caster->CastSpell(caster, 43836, this);
- // Glyph of Drain Soul - chance to create an additional Soul Shard
- if (AuraEffect* aur = caster->GetAuraEffect(58070, 0))
- if (roll_chance_i(aur->GetMiscValue()))
- caster->CastSpell(caster, 58068, aur);
+ if (caster && caster->GetTypeId() == TYPEID_PLAYER && caster->ToPlayer()->isHonorOrXPTarget(target))
+ {
+ if (roll_chance_i(20))
+ {
+ caster->CastSpell(caster, 43836, this);
+ // Glyph of Drain Soul - chance to create an additional Soul Shard
+ if (AuraEffect* aur = caster->GetAuraEffect(58070, 0))
+ if (roll_chance_i(aur->GetMiscValue()))
+ caster->CastSpell(caster, 58068, aur);
+ }
+ }
}
+ break;
}
- }
- if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_GENERIC)
- {
- switch (GetId())
+ case SPELLFAMILY_GENERIC:
{
- case 70911: // Unbound Plague
- case 72854: // Unbound Plague
- case 72855: // Unbound Plague
- case 72856: // Unbound Plague
- damage *= uint32(pow(1.25f, int32(_ticksDone)));
- break;
- default:
- break;
+ switch (GetId())
+ {
+ case 70911: // Unbound Plague
+ case 72854: // Unbound Plague
+ case 72855: // Unbound Plague
+ case 72856: // Unbound Plague
+ damage *= uint32(pow(1.25f, int32(_ticksDone)));
+ break;
+ default:
+ break;
+ }
+ break;
}
+ default:
+ break;
}
}
else // ceil obtained value, it may happen that 10 ticks for 10% damage may not kill owner
damage = uint32(ceil(CalculatePct<float, float>(target->GetMaxHealth(), damage)));
- if (!m_spellInfo->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
- {
- if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura)
- {
- damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
- if (caster->GetTypeId() != TYPEID_PLAYER)
- damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
- }
- }
+ damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
- bool crit = false;
+ bool crit = roll_chance_f(GetCritChanceFor(caster, target));
+ if (crit)
+ damage = Unit::SpellCriticalDamageBonus(caster, m_spellInfo, damage, target);
- if (CanPeriodicTickCrit(caster))
- crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()) : GetCritChance());
+ // Calculate armor mitigation
+ if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex()))
+ {
+ uint32 damageReductedArmor = Unit::CalcArmorReducedDamage(caster, target, damage, GetSpellInfo(), GetBase()->GetCasterLevel());
+ cleanDamage.mitigated_damage += damage - damageReductedArmor;
+ damage = damageReductedArmor;
+ }
- if (crit)
- damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
+ if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
+ {
+ if (GetSpellInfo()->Effects[GetEffIndex()].IsTargetingArea() || GetSpellInfo()->Effects[GetEffIndex()].IsAreaAuraEffect() || GetSpellInfo()->Effects[GetEffIndex()].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA)
+ damage = target->CalculateAOEAvoidance(damage, m_spellInfo->SchoolMask, caster);
+ }
int32 dmg = damage;
- if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
- caster->ApplyResilience(target, nullptr, &dmg, crit, CR_CRIT_TAKEN_SPELL);
+ if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE) && GetBase()->CanApplyResilience())
+ Unit::ApplyResilience(target, nullptr, &dmg, crit, CR_CRIT_TAKEN_SPELL);
damage = dmg;
DamageInfo damageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, BASE_ATTACK);
- caster->CalcAbsorbResist(damageInfo);
+ Unit::CalcAbsorbResist(damageInfo);
damage = damageInfo.GetDamage();
uint32 absorb = damageInfo.GetAbsorb();
@@ -5181,7 +5189,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s attacked %s for %u dmg inflicted by %u absorb is %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb);
- caster->DealDamageMods(target, damage, &absorb);
+ Unit::DealDamageMods(target, damage, &absorb);
// Set trigger flag
uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
@@ -5200,14 +5208,17 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
SpellPeriodicAuraLogInfo pInfo(this, damage, overkill, absorb, resist, 0.0f, crit);
target->SendPeriodicAuraLog(&pInfo);
- caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true);
+ Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true);
- caster->ProcSkillsAndAuras(target, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &damageInfo, nullptr);
+ Unit::ProcSkillsAndAuras(caster, target, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &damageInfo, nullptr);
}
void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const
{
- if (!caster || !target->IsAlive())
+ // dynobj auras must always have a caster
+ ASSERT(GetSpellInfo()->Effects[GetEffIndex()].Effect != SPELL_EFFECT_PERSISTENT_AREA_AURA || caster);
+
+ if (!target->IsAlive())
return;
if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo()))
@@ -5222,56 +5233,41 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA);
// ignore negative values (can be result apply spellmods to aura damage
- uint32 damage = std::max(GetAmount() + GetBonusAmount(), 0); // if isAreaAura == true, GetBonusAmount == 0.
+ uint32 damage = std::max(GetAmount(), 0);
// Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage);
- if (isAreaAura)
- damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()) * caster->SpellDamagePctDone(target, m_spellInfo, DOT);
- else
- damage = std::max(int32(damage * GetDonePct()), 0);
-
- if (Player* modOwner = caster->GetSpellModOwner())
- modOwner->ApplySpellMod(GetSpellInfo()->Id, SPELLMOD_DOT, damage);
-
+ if (GetBase()->GetType() == DYNOBJ_AURA_TYPE)
+ damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, { }, GetBase()->GetStackAmount());
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
+ bool crit = roll_chance_f(GetCritChanceFor(caster, target));
+ if (crit)
+ damage = Unit::SpellCriticalDamageBonus(caster, m_spellInfo, damage, target);
+
// Calculate armor mitigation
if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex()))
{
- uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellInfo());
+ uint32 damageReductedArmor = Unit::CalcArmorReducedDamage(caster, target, damage, GetSpellInfo(), GetBase()->GetCasterLevel());
cleanDamage.mitigated_damage += damage - damageReductedArmor;
damage = damageReductedArmor;
}
- if (!m_spellInfo->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
+ if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
{
- if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura)
- {
- damage = uint32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
- if (caster->GetTypeId() != TYPEID_PLAYER)
- damage = uint32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
- }
+ if (GetSpellInfo()->Effects[GetEffIndex()].IsTargetingArea() || GetSpellInfo()->Effects[GetEffIndex()].IsAreaAuraEffect() || GetSpellInfo()->Effects[GetEffIndex()].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA)
+ damage = target->CalculateAOEAvoidance(damage, m_spellInfo->SchoolMask, caster);
}
- bool crit = false;
-
- if (CanPeriodicTickCrit(caster))
- crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()) : GetCritChance());
-
- if (crit)
- damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
-
int32 dmg = damage;
- if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
- caster->ApplyResilience(target, nullptr, &dmg, crit, CR_CRIT_TAKEN_SPELL);
+ if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE) && GetBase()->CanApplyResilience())
+ Unit::ApplyResilience(target, nullptr, &dmg, crit, CR_CRIT_TAKEN_SPELL);
damage = dmg;
DamageInfo damageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, BASE_ATTACK);
- caster->CalcAbsorbResist(damageInfo);
+ Unit::CalcAbsorbResist(damageInfo);
uint32 absorb = damageInfo.GetAbsorb();
uint32 resist = damageInfo.GetResist();
@@ -5292,22 +5288,22 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
procVictim |= PROC_FLAG_TAKEN_DAMAGE;
}
- int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false);
- if (caster->IsAlive())
- {
- caster->ProcSkillsAndAuras(target, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &damageInfo, nullptr);
+ int32 new_damage = Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false);
+ if (!caster || !caster->IsAlive())
+ return;
- float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster);
+ Unit::ProcSkillsAndAuras(caster, target, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &damageInfo, nullptr);
- uint32 heal = uint32(caster->SpellHealingBonusDone(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, GetBase()->GetStackAmount()));
- heal = uint32(caster->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT, GetBase()->GetStackAmount()));
+ float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster);
- HealInfo healInfo(caster, caster, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask());
- caster->HealBySpell(healInfo);
+ uint32 heal = caster->SpellHealingBonusDone(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, { }, GetBase()->GetStackAmount());
+ heal = caster->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT, GetBase()->GetStackAmount());
- caster->GetThreatManager().ForwardThreatForAssistingMe(caster, healInfo.GetEffectiveHeal()*0.5f, GetSpellInfo());
- caster->ProcSkillsAndAuras(caster, PROC_FLAG_DONE_PERIODIC, PROC_FLAG_TAKEN_PERIODIC, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, hitMask, nullptr, nullptr, &healInfo);
- }
+ HealInfo healInfo(caster, caster, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask());
+ caster->HealBySpell(healInfo);
+
+ caster->GetThreatManager().ForwardThreatForAssistingMe(caster, healInfo.GetEffectiveHeal() * 0.5f, GetSpellInfo());
+ Unit::ProcSkillsAndAuras(caster, caster, PROC_FLAG_DONE_PERIODIC, PROC_FLAG_TAKEN_PERIODIC, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, hitMask, nullptr, nullptr, &healInfo);
}
void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) const
@@ -5337,12 +5333,15 @@ void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster)
HealInfo healInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask());
caster->HealBySpell(healInfo);
- caster->ProcSkillsAndAuras(target, PROC_FLAG_DONE_PERIODIC, PROC_FLAG_TAKEN_PERIODIC, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, PROC_HIT_NORMAL, nullptr, nullptr, &healInfo);
+ Unit::ProcSkillsAndAuras(caster, target, PROC_FLAG_DONE_PERIODIC, PROC_FLAG_TAKEN_PERIODIC, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, PROC_HIT_NORMAL, nullptr, nullptr, &healInfo);
}
void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
{
- if (!caster || !target->IsAlive())
+ // dynobj auras must always have a caster
+ ASSERT(GetSpellInfo()->Effects[GetEffIndex()].Effect != SPELL_EFFECT_PERSISTENT_AREA_AURA || caster);
+
+ if (!target->IsAlive())
return;
if (target->HasUnitState(UNIT_STATE_ISOLATED))
@@ -5352,72 +5351,32 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
}
// heal for caster damage (must be alive)
- if (target != caster && GetSpellInfo()->HasAttribute(SPELL_ATTR2_HEALTH_FUNNEL) && !caster->IsAlive())
+ if (target != caster && GetSpellInfo()->HasAttribute(SPELL_ATTR2_HEALTH_FUNNEL) && (!caster || !caster->IsAlive()))
return;
// don't regen when permanent aura target has full power
if (GetBase()->IsPermanent() && target->IsFullHealth())
return;
- bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA);
// ignore negative values (can be result apply spellmods to aura damage
- uint32 damage = std::max(GetAmount() + GetBonusAmount(), 0); // if isAreaAura == true, GetBonusAmount == 0.
+ uint32 damage = std::max(GetAmount(), 0);
// Script Hook For HandlePeriodicHealAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage);
if (GetAuraType() == SPELL_AURA_OBS_MOD_HEALTH)
- {
- // Taken mods
- float TakenTotalMod = 1.0f;
-
- // Tenacity increase healing % taken
- if (AuraEffect const* Tenacity = target->GetAuraEffect(58549, 0))
- AddPct(TakenTotalMod, Tenacity->GetAmount());
-
- // Healing taken percent
- float minval = (float)target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
- if (minval)
- AddPct(TakenTotalMod, minval);
-
- float maxval = (float)target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
- if (maxval)
- AddPct(TakenTotalMod, maxval);
-
- // Healing over time taken percent
- float minval_hot = (float)target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT);
- if (minval_hot)
- AddPct(TakenTotalMod, minval_hot);
-
- float maxval_hot = (float)target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT);
- if (maxval_hot)
- AddPct(TakenTotalMod, maxval_hot);
-
- TakenTotalMod = std::max(TakenTotalMod, 0.0f);
-
damage = uint32(target->CountPctFromMaxHealth(damage));
- damage = uint32(damage * TakenTotalMod);
- }
else
{
- if (isAreaAura)
- damage = caster->SpellHealingBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()) * caster->SpellHealingPctDone(target, m_spellInfo);
- else
- damage = std::max(int32(damage * GetDonePct()), 0);
-
- if (Player* modOwner = caster->GetSpellModOwner())
- modOwner->ApplySpellMod(GetSpellInfo()->Id, SPELLMOD_DOT, damage);
-
- damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
+ if (GetBase()->GetType() == DYNOBJ_AURA_TYPE)
+ damage = caster->SpellHealingBonusDone(target, GetSpellInfo(), damage, DOT, { }, GetBase()->GetStackAmount());
}
- bool crit = false;
-
- if (CanPeriodicTickCrit(caster))
- crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()) : GetCritChance());
+ damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
+ bool crit = roll_chance_f(GetCritChanceFor(caster, target));
if (crit)
- damage = caster->SpellCriticalHealingBonus(m_spellInfo, damage, target);
+ damage = Unit::SpellCriticalHealingBonus(caster, m_spellInfo, damage, target);
TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s heal of %s for %u health inflicted by %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId());
@@ -5425,13 +5384,14 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
uint32 heal = damage;
HealInfo healInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask());
- caster->CalcHealAbsorb(healInfo);
- caster->DealHeal(healInfo);
+ Unit::CalcHealAbsorb(healInfo);
+ Unit::DealHeal(healInfo);
SpellPeriodicAuraLogInfo pInfo(this, heal, heal - healInfo.GetEffectiveHeal(), healInfo.GetAbsorb(), 0, 0.0f, crit);
target->SendPeriodicAuraLog(&pInfo);
- target->GetThreatManager().ForwardThreatForAssistingMe(caster, float(healInfo.GetEffectiveHeal())*0.5f, GetSpellInfo());
+ if (caster)
+ target->GetThreatManager().ForwardThreatForAssistingMe(caster, healInfo.GetEffectiveHeal() * 0.5f, GetSpellInfo());
bool haveCastItem = !GetBase()->GetCastItemGUID().IsEmpty();
@@ -5445,11 +5405,11 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
funnelDamage = healInfo.GetEffectiveHeal();
uint32 funnelAbsorb = 0;
- caster->DealDamageMods(caster, funnelDamage, &funnelAbsorb);
+ Unit::DealDamageMods(caster, funnelDamage, &funnelAbsorb);
caster->SendSpellNonMeleeDamageLog(caster, GetId(), funnelDamage, GetSpellInfo()->GetSchoolMask(), funnelAbsorb, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- caster->DealDamage(caster, funnelDamage, &cleanDamage, NODAMAGE, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true);
+ Unit::DealDamage(caster, caster, funnelDamage, &cleanDamage, SELF_DAMAGE, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true);
}
// %-based heal - does not proc auras
@@ -5461,7 +5421,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
uint32 hitMask = crit ? PROC_HIT_CRITICAL : PROC_HIT_NORMAL;
// ignore item heals
if (!haveCastItem)
- caster->ProcSkillsAndAuras(target, procAttacker, procVictim, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, hitMask, nullptr, nullptr, &healInfo);
+ Unit::ProcSkillsAndAuras(caster, target, procAttacker, procVictim, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, hitMask, nullptr, nullptr, &healInfo);
}
void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) const
@@ -5482,7 +5442,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con
return;
// ignore negative values (can be result apply spellmods to aura damage
- int32 drainAmount = std::max(m_amount, 0);
+ int32 drainAmount = std::max(GetAmount(), 0);
// Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
// It's mana percent cost spells, m_amount is percent drain from target
@@ -5559,7 +5519,7 @@ void AuraEffect::HandleObsModPowerAuraTick(Unit* target, Unit* caster) const
return;
// ignore negative values (can be result apply spellmods to aura damage
- uint32 amount = std::max(m_amount, 0) * target->GetMaxPower(powerType) /100;
+ uint32 amount = std::max(GetAmount(), 0) * target->GetMaxPower(powerType) /100;
TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s energize %s for %u dmg inflicted by %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), amount, GetId());
@@ -5593,7 +5553,7 @@ void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) cons
return;
// ignore negative values (can be result apply spellmods to aura damage
- int32 amount = std::max(m_amount, 0);
+ int32 amount = std::max(GetAmount(), 0);
SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false);
target->SendPeriodicAuraLog(&pInfo);
@@ -5621,7 +5581,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
}
// ignore negative values (can be result apply spellmods to aura damage
- int32 damage = std::max(m_amount, 0);
+ int32 damage = std::max(GetAmount(), 0);
// resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
if (powerType == POWER_MANA)
@@ -5637,7 +5597,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
// no SpellDamageBonus for burn mana
caster->CalculateSpellDamageTaken(&damageInfo, int32(gain * dmgMultiplier), spellProto);
- caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
+ Unit::DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
caster->SendSpellNonMeleeDamageLog(&damageInfo);
@@ -5655,7 +5615,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
caster->DealSpellDamage(&damageInfo, true);
DamageInfo dotDamageInfo(damageInfo, DOT, BASE_ATTACK, hitMask);
- caster->ProcSkillsAndAuras(target, procAttacker, procVictim, spellTypeMask, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &dotDamageInfo, nullptr);
+ Unit::ProcSkillsAndAuras(caster, target, procAttacker, procVictim, spellTypeMask, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &dotDamageInfo, nullptr);
}
void AuraEffect::HandleModAttackPowerOfArmorAuraTick(Unit* target, Unit* caster) const
@@ -5723,10 +5683,10 @@ void AuraEffect::HandleProcTriggerDamageAuraProc(AuraApplication* aurApp, ProcEv
}
SpellNonMeleeDamage damageInfo(target, triggerTarget, GetId(), GetSpellInfo()->SchoolMask);
- uint32 damage = target->SpellDamageBonusDone(triggerTarget, GetSpellInfo(), GetAmount(), SPELL_DIRECT_DAMAGE);
+ uint32 damage = target->SpellDamageBonusDone(triggerTarget, GetSpellInfo(), GetAmount(), SPELL_DIRECT_DAMAGE, { });
damage = triggerTarget->SpellDamageBonusTaken(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE);
target->CalculateSpellDamageTaken(&damageInfo, damage, GetSpellInfo());
- target->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
+ Unit::DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
target->SendSpellNonMeleeDamageLog(&damageInfo);
TC_LOG_DEBUG("spells", "AuraEffect::HandleProcTriggerDamageAuraProc: Triggering %u spell damage from aura %u proc", damage, GetId());
target->DealSpellDamage(&damageInfo, true);
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index befe0d7a2f6..1818dc359af 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -55,8 +55,8 @@ class TC_GAME_API AuraEffect
int32 GetMiscValueB() const { return m_spellInfo->Effects[m_effIndex].MiscValueB; }
int32 GetMiscValue() const { return m_spellInfo->Effects[m_effIndex].MiscValue; }
AuraType GetAuraType() const { return (AuraType)m_spellInfo->Effects[m_effIndex].ApplyAuraName; }
- int32 GetAmount() const { return m_amount; }
- void SetAmount(int32 amount) { m_amount = amount; m_canBeRecalculated = false;}
+ int32 GetAmount() const { return _amount; }
+ void SetAmount(int32 amount) { _amount = amount; m_canBeRecalculated = false; }
int32 GetPeriodicTimer() const { return _periodicTimer; }
void SetPeriodicTimer(int32 periodicTimer) { _periodicTimer = periodicTimer; }
@@ -73,13 +73,6 @@ class TC_GAME_API AuraEffect
void HandleEffect(Unit* target, uint8 mode, bool apply);
void ApplySpellMod(Unit* target, bool apply);
- void SetBonusAmount(int32 val) { m_bonusAmount = val; }
- int32 GetBonusAmount() const { return m_bonusAmount; }
- void SetCritChance(float val) { m_critChance = val; }
- float GetCritChance() const { return m_critChance; }
- void SetDonePct(float val) { m_donePct = val; }
- float GetDonePct() const { return m_donePct; }
-
void Update(uint32 diff, Unit* caster);
uint32 GetTickNumber() const { return _ticksDone; }
@@ -109,10 +102,7 @@ class TC_GAME_API AuraEffect
SpellInfo const* const m_spellInfo;
int32 const m_baseAmount;
- int32 m_amount;
- int32 m_bonusAmount;
- float m_critChance;
- float m_donePct;
+ int32 _amount;
SpellModifier* m_spellmod;
@@ -124,8 +114,8 @@ class TC_GAME_API AuraEffect
uint8 const m_effIndex;
bool m_canBeRecalculated;
bool m_isPeriodic;
- private:
- bool CanPeriodicTickCrit(Unit const* caster) const;
+
+ float GetCritChanceFor(Unit const* caster, Unit const* target) const;
public:
// aura effect apply/remove handlers
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index d1285e5633c..5d34233fc00 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -344,7 +344,7 @@ Aura::Aura(SpellInfo const* spellproto, WorldObject* owner, Unit* caster, Item*
m_spellInfo(spellproto), m_casterGuid(casterGUID ? casterGUID : caster->GetGUID()),
m_castItemGuid(castItem ? castItem->GetGUID() : ObjectGuid::Empty), m_applyTime(GameTime::GetGameTime()),
m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0),
-m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1),
+_casterInfo(), m_procCharges(0), m_stackAmount(1),
m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr),
m_procCooldown(std::chrono::steady_clock::time_point::min())
{
@@ -356,7 +356,15 @@ m_procCooldown(std::chrono::steady_clock::time_point::min())
m_procCharges = CalcMaxCharges(caster);
m_isUsingCharges = m_procCharges != 0;
memset(m_effects, 0, sizeof(m_effects));
+
// m_casterLevel = cast item level/caster level, caster level should be saved to db, confirmed with sniffs
+ _casterInfo.Level = m_spellInfo->SpellLevel;
+ if (caster)
+ {
+ _casterInfo.Level = caster->getLevel();
+ _casterInfo.ApplyResilience = caster->CanApplyResilience();
+ SaveCasterInfo(caster);
+ }
}
AuraScript* Aura::GetScriptByName(std::string const& scriptName) const
@@ -379,6 +387,58 @@ void Aura::_InitEffects(uint8 effMask, Unit* caster, int32 *baseAmount)
}
}
+bool Aura::CanPeriodicTickCrit(Unit const* caster) const
+{
+ if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_ABILITY_PERIODIC_CRIT, GetSpellInfo()))
+ return true;
+
+ // Rupture - since 3.3.3 can crit
+ if (GetSpellInfo()->SpellIconID == 500 && GetSpellInfo()->SpellFamilyName == SPELLFAMILY_ROGUE)
+ return true;
+
+ return false;
+}
+
+float Aura::CalcPeriodicCritChance(Unit const* caster) const
+{
+ Player* modOwner = caster->GetSpellModOwner();
+ if (!modOwner || !CanPeriodicTickCrit(modOwner))
+ return 0.f;
+
+ float critChance = modOwner->SpellCritChanceDone(GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), GetSpellInfo()->GetAttackType());
+ return std::max(0.f, critChance);
+}
+
+void Aura::SaveCasterInfo(Unit* caster)
+{
+ _casterInfo.CritChance = CalcPeriodicCritChance(caster);
+
+ if (GetType() == UNIT_AURA_TYPE)
+ {
+ /*
+ * Get critical chance from last effect type (damage or healing)
+ * this could potentialy be wrong if any spell has both damage and heal periodics
+ * The only two spells in 3.3.5 with those conditions are 17484 and 50344
+ * which shouldn't be allowed to crit, so we're fine
+ */
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ switch (GetSpellInfo()->Effects[i].ApplyAuraName)
+ {
+ case SPELL_AURA_PERIODIC_HEAL:
+ _casterInfo.BonusDonePct = caster->SpellHealingPctDone(GetUnitOwner(), GetSpellInfo());
+ break;
+ case SPELL_AURA_PERIODIC_DAMAGE:
+ case SPELL_AURA_PERIODIC_LEECH:
+ _casterInfo.BonusDonePct = caster->SpellDamagePctDone(GetUnitOwner(), GetSpellInfo(), DOT);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
Aura::~Aura()
{
// unload scripts
@@ -870,13 +930,8 @@ void Aura::SetStackAmount(uint8 stackAmount)
m_effects[i]->ChangeAmount(m_effects[i]->CalculateAmount(caster), false, true);
for (std::list<AuraApplication*>::const_iterator apptItr = applications.begin(); apptItr != applications.end(); ++apptItr)
- {
if (!(*apptItr)->GetRemoveMode())
- {
- HandleAuraSpecificPeriodics(*apptItr, caster);
HandleAuraSpecificMods(*apptItr, caster, true, true);
- }
- }
SetNeedClientUpdateForTargets();
}
@@ -1067,13 +1122,15 @@ int32 Aura::CalcDispelChance(Unit const* auraTarget, bool offensive) const
return 100 - resistChance;
}
-void Aura::SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 * amount)
+void Aura::SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, float critChance, bool applyResilience, int32* amount)
{
m_maxDuration = maxduration;
m_duration = duration;
m_procCharges = charges;
m_isUsingCharges = m_procCharges != 0;
m_stackAmount = stackamount;
+ SetCritChance(critChance);
+ SetCanApplyResilience(applyResilience);
Unit* caster = GetCaster();
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
@@ -1307,10 +1364,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
// Improved Devouring Plague
if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3790, 1))
{
- int32 damage = (devouringPlague->GetAmount() + devouringPlague->GetBonusAmount()) * devouringPlague->GetDonePct();
- if (Player* modOwner = caster->GetSpellModOwner())
- modOwner->ApplySpellMod(GetSpellInfo()->Id, SPELLMOD_DOT, damage);
-
+ int32 damage = devouringPlague->GetAmount();
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT);
CastSpellExtraArgs args(devouringPlague), args2(devouringPlague);
@@ -1672,50 +1726,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
}
}
-void Aura::HandleAuraSpecificPeriodics(AuraApplication const* aurApp, Unit* caster)
-{
- Unit* target = aurApp->GetTarget();
-
- if (!caster || aurApp->GetRemoveMode())
- return;
-
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (!HasEffect(i))
- continue;
-
- if (m_spellInfo->Effects[i].IsAreaAuraEffect() || m_spellInfo->Effects[i].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
- continue;
-
- switch (m_spellInfo->Effects[i].ApplyAuraName)
- {
- case SPELL_AURA_PERIODIC_DAMAGE:
- case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
- case SPELL_AURA_PERIODIC_LEECH:
- {
- AuraEffect* aurEff = GetEffect(i);
-
- aurEff->SetDonePct(caster->SpellDamagePctDone(target, m_spellInfo, DOT));
- aurEff->SetBonusAmount(caster->SpellDamageBonusDone(target, m_spellInfo, 0, DOT, GetStackAmount()));
- aurEff->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()));
- break;
- }
- case SPELL_AURA_PERIODIC_HEAL:
- case SPELL_AURA_OBS_MOD_HEALTH:
- {
- AuraEffect* aurEff = GetEffect(i);
-
- aurEff->SetDonePct(caster->SpellHealingPctDone(target, m_spellInfo));
- aurEff->SetBonusAmount(caster->SpellHealingBonusDone(target, m_spellInfo, 0, DOT, GetStackAmount()));
- aurEff->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()));
- break;
- }
- default:
- break;
- }
- }
-}
-
bool Aura::CanBeAppliedOn(Unit* target)
{
// unit not in world or during remove from world
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index c99f9f1a73a..82613cea9ea 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -82,6 +82,15 @@ class TC_GAME_API AuraApplication
void ClientUpdate(bool remove = false);
};
+// Caches some information about caster (because it may no longer exist)
+struct CasterInfo
+{
+ float CritChance = 0.f;
+ float BonusDonePct = 0.f;
+ uint8 Level = 0;
+ bool ApplyResilience = false;
+};
+
class TC_GAME_API Aura
{
friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, bool resetPeriodicTimer);
@@ -94,6 +103,7 @@ class TC_GAME_API Aura
static Aura* Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID);
explicit Aura(SpellInfo const* spellproto, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID);
void _InitEffects(uint8 effMask, Unit* caster, int32 *baseAmount);
+ void SaveCasterInfo(Unit* caster);
virtual ~Aura();
SpellInfo const* GetSpellInfo() const { return m_spellInfo; }
@@ -148,7 +158,13 @@ class TC_GAME_API Aura
void SetStackAmount(uint8 num);
bool ModStackAmount(int32 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT, bool resetPeriodicTimer = true);
- uint8 GetCasterLevel() const { return m_casterLevel; }
+ bool CanApplyResilience() const { return _casterInfo.ApplyResilience; }
+ void SetCanApplyResilience(bool val) { _casterInfo.ApplyResilience = val; }
+ uint8 GetCasterLevel() const { return _casterInfo.Level; }
+ float GetCritChance() const { return _casterInfo.CritChance; }
+ void SetCritChance(float val) { _casterInfo.CritChance = val; }
+ float GetDonePct() const { return _casterInfo.BonusDonePct; }
+ void SetDonePct(float val) { _casterInfo.BonusDonePct = val; }
bool HasMoreThanOneEffectForType(AuraType auraType) const;
bool IsArea() const;
@@ -173,9 +189,12 @@ class TC_GAME_API Aura
void UnregisterSingleTarget();
int32 CalcDispelChance(Unit const* auraTarget, bool offensive) const;
- void SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 * amount);
+ void SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, float critChance, bool applyResilience, int32* amount);
// helpers for aura effects
+ bool CanPeriodicTickCrit(Unit const* caster) const;
+ float CalcPeriodicCritChance(Unit const* caster) const;
+
bool HasEffect(uint8 effIndex) const { return GetEffect(effIndex) != nullptr; }
bool HasEffectType(AuraType type) const;
AuraEffect* GetEffect(uint8 effIndex) const { ASSERT (effIndex < MAX_SPELL_EFFECTS); return m_effects[effIndex]; }
@@ -192,7 +211,6 @@ class TC_GAME_API Aura
void SetNeedClientUpdateForTargets() const;
void HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, bool apply, bool onReapply);
- void HandleAuraSpecificPeriodics(AuraApplication const* aurApp, Unit* caster);
bool CanBeAppliedOn(Unit* target);
bool CheckAreaTarget(Unit* target);
bool CanStackWith(Aura const* existingAura) const;
@@ -258,7 +276,7 @@ class TC_GAME_API Aura
int32 m_timeCla; // Timer for power per sec calcultion
int32 m_updateTargetMapInterval; // Timer for UpdateTargetMapOfEffect
- uint8 const m_casterLevel; // Aura level (store caster level for correct show level dep amount)
+ CasterInfo _casterInfo;
uint8 m_procCharges; // Aura charges (0 for infinite)
uint8 m_stackAmount; // Aura stack amount
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 184a003cba0..8fd6715bf24 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -2017,7 +2017,7 @@ class ProcReflectDelayed : public BasicEvent
uint32 const spellPhaseMask = PROC_SPELL_PHASE_NONE;
uint32 const hitMask = PROC_HIT_REFLECT;
- caster->ProcSkillsAndAuras(_victim, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, nullptr, nullptr, nullptr);
+ Unit::ProcSkillsAndAuras(caster, _victim, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, nullptr, nullptr, nullptr);
return true;
}
@@ -2394,7 +2394,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
if (crit)
{
hitMask |= PROC_HIT_CRITICAL;
- addhealth = caster->SpellCriticalHealingBonus(m_spellInfo, addhealth, nullptr);
+ addhealth = Unit::SpellCriticalHealingBonus(caster, m_spellInfo, addhealth, nullptr);
}
else
hitMask |= PROC_HIT_NORMAL;
@@ -2406,7 +2406,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
// Do triggers for unit
if (canEffectTrigger)
- caster->ProcSkillsAndAuras(unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_HIT, hitMask, this, nullptr, &healInfo);
+ Unit::ProcSkillsAndAuras(caster, unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_HIT, hitMask, this, nullptr, &healInfo);
}
// Do damage and triggers
else if (m_damage > 0)
@@ -2426,7 +2426,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
{
// Add bonuses and fill damageInfo struct
caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo, m_attackType, target->crit);
- caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
+ Unit::DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
// Send log damage message to client
caster->SendSpellNonMeleeDamageLog(&damageInfo);
@@ -2442,7 +2442,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
if (canEffectTrigger)
{
DamageInfo spellDamageInfo(damageInfo, SPELL_DIRECT_DAMAGE, m_attackType, hitMask);
- caster->ProcSkillsAndAuras(unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_HIT, hitMask, this, &spellDamageInfo, nullptr);
+ Unit::ProcSkillsAndAuras(caster, unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_HIT, hitMask, this, &spellDamageInfo, nullptr);
if (caster->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->HasAttribute(SPELL_ATTR0_STOP_ATTACK_TARGET) && !m_spellInfo->HasAttribute(SPELL_ATTR4_CANT_TRIGGER_ITEM_SPELLS) &&
(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED))
@@ -2459,7 +2459,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
if (canEffectTrigger)
{
DamageInfo spellNoDamageInfo(damageInfo, NODAMAGE, m_attackType, hitMask);
- caster->ProcSkillsAndAuras(unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_NO_DMG_HEAL, PROC_SPELL_PHASE_HIT, hitMask, this, &spellNoDamageInfo, nullptr);
+ Unit::ProcSkillsAndAuras(caster, unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_NO_DMG_HEAL, PROC_SPELL_PHASE_HIT, hitMask, this, &spellNoDamageInfo, nullptr);
if (caster->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->HasAttribute(SPELL_ATTR0_STOP_ATTACK_TARGET) && !m_spellInfo->HasAttribute(SPELL_ATTR4_CANT_TRIGGER_ITEM_SPELLS) &&
(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED))
@@ -3379,7 +3379,7 @@ void Spell::_cast(bool skipCheck)
if (!(hitMask & PROC_HIT_CRITICAL))
hitMask |= PROC_HIT_NORMAL;
- m_originalCaster->ProcSkillsAndAuras(nullptr, procAttacker, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_CAST, hitMask, this, nullptr, nullptr);
+ Unit::ProcSkillsAndAuras(m_originalCaster, nullptr, procAttacker, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_CAST, hitMask, this, nullptr, nullptr);
}
void Spell::handle_immediate()
@@ -3575,7 +3575,7 @@ void Spell::_handle_finish_phase()
procAttacker = IsPositive() ? PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG;
}
- m_originalCaster->ProcSkillsAndAuras(nullptr, procAttacker, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_FINISH, m_hitMask, this, nullptr, nullptr);
+ Unit::ProcSkillsAndAuras(m_originalCaster, nullptr, procAttacker, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_FINISH, m_hitMask, this, nullptr, nullptr);
}
void Spell::SendSpellCooldown()
@@ -7308,9 +7308,7 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier)
{
if (m_spellInfo->Effects[i].IsTargetingArea() || m_spellInfo->Effects[i].IsAreaAuraEffect() || m_spellInfo->Effects[i].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
{
- m_damage = int32(float(m_damage) * unit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
- if (m_caster->GetTypeId() != TYPEID_PLAYER)
- m_damage = int32(float(m_damage) * unit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
+ m_damage = unit->CalculateAOEAvoidance(m_damage, m_spellInfo->SchoolMask, m_caster);
if (m_caster->GetTypeId() == TYPEID_PLAYER)
{
@@ -7330,7 +7328,8 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier)
}
}
- targetInfo.crit = m_caster->IsSpellCrit(unit, m_spellInfo, m_spellSchoolMask, m_attackType);
+ float critChance = m_caster->SpellCritChanceDone(m_spellInfo, m_spellSchoolMask, m_attackType);
+ targetInfo.crit = roll_chance_f(unit->SpellCritChanceTaken(m_caster, m_spellInfo, m_spellSchoolMask, critChance, m_attackType));
}
SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& skillId, int32& reqSkillValue, int32& skillValue)
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 5baf98ebf10..2e43d43bd81 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -286,7 +286,7 @@ void Spell::EffectInstaKill(SpellEffIndex /*effIndex*/)
data << uint32(m_spellInfo->Id);
m_caster->SendMessageToSet(&data, true);
- m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), nullptr, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ Unit::DealDamage(m_caster, unitTarget, unitTarget->GetHealth(), nullptr, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
}
void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/)
@@ -303,7 +303,7 @@ void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/)
else
{
DamageInfo damageInfo(m_caster, unitTarget, damage, m_spellInfo, m_spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE, BASE_ATTACK);
- m_caster->CalcAbsorbResist(damageInfo);
+ Unit::CalcAbsorbResist(damageInfo);
uint32 absorb = damageInfo.GetAbsorb();
uint32 resist = damageInfo.GetResist();
@@ -430,10 +430,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
if (aura)
{
// Calculate damage of Immolate/Shadowflame tick
- int32 pdamage = (aura->GetAmount() + aura->GetBonusAmount()) * aura->GetDonePct();
- if (Player* modOwner = m_caster->GetSpellModOwner())
- modOwner->ApplySpellMod(GetSpellInfo()->Id, SPELLMOD_DOT, pdamage);
-
+ int32 pdamage = aura->GetAmount();
pdamage = unitTarget->SpellDamageBonusTaken(m_caster, aura->GetSpellInfo(), pdamage, DOT);
// And multiply by amount of ticks to get damage potential
@@ -670,7 +667,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
if (m_originalCaster && damage > 0 && apply_direct_bonus)
{
- damage = m_originalCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE);
+ damage = m_originalCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE, { });
damage = unitTarget->SpellDamageBonusTaken(m_originalCaster, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE);
}
@@ -1210,7 +1207,7 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex)
return;
// add spell damage bonus
- damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
+ damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE, { });
damage = unitTarget->SpellDamageBonusTaken(m_caster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
// resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
@@ -1372,10 +1369,7 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
return;
}
- int32 tickheal = (targetAura->GetAmount() + targetAura->GetBonusAmount()) * targetAura->GetDonePct();
- if (Player* modOwner = m_caster->GetSpellModOwner())
- modOwner->ApplySpellMod(targetAura->GetId(), SPELLMOD_DOT, tickheal);
-
+ int32 tickheal = targetAura->GetAmount();
unitTarget->SpellHealingBonusTaken(m_caster, targetAura->GetSpellInfo(), tickheal, DOT);
//int32 tickheal = targetAura->GetSpellInfo()->EffectBasePoints[idx] + 1;
@@ -1401,24 +1395,27 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
// Nourish
else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags[1] & 0x2000000)
{
- addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL);
+ addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL, { });
// Glyph of Nourish
if (AuraEffect const* aurEff = m_caster->GetAuraEffect(62971, 0))
{
- Unit::AuraEffectList const& Periodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL);
- for (Unit::AuraEffectList::const_iterator i = Periodic.begin(); i != Periodic.end(); ++i)
+ uint32 auraCount = 0;
+ Unit::AuraEffectList const& periodicHeals = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL);
+ for (AuraEffect const* hot : periodicHeals)
{
- if (m_caster->GetGUID() == (*i)->GetCasterGUID())
- AddPct(addhealth, aurEff->GetAmount());
+ if (m_caster->GetGUID() == hot->GetCasterGUID())
+ ++auraCount;
}
+
+ AddPct(addhealth, aurEff->GetAmount() * auraCount);
}
}
// Death Pact - return pct of max health to caster
else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00080000)
- addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, int32(caster->CountPctFromMaxHealth(damage)), HEAL);
+ addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, int32(caster->CountPctFromMaxHealth(damage)), HEAL, { });
else
- addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL);
+ addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL, { });
addhealth = unitTarget->SpellHealingBonusTaken(caster, m_spellInfo, addhealth, HEAL);
@@ -1442,10 +1439,8 @@ void Spell::EffectHealPct(SpellEffIndex /*effIndex*/)
if (!m_originalCaster)
return;
- uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, unitTarget->CountPctFromMaxHealth(damage), HEAL);
- heal = unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL);
-
- m_healing += heal;
+ uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, unitTarget->CountPctFromMaxHealth(damage), HEAL, { });
+ m_healing += unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL);
}
void Spell::EffectHealMechanical(SpellEffIndex /*effIndex*/)
@@ -1460,8 +1455,7 @@ void Spell::EffectHealMechanical(SpellEffIndex /*effIndex*/)
if (!m_originalCaster)
return;
- uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, uint32(damage), HEAL);
-
+ uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, uint32(damage), HEAL, { });
m_healing += unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL);
}
@@ -1473,7 +1467,7 @@ void Spell::EffectHealthLeech(SpellEffIndex effIndex)
if (!unitTarget || !unitTarget->IsAlive() || damage < 0)
return;
- damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
+ damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE, { });
damage = unitTarget->SpellDamageBonusTaken(m_caster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
TC_LOG_DEBUG("spells", "HealthLeech :%i", damage);
@@ -1486,7 +1480,7 @@ void Spell::EffectHealthLeech(SpellEffIndex effIndex)
if (m_caster->IsAlive())
{
- healthGain = m_caster->SpellHealingBonusDone(m_caster, m_spellInfo, healthGain, HEAL);
+ healthGain = m_caster->SpellHealingBonusDone(m_caster, m_spellInfo, healthGain, HEAL, { });
healthGain = m_caster->SpellHealingBonusTaken(m_caster, m_spellInfo, healthGain, HEAL);
HealInfo healInfo(m_caster, m_caster, healthGain, m_spellInfo, m_spellSchoolMask);
@@ -3406,7 +3400,7 @@ void Spell::EffectInterruptCast(SpellEffIndex effIndex)
{
int32 duration = m_spellInfo->GetDuration();
unitTarget->GetSpellHistory()->LockSpellSchool(curSpellInfo->GetSchoolMask(), unitTarget->ModSpellDuration(m_spellInfo, unitTarget, duration, false, 1 << effIndex));
- m_originalCaster->ProcSkillsAndAuras(unitTarget, PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_HIT, PROC_HIT_INTERRUPT, nullptr, nullptr, nullptr);
+ Unit::ProcSkillsAndAuras(m_originalCaster, unitTarget, PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_HIT, PROC_HIT_INTERRUPT, nullptr, nullptr, nullptr);
}
ExecuteLogEffectInterruptCast(effIndex, unitTarget, curSpellInfo->Id);
unitTarget->InterruptSpell(CurrentSpellTypes(i), false);
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 274d77c0134..731d4f4dfb7 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -2977,6 +2977,21 @@ void SpellMgr::LoadSpellInfoCorrections()
});
}
+ // Allows those to crit
+ ApplySpellFix({
+ 379, // Earth Shield
+ 33778, // Lifebloom Final Bloom
+ 64844, // Divine Hymn
+ 71607, // Item - Bauble of True Blood 10m
+ 71646, // Item - Bauble of True Blood 25m
+ 71610, // Item - Althor's Abacus trigger 10m
+ 71641 // Item - Althor's Abacus trigger 25m
+ }, [](SpellInfo* spellInfo)
+ {
+ // We need more spells to find a general way (if there is any)
+ spellInfo->DmgClass = SPELL_DAMAGE_CLASS_MAGIC;
+ });
+
// Spell Reflection
ApplySpellFix({ 57643 }, [](SpellInfo* spellInfo)
{
@@ -3172,6 +3187,14 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_20_YARDS);
});
+ // Arcane Potency
+ ApplySpellFix({ 57529, 57531 }, [](SpellInfo* spellInfo)
+ {
+ spellInfo->Effects[EFFECT_0].SpellClassMask = flag96();
+ spellInfo->Effects[EFFECT_0].ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER;
+ spellInfo->Effects[EFFECT_0].MiscValue = SPELLMOD_CRITICAL_CHANCE;
+ });
+
ApplySpellFix({
44978, // Wild Magic
45001, // Wild Magic
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index f61400c6b4b..aa6f1c7b5f3 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -634,9 +634,9 @@ public:
if (target->IsAlive())
{
if (sWorld->getBoolConfig(CONFIG_DIE_COMMAND_MODE))
- handler->GetSession()->GetPlayer()->Kill(target);
+ Unit::Kill(handler->GetSession()->GetPlayer(), target);
else
- handler->GetSession()->GetPlayer()->DealDamage(target, target->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ Unit::DealDamage(handler->GetSession()->GetPlayer(), target, target->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
}
return true;
@@ -2334,7 +2334,7 @@ public:
// flat melee damage without resistence/etc reduction
if (!schoolStr)
{
- handler->GetSession()->GetPlayer()->DealDamage(target, damage, nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ Unit::DealDamage(handler->GetSession()->GetPlayer(), target, damage, nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
if (target != handler->GetSession()->GetPlayer())
handler->GetSession()->GetPlayer()->SendAttackStateUpdate (HITINFO_AFFECTS_VICTIM, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_HIT, 0);
return true;
@@ -2347,7 +2347,7 @@ public:
SpellSchoolMask schoolmask = SpellSchoolMask(1 << school);
if (Unit::IsDamageReducedByArmor(schoolmask))
- damage = handler->GetSession()->GetPlayer()->CalcArmorReducedDamage(target, damage, nullptr, BASE_ATTACK);
+ damage = Unit::CalcArmorReducedDamage(handler->GetSession()->GetPlayer(), target, damage, nullptr, BASE_ATTACK);
char* spellStr = strtok((char*)nullptr, " ");
@@ -2356,7 +2356,7 @@ public:
{
Player* attacker = handler->GetSession()->GetPlayer();
DamageInfo dmgInfo(attacker, target, damage, nullptr, schoolmask, SPELL_DIRECT_DAMAGE, BASE_ATTACK);
- attacker->CalcAbsorbResist(dmgInfo);
+ Unit::CalcAbsorbResist(dmgInfo);
if (!dmgInfo.GetDamage())
return true;
@@ -2365,8 +2365,8 @@ public:
uint32 absorb = dmgInfo.GetAbsorb();
uint32 resist = dmgInfo.GetResist();
- attacker->DealDamageMods(target, damage, &absorb);
- attacker->DealDamage(target, damage, nullptr, DIRECT_DAMAGE, schoolmask, nullptr, false);
+ Unit::DealDamageMods(target, damage, &absorb);
+ Unit::DealDamage(attacker, target, damage, nullptr, DIRECT_DAMAGE, schoolmask, nullptr, false);
attacker->SendAttackStateUpdate(HITINFO_AFFECTS_VICTIM, target, 0, schoolmask, damage, absorb, resist, VICTIMSTATE_HIT, 0);
return true;
}
@@ -2384,11 +2384,11 @@ public:
Player* attacker = handler->GetSession()->GetPlayer();
SpellNonMeleeDamage dmgInfo(attacker, target, spellid, spellInfo->GetSchoolMask());
- damage = attacker->SpellDamageBonusDone(target, spellInfo, damage, SPELL_DIRECT_DAMAGE);
+ damage = attacker->SpellDamageBonusDone(target, spellInfo, damage, SPELL_DIRECT_DAMAGE, { });
damage = target->SpellDamageBonusTaken(attacker, spellInfo, damage, SPELL_DIRECT_DAMAGE);
attacker->CalculateSpellDamageTaken(&dmgInfo, damage, spellInfo);
- attacker->DealDamageMods(dmgInfo.target, dmgInfo.damage, &dmgInfo.absorb);
+ Unit::DealDamageMods(dmgInfo.target, dmgInfo.damage, &dmgInfo.absorb);
attacker->SendSpellNonMeleeDamageLog(&dmgInfo);
attacker->DealSpellDamage(&dmgInfo, true);
return true;
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp
index e5fbd9fb0bb..c779ae9db33 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp
@@ -158,7 +158,7 @@ class boss_ragnaros : public CreatureScript
case EVENT_INTRO_4:
Talk(SAY_ARRIVAL5_RAG);
if (Creature* executus = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MAJORDOMO_EXECUTUS)))
- me->Kill(executus);
+ Unit::Kill(me, executus);
break;
case EVENT_INTRO_5:
me->SetReactState(REACT_AGGRESSIVE);
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
index 59f647b7cb3..1169772f369 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
@@ -584,7 +584,7 @@ public:
}
case 15:
if (Creature* arca = ObjectAccessor::GetCreature(*me, ArcanagosGUID))
- arca->DealDamage(arca, arca->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ arca->KillSelf();
return 5000;
default:
return 9999999;
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp
index 4ffaf1c5f42..a79ece86c6d 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp
@@ -570,7 +570,7 @@ public:
{
//spell Burn should possible do this, but it doesn't, so do this for now.
uint16 dmg = urand(1650, 2050);
- me->DealDamage(me, dmg, 0, DOT, SPELL_SCHOOL_MASK_FIRE, nullptr, false);
+ Unit::DealDamage(me, me, dmg, 0, DOT, SPELL_SCHOOL_MASK_FIRE, nullptr, false);
BurnTimer += 2000;
} BurnTimer -= diff;
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp
index 09f995994da..ee2c7d70bfe 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp
@@ -142,7 +142,7 @@ public:
case 6:
Talk(SAY_PERSUADED6);
- player->Kill(me);
+ Unit::Kill(player, me);
speechCounter = 0;
player->GroupEventHappens(QUEST_HOW_TO_WIN_FRIENDS, me);
return;
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp
index b9516df7b0a..1d221606877 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp
@@ -234,7 +234,7 @@ public:
++IntroPhase;
break;
case 7:
- me->Kill(Madrigosa);
+ Unit::Kill(me, Madrigosa);
Madrigosa->AI()->Talk(YELL_MADR_DEATH);
me->SetFullHealth();
me->AttackStop();
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp
index 2a27aa8006a..1eaf4005e7b 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp
@@ -217,7 +217,7 @@ public:
summon->CastSpell(summon, SPELL_FOG_CHARM, true);
summon->CastSpell(summon, SPELL_FOG_CHARM2, true);
}
- me->DealDamage(caster, caster->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ Unit::DealDamage(me, caster, caster->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
}
}
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp
index 46d8b24e6cd..f360a25a6be 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp
@@ -478,7 +478,7 @@ struct boss_sathrovarr : public BossAI
if (spell->Id == SPELL_TAP_CHECK_DAMAGE)
{
DoCastSelf(SPELL_TELEPORT_BACK, true);
- caster->Kill(me);
+ Unit::Kill(caster, me);
}
}
diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp
index 47e54eece77..818fd205679 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp
@@ -216,7 +216,7 @@ class boss_akilzon : public CreatureScript
me->InterruptNonMeleeSpells(false);
CloudGUID.Clear();
if (Cloud)
- Cloud->DealDamage(Cloud, Cloud->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ Cloud->KillSelf();
SetWeather(WEATHER_STATE_FINE, 0.0f);
isRaining = false;
}
diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp
index 390381ea3fc..98272d1526d 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp
@@ -331,7 +331,7 @@ class boss_hexlord_malacrass : public CreatureScript
{
Unit* Temp = ObjectAccessor::GetUnit(*me, AddGUID[i]);
if (Temp && Temp->IsAlive())
- Temp->DealDamage(Temp, Temp->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ Temp->KillSelf();
}
}
diff --git a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp
index a631dd417e7..a8e6857bd34 100644
--- a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp
@@ -59,7 +59,7 @@ public:
void DoDie()
{
//summoner dies here
- me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ me->KillSelf();
//override any database `spawntimesecs` to prevent duplicated summons
uint32 rTime = me->GetRespawnDelay();
if (rTime < 600)
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp
index a1701b52f92..1fe47520fee 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp
@@ -392,7 +392,7 @@ public:
DoSpawnCreature(NPC_ANCIENT_WISP, float(rand32() % 40), float(rand32() % 40), 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
++WispCount;
if (WispCount >= 30)
- me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ me->KillSelf();
events.ScheduleEvent(EVENT_SUMMON_WHISP, 1500);
break;
default:
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp
index e442af3c594..323d027b2d0 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp
@@ -297,7 +297,7 @@ class instance_culling_of_stratholme : public InstanceMapScript
if (Creature* infinite = instance->GetCreature(_infiniteGUID))
{
if (Creature* guardian = infinite->FindNearestCreature(NPC_GUARDIAN_OF_TIME, 100.0f))
- infinite->Kill(guardian);
+ Unit::Kill(infinite, guardian);
if (Creature* rift = infinite->FindNearestCreature(NPC_TIME_RIFT, 100.0f))
{
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp
index b785aa0fb50..25b30c130cf 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp
@@ -80,7 +80,7 @@ public:
if (me->IsWithinDistInMap(who, 20.0f))
{
Talk(SAY_BANISH);
- me->DealDamage(who, who->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ Unit::DealDamage(me, who, who->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
}
}
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp
index b6b98aa182f..59b89c2ed09 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp
@@ -83,7 +83,7 @@ public:
if (me->IsWithinDistInMap(who, 20.0f))
{
Talk(SAY_BANISH);
- me->DealDamage(who, who->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ Unit::DealDamage(me, who, who->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
}
}
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp
index c7e74ec1b36..c0d97f39c41 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp
@@ -94,7 +94,7 @@ public:
{
Talk(SAY_BANISH);
- me->DealDamage(who, who->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ Unit::DealDamage(me, who, who->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
}
}
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp
index 5bc21333b95..3048fbb5c15 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp
@@ -182,7 +182,7 @@ public:
{
if (medivh->IsAlive())
{
- medivh->DealDamage(medivh, medivh->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ medivh->KillSelf();
m_auiEncounter[0] = FAIL;
m_auiEncounter[1] = NOT_STARTED;
}
diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp
index 0799b96a379..0bef0dabac1 100644
--- a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp
+++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp
@@ -231,7 +231,7 @@ public:
me->SetDisableGravity(false);
me->RemoveByteFlag(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
if (Creature* trigger = ObjectAccessor::GetCreature(*me, triggerGUID))
- me->Kill(trigger);
+ Unit::Kill(me, trigger);
me->SetReactState(REACT_AGGRESSIVE);
// tank selection based on phase one. If tank is not there i take nearest one
if (Unit* tank = ObjectAccessor::GetUnit(*me, tankGUID))
diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp
index c750a127163..de35c64119b 100644
--- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp
+++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp
@@ -102,7 +102,7 @@ class boss_buru : public CreatureScript
{
if (action == ACTION_EXPLODE)
if (_phase == PHASE_EGG)
- me->DealDamage(me, 45000);
+ Unit::DealDamage(me, me, 45000);
}
void KilledUnit(Unit* victim) override
@@ -261,7 +261,7 @@ class spell_egg_explosion : public SpellScriptLoader
void HandleDummyHitTarget(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
- GetCaster()->DealDamage(target, -16 * GetCaster()->GetDistance(target) + 500);
+ Unit::DealDamage(GetCaster(), target, -16 * GetCaster()->GetDistance(target) + 500);
}
void Register() override
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp
index f042f707f67..daf33fb3c79 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp
@@ -285,7 +285,7 @@ class npc_glob_of_viscidus : public CreatureScript
{
Viscidus->SetVisible(true);
if (Viscidus->GetVictim())
- Viscidus->EnsureVictim()->Kill(Viscidus);
+ Unit::Kill(Viscidus->EnsureVictim(), Viscidus);
}
else
{
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
index 0174e42f56d..38bda91bce7 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
@@ -816,7 +816,7 @@ public:
me->SummonCreature(NPC_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
else
me->SummonCreature(NPC_SARTHARION_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
- me->DealDamage(me, me->GetHealth());
+ me->KillSelf();
}
void JustSummoned(Creature* who) override
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp
index 2f9c010e63b..941deb21c37 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp
@@ -273,7 +273,7 @@ class npc_baltharus_the_warborn_clone : public CreatureScript
{
// This is here because DamageTaken wont trigger if the damage is deadly.
if (Creature* baltharus = instance->GetCreature(DATA_BALTHARUS_THE_WARBORN))
- killer->Kill(baltharus);
+ Unit::Kill(killer, baltharus);
}
void UpdateAI(uint32 diff) override
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
index 94aed04c62d..fe78ac3266b 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
@@ -451,7 +451,7 @@ class boss_twilight_halion : public CreatureScript
halion->LowerPlayerDamageReq(halion->GetMaxHealth());
if (halion->IsAlive())
- killer->Kill(halion);
+ Unit::Kill(killer, halion);
}
if (Creature* controller = instance->GetCreature(DATA_HALION_CONTROLLER))
diff --git a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp
index 4ac7f99e2c2..eb909ffa7bb 100644
--- a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp
+++ b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp
@@ -265,7 +265,7 @@ class boss_drakkari_elemental : public CreatureScript
Talk(EMOTE_ACTIVATE_ALTAR);
if (Creature* colossus = instance->GetCreature(DATA_DRAKKARI_COLOSSUS))
- killer->Kill(colossus);
+ Unit::Kill(killer, colossus);
}
void UpdateAI(uint32 diff) override
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
index 70f9c167cc2..c49b61b3014 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
@@ -331,7 +331,7 @@ class boss_blood_council_controller : public CreatureScript
// Make sure looting is allowed
if (me->IsDamageEnoughForLootingAndReward())
prince->LowerPlayerDamageReq(prince->GetMaxHealth());
- killer->Kill(prince);
+ Unit::Kill(killer, prince);
}
}
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
index 50ed4cc21b4..8550a5711ac 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
@@ -374,7 +374,7 @@ class boss_valithria_dreamwalker : public CreatureScript
lichKing->CastSpell(lichKing, SPELL_SPAWN_CHEST, false);
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER)))
- me->Kill(trigger);
+ Unit::Kill(me, trigger);
}
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
index 8b0e8f4baae..46890132586 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
@@ -881,7 +881,7 @@ class boss_sister_svalna : public CreatureScript
switch (spell->Id)
{
case SPELL_IMPALING_SPEAR_KILL:
- me->Kill(target);
+ Unit::Kill(me, target);
break;
case SPELL_IMPALING_SPEAR:
if (TempSummon* summon = target->SummonCreature(NPC_IMPALING_SPEAR, *target))
diff --git a/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp b/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp
index ed16b6728ac..c49af265572 100644
--- a/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp
+++ b/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp
@@ -71,7 +71,7 @@ public:
void SpellHit(Unit* caster, SpellInfo const* /*spell*/) override
{
if (caster->IsVehicle())
- me->Kill(caster);
+ Unit::Kill(me, caster);
}
void UpdateAI(uint32 diff) override
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp
index a7526420fd4..e81104ac77f 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp
@@ -130,7 +130,7 @@ class boss_faerlina : public CreatureScript
{
++_frenzyDispels;
Talk(EMOTE_WIDOW_EMBRACE, caster);
- me->Kill(caster);
+ Unit::Kill(me, caster);
}
}
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp
index 34bd11c3314..9a6401fa8cb 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp
@@ -555,7 +555,7 @@ public:
me->SetStandState(UNIT_STAND_STATE_STAND);
instance->HandleGameObject(instance->GetGuidData(DATA_GO_SKY_FLOOR), true);
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiControllerGUID))
- temp->DealDamage(temp, temp->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ temp->KillSelf();
bIsBattle = true;
SetEscortPaused(false);
JumpToNextStep(6500);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
index a92f6b0e62a..3d247223c97 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
@@ -1196,7 +1196,7 @@ class spell_algalon_collapse : public SpellScriptLoader
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
PreventDefaultAction();
- GetTarget()->DealDamage(GetTarget(), GetTarget()->CountPctFromMaxHealth(1), nullptr, NODAMAGE);
+ Unit::DealDamage(GetTarget(), GetTarget(), GetTarget()->CountPctFromMaxHealth(1), nullptr, NODAMAGE);
}
void Register() override
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
index 369a9c2f4d2..161287ccce8 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
@@ -366,9 +366,9 @@ static bool IsEncounterFinished(Unit* who)
vx001->GetStandState() == UNIT_STAND_STATE_DEAD &&
aerial->GetStandState() == UNIT_STAND_STATE_DEAD)
{
- who->Kill(mkii);
- who->Kill(vx001);
- who->Kill(aerial);
+ Unit::Kill(who, mkii);
+ Unit::Kill(who, vx001);
+ Unit::Kill(who, aerial);
mkii->DespawnOrUnsummon(120000);
vx001->DespawnOrUnsummon(120000);
aerial->DespawnOrUnsummon(120000);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
index 4e9b8a5780a..a4b5de9dd5b 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
@@ -699,7 +699,7 @@ class npc_boombot : public CreatureScript
data << uint32(SPELL_BOOM);
me->SendMessageToSet(&data, false);
- me->DealDamage(me, me->GetHealth(), nullptr, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ me->KillSelf();
damage = 0;
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
index 15e6be5ade7..af81915f694 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
@@ -949,7 +949,7 @@ class boss_yogg_saron : public CreatureScript
Talk(SAY_YOGG_SARON_DEATH);
if (Creature* creature = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON))
- me->Kill(creature);
+ Unit::Kill(me, creature);
for (uint8 i = DATA_SARA; i <= DATA_BRAIN_OF_YOGG_SARON; ++i)
if (Creature* creature = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(i)))
@@ -3101,7 +3101,7 @@ class spell_yogg_saron_titanic_storm : public SpellScriptLoader // 64172
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
- GetCaster()->Kill(target);
+ Unit::Kill(GetCaster(), target);
}
void Register() override
diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp
index fa7952110ac..d7dcf7e3639 100644
--- a/src/server/scripts/Northrend/zone_borean_tundra.cpp
+++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp
@@ -149,7 +149,7 @@ public:
DoCast(me, SPELL_EXPLODE_CART, true);
if (Unit* worm = me->FindNearestCreature(NPC_SCOURGED_BURROWER, 3.0f))
{
- me->Kill(worm);
+ Unit::Kill(me, worm);
worm->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
}
phaseTimer = 2000;
diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp
index 05b887f695e..d414a82bcd7 100644
--- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp
+++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp
@@ -136,7 +136,7 @@ public:
{
if (Creature* RWORG = ObjectAccessor::GetCreature(*me, _RavenousworgGUID))
{
- RWORG->Kill(Mrfloppy);
+ Unit::Kill(RWORG, Mrfloppy);
Mrfloppy->ExitVehicle();
RWORG->SetFaction(FACTION_MONSTER);
RWORG->GetMotionMaster()->MovePoint(0, RWORG->GetPositionX()+10, RWORG->GetPositionY()+80, RWORG->GetPositionZ());
diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp
index c297cb14460..8fb3fa601e7 100644
--- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp
+++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp
@@ -344,7 +344,7 @@ public:
Creature* Pet = ObjectAccessor::GetCreature(*me, SummonedPet);
if (Pet && Pet->IsAlive())
- Pet->DealDamage(Pet, Pet->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ Pet->KillSelf();
SummonedPet.Clear();
diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp
index 666dc045b5a..b429eda5aee 100644
--- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp
+++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp
@@ -158,7 +158,7 @@ public:
AttackStart(owner);
} else if (owner && owner->isDead())
{
- me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ me->KillSelf();
return;
}
}
diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp
index 9ceef78a818..bf8040bd287 100644
--- a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp
+++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp
@@ -201,9 +201,9 @@ public:
instance->DoCastSpellOnPlayers(SPELL_AHUNE_ACHIEVEMENT);
if (Creature* ahuneBunny = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AHUNE_BUNNY)))
- me->Kill(ahuneBunny);
+ Unit::Kill(me, ahuneBunny);
if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE)))
- me->Kill(frozenCore);
+ Unit::Kill(me, frozenCore);
Map::PlayerList const& players = me->GetMap()->GetPlayers();
if (!players.isEmpty())
@@ -316,7 +316,7 @@ public:
void JustDied(Unit* /*killer*/) override
{
if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE)))
- me->Kill(ahune);
+ Unit::Kill(me, ahune);
DoCast(SPELL_SUMMON_LOOT_MISSILE);
DoCast(SPELL_MINION_DESPAWNER);
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp
index 67a4b69375d..96001562d10 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp
@@ -125,7 +125,7 @@ class boss_shattered_executioner : public CreatureScript
if (type == DATA_PRISONERS_EXECUTED && data <= 3)
{
if (Creature* victim = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FIRST_PRISONER + data - 1)))
- me->Kill(victim);
+ Unit::Kill(me, victim);
if (data == 1)
{
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp
index 27f414783ed..07a7c3a910d 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp
@@ -551,7 +551,7 @@ class npc_ember_of_alar : public CreatureScript
if (toDie)
{
- me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ me->KillSelf();
//me->SetVisibility(VISIBILITY_OFF);
}
diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp
index 0a009c2ae63..047ba40bd9f 100644
--- a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp
+++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp
@@ -109,7 +109,7 @@ class npc_warp_splinter_treant : public CreatureScript
{
int32 CurrentHP_Treant = (int32)me->GetHealth();
Warp->CastSpell(Warp, SPELL_HEAL_FATHER, CastSpellExtraArgs(me->GetGUID()).AddSpellBP0(CurrentHP_Treant));
- me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ me->KillSelf();
return;
}
me->GetMotionMaster()->MoveFollow(Warp, 0, 0);
diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
index 2868c89439d..b317bda4e0e 100644
--- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
+++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
@@ -553,7 +553,7 @@ public:
player->KilledMonsterCredit(23209);
}
PoisonTimer = 0;
- me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ me->KillSelf();
} else PoisonTimer -= diff;
}
if (!UpdateVictim())
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp
index de0d34c59c0..bda0a4257ce 100644
--- a/src/server/scripts/Spells/spell_dk.cpp
+++ b/src/server/scripts/Spells/spell_dk.cpp
@@ -781,7 +781,7 @@ class spell_dk_dancing_rune_weapon : public SpellScriptLoader
int32 amount = static_cast<int32>(damageInfo->GetDamage()) / 2;
drw->SendSpellNonMeleeDamageLog(drw->GetVictim(), spellInfo->Id, amount, spellInfo->GetSchoolMask(), 0, 0, false, 0, false);
- drw->DealDamage(drw->GetVictim(), amount, nullptr, SPELL_DIRECT_DAMAGE, spellInfo->GetSchoolMask(), spellInfo, true);
+ Unit::DealDamage(drw, drw->GetVictim(), amount, nullptr, SPELL_DIRECT_DAMAGE, spellInfo->GetSchoolMask(), spellInfo, true);
}
void Register() override
@@ -1278,7 +1278,7 @@ class spell_dk_hysteria : public AuraScript
void PeriodicTick(AuraEffect const* aurEff)
{
uint32 const damage = GetTarget()->CountPctFromMaxHealth(GetTarget()->CalculateSpellDamage(nullptr, GetSpellInfo(), aurEff->GetEffIndex()));
- GetTarget()->DealDamage(GetTarget(), damage, nullptr, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
+ Unit::DealDamage(GetTarget(), GetTarget(), damage, nullptr, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
}
void Register() override
@@ -1733,40 +1733,36 @@ class spell_dk_pestilence : public SpellScriptLoader
{
if (Aura* aurOld = victim->GetAura(SPELL_DK_BLOOD_PLAGUE, caster->GetGUID())) // Check Blood Plague application on victim.
{
+ float donePct = aurOld->GetDonePct();
+ float critChance = aurOld->GetCritChance();
+
if (AuraEffect* aurEffOld = aurOld->GetEffect(EFFECT_0))
{
- float donePct = aurEffOld->GetDonePct();
- float critChance = aurEffOld->GetCritChance();
-
caster->CastSpell(hitUnit, SPELL_DK_BLOOD_PLAGUE, true); // Spread the disease to hitUnit.
if (Aura* aurNew = hitUnit->GetAura(SPELL_DK_BLOOD_PLAGUE, caster->GetGUID())) // Check Blood Plague application on hitUnit.
{
+ aurNew->SetCritChance(critChance); // Blood Plague can crit if caster has T9.
+ aurNew->SetDonePct(donePct);
if (AuraEffect* aurEffNew = aurNew->GetEffect(EFFECT_0))
- {
- aurEffNew->SetCritChance(critChance); // Blood Plague can crit if caster has T9.
- aurEffNew->SetDonePct(donePct);
- aurEffNew->SetBonusAmount(caster->SpellDamageBonusDone(hitUnit, aurEffNew->GetSpellInfo(), 0, DOT));
- }
+ aurEffNew->ChangeAmount(aurEffNew->CalculateAmount(aurEffNew->GetCaster()), false);
}
}
}
if (Aura* aurOld = victim->GetAura(SPELL_DK_FROST_FEVER, caster->GetGUID())) // Check Frost Fever application on victim.
{
+ float donePct = aurOld->GetDonePct();
+
if (AuraEffect* aurEffOld = aurOld->GetEffect(EFFECT_0))
{
- float donePct = aurEffOld->GetDonePct();
-
caster->CastSpell(hitUnit, SPELL_DK_FROST_FEVER, true); // Spread the disease to hitUnit.
if (Aura* aurNew = hitUnit->GetAura(SPELL_DK_FROST_FEVER, caster->GetGUID())) // Check Frost Fever application on hitUnit.
{
+ aurNew->SetDonePct(donePct);
if (AuraEffect* aurEffNew = aurNew->GetEffect(EFFECT_0))
- {
- aurEffNew->SetDonePct(donePct);
- aurEffNew->SetBonusAmount(caster->SpellDamageBonusDone(hitUnit, aurEffNew->GetSpellInfo(), 0, DOT));
- }
+ aurEffNew->ChangeAmount(aurEffNew->CalculateAmount(aurEffNew->GetCaster()), false);
}
}
}
@@ -2569,7 +2565,7 @@ class spell_dk_wandering_plague : public SpellScriptLoader
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
Unit* target = eventInfo.GetProcTarget();
- if (!roll_chance_f(caster->GetUnitCriticalChance(BASE_ATTACK, target)))
+ if (!roll_chance_f(caster->GetUnitCriticalChanceAgainst(BASE_ATTACK, target)))
return;
DamageInfo* damageInfo = eventInfo.GetDamageInfo();
diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp
index fdedfa6124a..9f349f223f8 100644
--- a/src/server/scripts/Spells/spell_druid.cpp
+++ b/src/server/scripts/Spells/spell_druid.cpp
@@ -1012,7 +1012,7 @@ class spell_dru_lifebloom : public SpellScriptLoader
int32 healAmount = aurEff->GetAmount();
if (Unit* caster = GetCaster())
{
- healAmount = caster->SpellHealingBonusDone(target, GetSpellInfo(), healAmount, HEAL, stack);
+ healAmount = caster->SpellHealingBonusDone(target, GetSpellInfo(), healAmount, HEAL, { }, stack);
healAmount = target->SpellHealingBonusTaken(caster, GetSpellInfo(), healAmount, HEAL, stack);
// restore mana
diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp
index 89b14f71ccb..bb741a94819 100644
--- a/src/server/scripts/Spells/spell_hunter.cpp
+++ b/src/server/scripts/Spells/spell_hunter.cpp
@@ -254,10 +254,7 @@ class spell_hun_chimera_shot : public SpellScriptLoader
spellId = SPELL_HUNTER_CHIMERA_SHOT_SERPENT;
// first, calculate damage of basic tick (C&P from AuraEffect::HandlePeriodicDamageAurasTick)
- basePoint = (aurEff->GetAmount() + aurEff->GetBonusAmount()) * aurEff->GetDonePct();
- if (Player* modOwner = caster->GetSpellModOwner())
- modOwner->ApplySpellMod(aurEff->GetId(), SPELLMOD_DOT, basePoint);
-
+ basePoint = aurEff->GetAmount();
basePoint = unitTarget->SpellDamageBonusTaken(caster, aurEff->GetSpellInfo(), basePoint, DOT, aura->GetStackAmount());
// then, multiply to get damage potential
diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp
index bc7219a1e03..e3664c16f3f 100644
--- a/src/server/scripts/Spells/spell_priest.cpp
+++ b/src/server/scripts/Spells/spell_priest.cpp
@@ -880,7 +880,7 @@ class spell_pri_pain_and_suffering_proc : public SpellScriptLoader
{
if (AuraEffect* aur = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, caster->GetGUID()))
{
- aur->SetBonusAmount(caster->SpellDamageBonusDone(target, aur->GetSpellInfo(), 0, DOT));
+ aur->ChangeAmount(aur->CalculateAmount(aur->GetCaster()), false);
aur->CalculatePeriodic(caster, false, false);
aur->GetBase()->RefreshDuration();
}
@@ -1112,10 +1112,7 @@ class spell_pri_renew : public SpellScriptLoader
// Empowered Renew
if (AuraEffect const* empoweredRenewAurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, PRIEST_ICON_ID_EMPOWERED_RENEW_TALENT, EFFECT_1))
{
- int32 heal = (aurEff->GetAmount() + aurEff->GetBonusAmount()) * aurEff->GetDonePct();
- if (Player* modOwner = caster->GetSpellModOwner())
- modOwner->ApplySpellMod(GetId(), SPELLMOD_DOT, heal);
-
+ int32 heal = aurEff->GetAmount();
heal = GetTarget()->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT);
heal *= GetSpellInfo()->GetMaxTicks();
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index c8cb24336ae..be2e27ab540 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -435,7 +435,7 @@ class spell_sha_earth_shield : public SpellScriptLoader
void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
if (Unit* caster = GetCaster())
- amount = caster->SpellHealingBonusDone(GetUnitOwner(), GetSpellInfo(), amount, HEAL);
+ amount = caster->SpellHealingBonusDone(GetUnitOwner(), GetSpellInfo(), amount, HEAL, { });
// SpellHealingBonusTaken will be called on Heal
}
@@ -996,7 +996,7 @@ class spell_sha_healing_stream_totem : public SpellScriptLoader
if (Unit* owner = caster->GetOwner())
{
if (triggeringSpell)
- damage = int32(owner->SpellHealingBonusDone(target, triggeringSpell, damage, HEAL));
+ damage = int32(owner->SpellHealingBonusDone(target, triggeringSpell, damage, HEAL, { }));
// Restorative Totems
if (AuraEffect* dummy = owner->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, SHAMAN_ICON_ID_RESTORATIVE_TOTEMS, 1))
diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp
index 38772874e0e..bd82af3bd8b 100644
--- a/src/server/scripts/Spells/spell_warlock.cpp
+++ b/src/server/scripts/Spells/spell_warlock.cpp
@@ -524,7 +524,7 @@ class spell_warl_everlasting_affliction : public SpellScriptLoader
// Refresh corruption on target
if (AuraEffect* aur = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x2, 0, 0, caster->GetGUID()))
{
- aur->SetBonusAmount(caster->SpellDamageBonusDone(target, aur->GetSpellInfo(), 0, DOT));
+ aur->ChangeAmount(aur->CalculateAmount(aur->GetCaster()), false);
aur->CalculatePeriodic(caster, false, false);
aur->GetBase()->RefreshDuration(true);
}
diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp
index 929bdb8fac3..0a735e39fea 100644
--- a/src/server/scripts/Spells/spell_warrior.cpp
+++ b/src/server/scripts/Spells/spell_warrior.cpp
@@ -102,7 +102,7 @@ class spell_warr_bloodthirst : public SpellScriptLoader
if (Unit* target = GetHitUnit())
{
- damage = GetCaster()->SpellDamageBonusDone(target, GetSpellInfo(), uint32(damage), SPELL_DIRECT_DAMAGE);
+ damage = GetCaster()->SpellDamageBonusDone(target, GetSpellInfo(), uint32(damage), SPELL_DIRECT_DAMAGE, { });
damage = target->SpellDamageBonusTaken(GetCaster(), GetSpellInfo(), uint32(damage), SPELL_DIRECT_DAMAGE);
}
SetHitDamage(damage);