Skip to content

Commit

Permalink
Enable using self-resurrection spells on 1.5 client (#2182)
Browse files Browse the repository at this point in the history
* Correct comment position

* Enable self-resurrection spells for 1.5 client

Fixes build errors related to self-resurrection and enables self-
resurrection to work on the 1.5 client, per the 1.6 patch notes.
> Self-resurrection spells show their name on the button in the release
> spirit dialog.
The update field PLAYER_SELF_RES_SPELL did not exist in patch 1.5, and
so the ID of the self-resurrection spell was not sent to the client.
Decompiled 1.5 client code shows that it instead checks the player flag
0x1000 (currently PLAYER_FLAGS_PARTIAL_PLAY_TIME) to determine whether
the player can self-resurrect, meaning this flag was repurposed on or
after patch 1.6. As this means we cannot store the spell ID in the
player's update fields, for these clients we instead store the ID purely
server-side to read after the player dies.
  • Loading branch information
codestothestars authored Aug 26, 2023
1 parent bc37c02 commit 8e35ae2
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 7 deletions.
14 changes: 14 additions & 0 deletions src/game/Handlers/SpellHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,9 @@ void WorldSession::HandleCancelChanneling(WorldPacket& recv_data)

void WorldSession::HandleSelfResOpcode(WorldPacket& /*recv_data*/)
{
// World of Warcraft Client Patch 1.6.0 (2005-07-12)
// - Self-resurrection spells show their name on the button in the release spirit dialog.
#if SUPPORTED_CLIENT_BUILD >= CLIENT_BUILD_1_6_1
if (_player->GetUInt32Value(PLAYER_SELF_RES_SPELL))
{
SpellEntry const* spellInfo = sSpellMgr.GetSpellEntry(_player->GetUInt32Value(PLAYER_SELF_RES_SPELL));
Expand All @@ -504,4 +507,15 @@ void WorldSession::HandleSelfResOpcode(WorldPacket& /*recv_data*/)

_player->SetUInt32Value(PLAYER_SELF_RES_SPELL, 0);
}
#else
if (_player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CAN_SELF_RESURRECT))
{
SpellEntry const* spellInfo = sSpellMgr.GetSpellEntry(_player->GetResurrectionSpellId());
if (spellInfo)
_player->CastSpell(_player, spellInfo, false);

_player->SetResurrectionSpellId(0);
_player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_CAN_SELF_RESURRECT);
}
#endif
}
28 changes: 25 additions & 3 deletions src/game/Objects/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,10 @@ Player::Player(WorldSession* session) : Unit(),

m_lastFromClientCastedSpellID = 0;

#if SUPPORTED_CLIENT_BUILD < CLIENT_BUILD_1_6_1
m_resurrectionSpellId = 0;
#endif

// Anti undermap
m_undermapPosValid = false;
session->InitCheatData(this);
Expand Down Expand Up @@ -1933,12 +1937,18 @@ void Player::SetDeathState(DeathState s)
if (ObjectGuid lootGuid = GetLootGuid())
GetSession()->DoLootRelease(lootGuid);

// World of Warcraft Client Patch 1.6.0 (2005-07-12)
// - Self-resurrection spells show their name on the button in the release spirit dialog.
#if SUPPORTED_CLIENT_BUILD >= CLIENT_BUILD_1_6_1
// save value before aura remove in Unit::SetDeathState
ressSpellId = GetUInt32Value(PLAYER_SELF_RES_SPELL);
#else
ressSpellId = GetResurrectionSpellId();
#endif

// passive spell
if (!ressSpellId)
ressSpellId = GetResurrectionSpellId();
ressSpellId = SelectResurrectionSpellId();

if (m_zoneScript)
m_zoneScript->OnPlayerDeath(this);
Expand All @@ -1948,12 +1958,24 @@ void Player::SetDeathState(DeathState s)

// restore resurrection spell id for player after aura remove
if (s == JUST_DIED && cur && ressSpellId)
{
#if SUPPORTED_CLIENT_BUILD >= CLIENT_BUILD_1_6_1
SetUInt32Value(PLAYER_SELF_RES_SPELL, ressSpellId);
#else
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_CAN_SELF_RESURRECT);
SetResurrectionSpellId(ressSpellId);
#endif
}

if (IsAlive() && !cur)
{
//clear aura case after resurrection by another way (spells will be applied before next death)
//clear self-resurrection state after resurrection by another way (spells will be applied before next death)
#if SUPPORTED_CLIENT_BUILD >= CLIENT_BUILD_1_6_1
SetUInt32Value(PLAYER_SELF_RES_SPELL, 0);
#else
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_CAN_SELF_RESURRECT);
SetResurrectionSpellId(0);
#endif

UpdatePvPContested(false, true);
}
Expand Down Expand Up @@ -20012,7 +20034,7 @@ void Player::RemoveItemDependentAurasAndCasts(Item* pItem)
}
}

