aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2018-01-13 06:45:21 -0300
committerariel- <ariel-@users.noreply.github.com>2018-01-13 06:45:21 -0300
commitcb9e72e521d3cc415dd15bf6912c87f89e41b92a (patch)
treebe9e692f0ddf9f080f923c7396de19e4ca869c6f
parent1c60af632888433b29a27bee76e82e96632d4096 (diff)
Core/Auras: removed caster dependency from core
- Decoupled Unit logic: split of spell critical chance into done (caster bonuses) and taken (target bonuses), this allows to precalculate caster bonuses on aura apply and then check victim's auras on damage/healing calc - Made static a bunch of methods (they no longer have this pointer because they are now called from periodic handlers which may or may not have an active caster in world) - Simplified all AuraEffect bonuses into AuraEffect::_amount, no more duplicated code - Critical chance and whether or not caster is player owned unit (for resilience calcs) is now saved one level upper, on Aura itself (it's impossible as of 3.3.5 to have different effects with different critical chances) - Minor cleanup of SPELL_DAMAGE_CLASS_NONE and Arcane Potency (#18813) crit handling Closes #19876
-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);