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

@@ -957,7 +957,7 @@ void Player::HandleSobering()
SetDrunkValue(drunk);
}
DrunkenState Player::GetDrunkenstateByValue(uint8 value)
/*static*/ DrunkenState Player::GetDrunkenstateByValue(uint8 value)
{
if (value >= 90)
return DRUNKEN_SMASHED;
@@ -970,27 +970,17 @@ DrunkenState Player::GetDrunkenstateByValue(uint8 value)
void Player::SetDrunkValue(uint8 newDrunkValue, uint32 itemId /*= 0*/)
{
bool isSobering = newDrunkValue < GetDrunkValue();
newDrunkValue = std::min<uint8>(newDrunkValue, 100);
if (newDrunkValue == GetDrunkValue())
return;
uint32 oldDrunkenState = Player::GetDrunkenstateByValue(GetDrunkValue());
if (newDrunkValue > 100)
newDrunkValue = 100;
// select drunk percent or total SPELL_AURA_MOD_FAKE_INEBRIATE amount, whichever is higher for visibility updates
int32 drunkPercent = std::max<int32>(newDrunkValue, GetTotalAuraModifier(SPELL_AURA_MOD_FAKE_INEBRIATE));
if (drunkPercent)
{
m_invisibilityDetect.AddFlag(INVISIBILITY_DRUNK);
m_invisibilityDetect.SetValue(INVISIBILITY_DRUNK, drunkPercent);
}
else if (!HasAuraType(SPELL_AURA_MOD_FAKE_INEBRIATE) && !newDrunkValue)
m_invisibilityDetect.DelFlag(INVISIBILITY_DRUNK);
uint32 newDrunkenState = Player::GetDrunkenstateByValue(newDrunkValue);
SetByteValue(PLAYER_BYTES_3, 1, newDrunkValue);
UpdateObjectVisibility(false);
if (!isSobering)
m_drunkTimer = 0; // reset sobering timer
SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_INEBRIATION, newDrunkValue);
UpdateInvisibilityDrunkDetect();
m_drunkTimer = 0; // reset sobering timer
if (newDrunkenState == oldDrunkenState)
return;
@@ -1003,6 +993,24 @@ void Player::SetDrunkValue(uint8 newDrunkValue, uint32 itemId /*= 0*/)
SendMessageToSet(data.Write(), true);
}
void Player::UpdateInvisibilityDrunkDetect()
{
// select drunk percent or total SPELL_AURA_MOD_FAKE_INEBRIATE amount, whichever is higher for visibility updates
uint8 drunkValue = GetDrunkValue();
int32 fakeDrunkValue = GetFakeDrunkValue();
int32 maxDrunkValue = std::max<int32>(drunkValue, fakeDrunkValue);
if (maxDrunkValue != 0)
{
m_invisibilityDetect.AddFlag(INVISIBILITY_DRUNK);
m_invisibilityDetect.SetValue(INVISIBILITY_DRUNK, maxDrunkValue);
}
else
m_invisibilityDetect.DelFlag(INVISIBILITY_DRUNK);
UpdateObjectVisibility();
}
void Player::setDeathState(DeathState s, bool /*despawn = false*/)
{
uint32 ressSpellId = 0;