fix(Core/Spells): Fixed work of sobering spells and other improvements for drunk system (#18390)

* fix(Core/Spells): Fix sobering spells and possible uint8 overflow/underflow in SPELL_EFFECT_INEBRIATE handler.

* fix(Core/Spells): Improvements for SPELL_AURA_MOD_FAKE_INEBRIATE handling
This commit is contained in:
Mykhailo Redko
2024-03-20 06:45:01 +02:00
committed by GitHub
parent 21c1c5de11
commit 33f951d742
4 changed files with 50 additions and 60 deletions

View File

@@ -364,7 +364,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS] =
&AuraEffect::HandleNoImmediateEffect, //301 SPELL_AURA_SCHOOL_HEAL_ABSORB implemented in Unit::CalcHealAbsorb
&AuraEffect::HandleNULL, //302 0 spells in 3.3.5
&AuraEffect::HandleNoImmediateEffect, //303 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
&AuraEffect::HandleAuraModFakeInebriation, //304 SPELL_AURA_MOD_DRUNK
&AuraEffect::HandleAuraModFakeInebriation, //304 SPELL_AURA_MOD_FAKE_INEBRIATE
&AuraEffect::HandleAuraModIncreaseSpeed, //305 SPELL_AURA_MOD_MINIMUM_SPEED
&AuraEffect::HandleNULL, //306 0 spells in 3.3.5
&AuraEffect::HandleNULL, //307 0 spells in 3.3.5
@@ -6119,40 +6119,12 @@ void AuraEffect::HandleAuraModFakeInebriation(AuraApplication const* aurApp, uin
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit* target = aurApp->GetTarget();
Player* target = aurApp->GetTarget()->ToPlayer();
if (!target)
return;
if (apply)
{
target->m_invisibilityDetect.AddFlag(INVISIBILITY_DRUNK);
target->m_invisibilityDetect.AddValue(INVISIBILITY_DRUNK, GetAmount());
if (target->GetTypeId() == TYPEID_PLAYER)
{
int32 oldval = target->ToPlayer()->GetInt32Value(PLAYER_FAKE_INEBRIATION);
target->ToPlayer()->SetInt32Value(PLAYER_FAKE_INEBRIATION, oldval + GetAmount());
}
}
else
{
bool removeDetect = !target->HasAuraType(SPELL_AURA_MOD_FAKE_INEBRIATE);
target->m_invisibilityDetect.AddValue(INVISIBILITY_DRUNK, -GetAmount());
if (target->GetTypeId() == TYPEID_PLAYER)
{
int32 oldval = target->ToPlayer()->GetInt32Value(PLAYER_FAKE_INEBRIATION);
target->ToPlayer()->SetInt32Value(PLAYER_FAKE_INEBRIATION, oldval - GetAmount());
if (removeDetect)
removeDetect = !target->ToPlayer()->GetDrunkValue();
}
if (removeDetect)
target->m_invisibilityDetect.DelFlag(INVISIBILITY_DRUNK);
}
// call functions which may have additional effects after chainging state of unit
target->UpdateObjectVisibility(false);
target->ApplyModInt32Value(PLAYER_FAKE_INEBRIATION, GetAmount(), apply);
target->UpdateInvisibilityDrunkDetect();
}
void AuraEffect::HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 mode, bool apply) const

View File

@@ -4474,17 +4474,25 @@ void Spell::EffectInebriate(SpellEffIndex /*effIndex*/)
}
uint8 currentDrunk = player->GetDrunkValue();
uint8 drunkMod = damage;
if (currentDrunk + drunkMod > 100)
{
int32 drunkMod = damage;
if (drunkMod == 0)
return;
// drunkMod may contain values that are guaranteed to cause uint8 overflow/underflow (examples: 29690, 46874)
// In addition, we would not want currentDrunk to become more than 100.
// So before adding the values, let's check that everything is fine.
if (drunkMod > 0 && drunkMod > static_cast<int32>(100 - currentDrunk))
currentDrunk = 100;
if (rand_chance() < 25.0f)
player->CastSpell(player, 67468, false); // Drunken Vomit
}
else if (drunkMod < 0 && drunkMod < static_cast<int32>(0 - currentDrunk))
currentDrunk = 0;
else
currentDrunk += drunkMod;
currentDrunk += drunkMod; // Due to previous checks we can be sure that currentDrunk will not go beyond [0-100] range.
player->SetDrunkValue(currentDrunk, m_CastItem ? m_CastItem->GetEntry() : 0);
if (currentDrunk == 100 && roll_chance_i(25))
player->CastSpell(player, 67468, false); // Drunken Vomit
}
void Spell::EffectFeedPet(SpellEffIndex effIndex)