uint32 Player::GetResurrectionSpellId() const
uint32 Player::SelectResurrectionSpellId() const
{
// search priceless resurrection possibilities
uint32 prio = 0;
Expand Down
13 changes: 11 additions & 2 deletions src/game/Objects/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ enum PlayerFlags
PLAYER_FLAGS_PVP_DESIRED = 0x00000200, // Stores player's permanent PvP flag preference
PLAYER_FLAGS_HIDE_HELM = 0x00000400,
PLAYER_FLAGS_HIDE_CLOAK = 0x00000800,
#if SUPPORTED_CLIENT_BUILD < CLIENT_BUILD_1_6_1
PLAYER_FLAGS_CAN_SELF_RESURRECT = 0x00001000,
#endif
PLAYER_FLAGS_PARTIAL_PLAY_TIME = 0x00001000, // played long time
PLAYER_FLAGS_NO_PLAY_TIME = 0x00002000, // played too long time
PLAYER_FLAGS_UNK15 = 0x00004000,
Expand Down Expand Up @@ -1501,7 +1504,9 @@ class Player final: public Unit
SpellModList m_spellMods[MAX_SPELLMOD];
uint32 m_lastFromClientCastedSpellID;
std::map<uint32, ItemSetEffect> m_itemSetEffects;

#if SUPPORTED_CLIENT_BUILD < CLIENT_BUILD_1_6_1
uint32 m_resurrectionSpellId;
#endif
bool IsNeedCastPassiveLikeSpellAtLearn(SpellEntry const* spellInfo) const;
void SendInitialSpells() const;
bool AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled);
Expand Down Expand Up @@ -2263,7 +2268,11 @@ class Player final: public Unit
void SpawnCorpseBones();
Corpse* CreateCorpse();
void KillPlayer();
uint32 GetResurrectionSpellId() const;
#if SUPPORTED_CLIENT_BUILD < CLIENT_BUILD_1_6_1
uint32 GetResurrectionSpellId() const { return m_resurrectionSpellId; }
void SetResurrectionSpellId(uint32 resurrectionSpellId) { m_resurrectionSpellId = resurrectionSpellId; }
#endif
uint32 SelectResurrectionSpellId() const;
void ResurrectPlayer(float restore_percent, bool applySickness = false);
void BuildPlayerRepop();
void RepopAtGraveyard();
Expand Down
24 changes: 22 additions & 2 deletions src/game/Objects/Unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1107,9 +1107,17 @@ void Unit::Kill(Unit* pVictim, SpellEntry const* spellProto, bool durabilityLoss
pVictim->SetHealth(0);
DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "SET JUST_DIED");
pVictim->SetDeathState(JUST_DIED);
// Nostalrius: Instantly send values update for health

// World of Warcraft Client Patch 1.6.0 (2005-07-12)
// - Self-resurrection spells show their name on the button in the release spirit dialog.
#if SUPPORTED_CLIENT_BUILD >= CLIENT_BUILD_1_6_1
if (pPlayerVictim && pVictim->GetUInt32Value(PLAYER_SELF_RES_SPELL))
pVictim->DirectSendPublicValueUpdate(PLAYER_SELF_RES_SPELL);
#else
if (pPlayerVictim && pVictim->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CAN_SELF_RESURRECT))
pVictim->DirectSendPublicValueUpdate(PLAYER_FLAGS);
#endif
// Nostalrius: Instantly send values update for health
pVictim->DirectSendPublicValueUpdate(UNIT_FIELD_HEALTH);
}
else
Expand All @@ -1135,15 +1143,27 @@ void Unit::Kill(Unit* pVictim, SpellEntry const* spellProto, bool durabilityLoss
if (spiritOfRedemtionTalentImmune)
{
// save value before aura remove
uint32 ressSpellId = pVictim->GetUInt32Value(PLAYER_SELF_RES_SPELL);
uint32 ressSpellId = 0;
#if SUPPORTED_CLIENT_BUILD >= CLIENT_BUILD_1_6_1
ressSpellId = pVictim->GetUInt32Value(PLAYER_SELF_RES_SPELL);
if (!ressSpellId)
ressSpellId = ((Player*)pVictim)->SelectResurrectionSpellId();
#else
if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CAN_SELF_RESURRECT))
ressSpellId = ((Player*)pVictim)->GetResurrectionSpellId();
#endif

//Remove all expected to remove at death auras (most important negative case like DoT or periodic triggers)
pVictim->RemoveAllAurasOnDeath();

// restore for use at real death
#if SUPPORTED_CLIENT_BUILD >= CLIENT_BUILD_1_6_1
pVictim->SetUInt32Value(PLAYER_SELF_RES_SPELL, ressSpellId);
#else
pPlayerVictim->SetResurrectionSpellId(ressSpellId);
if (ressSpellId)
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_CAN_SELF_RESURRECT);
#endif

// FORM_SPIRITOFREDEMPTION and related auras
pVictim->AddAura(27827, ADD_AURA_NO_OPTION, pVictim);
Expand Down

0 comments on commit 8e35ae2

Please sign in to comment.