diff --git a/Source/inv.cpp b/Source/inv.cpp index 3a11d8869..ab3e71d9d 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -1914,7 +1914,7 @@ void UseStaffCharge(Player &player) { auto &staff = player.InvBody[INVLOC_HAND_LEFT]; - if (!CanUseStaff(staff, player._pSpell)) + if (!CanUseStaff(staff, player.executedSpell.spellId)) return; staff._iCharges--; diff --git a/Source/inv.h b/Source/inv.h index e09391443..7f0017171 100644 --- a/Source/inv.h +++ b/Source/inv.h @@ -381,7 +381,7 @@ inline bool RemoveInventoryOrBeltItemById(Player &player, _item_indexes id) */ inline bool RemoveCurrentSpellScroll(Player &player) { - const spell_id spellId = player._pSpell; + const spell_id spellId = player.executedSpell.spellId; return RemoveInventoryOrBeltItem(player, [spellId](const Item &item) { return item.isScrollOf(spellId); }); diff --git a/Source/items.cpp b/Source/items.cpp index c97b9c8d9..a45f36a10 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -3911,9 +3911,9 @@ void UseItem(int pnum, item_misc_id mid, spell_id spl) NewCursor(CURSOR_TELEPORT); } else { ClrPlrPath(player); - player._pSpell = spl; - player._pSplType = RSPLTYPE_INVALID; - player._pSplFrom = 3; + player.queuedSpell.spellId = spl; + player.queuedSpell.spellType = RSPLTYPE_INVALID; + player.queuedSpell.spellFrom = 3; player.destAction = ACTION_SPELL; player.destParam1 = cursPosition.x; player.destParam2 = cursPosition.y; diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index c4df16ecc..02f174f02 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -359,9 +359,9 @@ void LoadPlayer(LoadHelper &file, Player &player) player._plid = file.NextLE(); player._pvid = file.NextLE(); - player._pSpell = static_cast(file.NextLE()); - player._pSplType = static_cast(file.NextLE()); - player._pSplFrom = file.NextLE(); + player.queuedSpell.spellId = static_cast(file.NextLE()); + player.queuedSpell.spellType = static_cast(file.NextLE()); + player.queuedSpell.spellFrom = file.NextLE(); file.Skip(2); // Alignment player._pTSpell = static_cast(file.NextLE()); file.Skip(); // Skip _pTSplType @@ -444,7 +444,7 @@ void LoadPlayer(LoadHelper &file, Player &player) player.position.temp.y = static_cast(tempPositionY); player.tempDirection = static_cast(file.NextLE()); - player.spellLevel = file.NextLE(); + player.queuedSpell.spellLevel = file.NextLE(); file.Skip(); // skip _pVar5, was used for storing position of a tile which should have its HorizontalMovingPlayer flag removed after walking player.position.offset2.deltaX = file.NextLE(); player.position.offset2.deltaY = file.NextLE(); @@ -550,6 +550,8 @@ void LoadPlayer(LoadHelper &file, Player &player) file.Skip(20); // Available bytes CalcPlrItemVals(player, false); + player.executedSpell = player.queuedSpell; // Ensures backwards compatibility + // Omit pointer _pNData // Omit pointer _pWData // Omit pointer _pAData @@ -1128,9 +1130,9 @@ void SavePlayer(SaveHelper &file, const Player &player) file.WriteLE(player._plid); file.WriteLE(player._pvid); - file.WriteLE(player._pSpell); - file.WriteLE(player._pSplType); - file.WriteLE(player._pSplFrom); + file.WriteLE(player.queuedSpell.spellId); + file.WriteLE(player.queuedSpell.spellType); + file.WriteLE(player.queuedSpell.spellFrom); file.Skip(2); // Alignment file.WriteLE(player._pTSpell); file.Skip(); // Skip _pTSplType @@ -1214,7 +1216,7 @@ void SavePlayer(SaveHelper &file, const Player &player) file.WriteLE(tempPositionY); file.WriteLE(static_cast(player.tempDirection)); - file.WriteLE(player.spellLevel); + file.WriteLE(player.queuedSpell.spellLevel); file.Skip(); // skip _pVar5, was used for storing position of a tile which should have its HorizontalMovingPlayer flag removed after walking file.WriteLE(player.position.offset2.deltaX); file.WriteLE(player.position.offset2.deltaY); diff --git a/Source/msg.cpp b/Source/msg.cpp index d7db24b78..2322e97ae 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -1141,9 +1141,9 @@ size_t OnSpellWall(const TCmd *pCmd, Player &player) player.destParam2 = position.y; player.destParam3 = message.wParam3; player.destParam4 = message.wParam4; - player._pSpell = spell; - player._pSplType = static_cast(message.wParam2); - player._pSplFrom = 0; + player.queuedSpell.spellId = spell; + player.queuedSpell.spellType = static_cast(message.wParam2); + player.queuedSpell.spellFrom = 0; return sizeof(message); } @@ -1179,8 +1179,8 @@ size_t OnSpellTile(const TCmd *pCmd, Player &player) player.destParam1 = position.x; player.destParam2 = position.y; player.destParam3 = message.wParam3; - player._pSpell = spell; - player._pSplType = static_cast(message.wParam2); + player.queuedSpell.spellId = spell; + player.queuedSpell.spellType = static_cast(message.wParam2); return sizeof(message); } @@ -1210,9 +1210,9 @@ size_t OnTargetSpellTile(const TCmd *pCmd, Player &player) player.destParam1 = position.x; player.destParam2 = position.y; player.destParam3 = message.wParam2; - player._pSpell = spell; - player._pSplType = RSPLTYPE_INVALID; - player._pSplFrom = 2; + player.queuedSpell.spellId = spell; + player.queuedSpell.spellType = RSPLTYPE_INVALID; + player.queuedSpell.spellFrom = 2; return sizeof(message); } @@ -1317,9 +1317,9 @@ size_t OnSpellMonster(const TCmd *pCmd, Player &player) player.destAction = ACTION_SPELLMON; player.destParam1 = message.wParam1; player.destParam2 = message.wParam4; - player._pSpell = spell; - player._pSplType = static_cast(message.wParam3); - player._pSplFrom = 0; + player.queuedSpell.spellId = spell; + player.queuedSpell.spellType = static_cast(message.wParam3); + player.queuedSpell.spellFrom = 0; return sizeof(message); } @@ -1353,9 +1353,9 @@ size_t OnSpellPlayer(const TCmd *pCmd, Player &player) player.destAction = ACTION_SPELLPLR; player.destParam1 = message.wParam1; player.destParam2 = message.wParam4; - player._pSpell = spell; - player._pSplType = static_cast(message.wParam3); - player._pSplFrom = 0; + player.queuedSpell.spellId = spell; + player.queuedSpell.spellType = static_cast(message.wParam3); + player.queuedSpell.spellFrom = 0; return sizeof(message); } @@ -1385,9 +1385,9 @@ size_t OnTargetSpellMonster(const TCmd *pCmd, Player &player) player.destAction = ACTION_SPELLMON; player.destParam1 = message.wParam1; player.destParam2 = message.wParam3; - player._pSpell = spell; - player._pSplType = RSPLTYPE_INVALID; - player._pSplFrom = 2; + player.queuedSpell.spellId = spell; + player.queuedSpell.spellType = RSPLTYPE_INVALID; + player.queuedSpell.spellFrom = 2; return sizeof(message); } @@ -1415,9 +1415,9 @@ size_t OnTargetSpellPlayer(const TCmd *pCmd, Player &player) player.destAction = ACTION_SPELLPLR; player.destParam1 = message.wParam1; player.destParam2 = message.wParam3; - player._pSpell = spell; - player._pSplType = RSPLTYPE_INVALID; - player._pSplFrom = 2; + player.queuedSpell.spellId = spell; + player.queuedSpell.spellType = RSPLTYPE_INVALID; + player.queuedSpell.spellFrom = 2; return sizeof(message); } @@ -2020,9 +2020,9 @@ size_t OnNova(const TCmd *pCmd, Player &player) if (gbBufferMsgs != 1) { if (player.isOnActiveLevel() && &player != MyPlayer && InDungeonBounds(position)) { ClrPlrPath(player); - player._pSpell = SPL_NOVA; - player._pSplType = RSPLTYPE_INVALID; - player._pSplFrom = 3; + player.queuedSpell.spellId = SPL_NOVA; + player.queuedSpell.spellType = RSPLTYPE_INVALID; + player.queuedSpell.spellFrom = 3; player.destAction = ACTION_SPELL; player.destParam1 = position.x; player.destParam2 = position.y; diff --git a/Source/player.cpp b/Source/player.cpp index bf920da70..4b72de6ea 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -384,7 +384,7 @@ void ClearStateVariables(Player &player) { player.position.temp = { 0, 0 }; player.tempDirection = Direction::South; - player.spellLevel = 0; + player.queuedSpell.spellLevel = 0; player.position.offset2 = { 0, 0 }; } @@ -501,9 +501,9 @@ void StartSpell(Player &player, Direction d, WorldTileCoord cx, WorldTileCoord c auto animationFlags = AnimationDistributionFlags::ProcessAnimationPending; if (player._pmode == PM_SPELL) animationFlags = static_cast(animationFlags | AnimationDistributionFlags::RepeatedAction); - NewPlrAnim(player, GetPlayerGraphicForSpell(player._pSpell), d, player._pSFrames, 1, animationFlags, 0, player._pSFNum); + NewPlrAnim(player, GetPlayerGraphicForSpell(player.queuedSpell.spellId), d, player._pSFrames, 1, animationFlags, 0, player._pSFNum); - PlaySfxLoc(spelldata[player._pSpell].sSFX, player.position.tile); + PlaySfxLoc(spelldata[player.queuedSpell.spellId].sSFX, player.position.tile); player._pmode = PM_SPELL; @@ -511,7 +511,8 @@ void StartSpell(Player &player, Direction d, WorldTileCoord cx, WorldTileCoord c SetPlayerOld(player); player.position.temp = WorldTilePosition { cx, cy }; - player.spellLevel = player.GetSpellLevel(player._pSpell); + player.queuedSpell.spellLevel = player.GetSpellLevel(player.queuedSpell.spellId); + player.executedSpell = player.queuedSpell; } void RespawnDeadItem(Item &&itm, Point target) @@ -1264,14 +1265,14 @@ bool DoSpell(Player &player) if (player.AnimInfo.currentFrame == player._pSFNum) { CastSpell( player.getId(), - player._pSpell, + player.executedSpell.spellId, player.position.tile.x, player.position.tile.y, player.position.temp.x, player.position.temp.y, - player.spellLevel); + player.executedSpell.spellLevel); - if (player._pSplFrom == 0) { + if (player.executedSpell.spellFrom == 0) { EnsureValidReadiedSpell(player); } } @@ -1525,22 +1526,22 @@ void CheckNewPath(Player &player, bool pmWillBeCalled) case ACTION_SPELL: d = GetDirection(player.position.tile, { player.destParam1, player.destParam2 }); StartSpell(player, d, player.destParam1, player.destParam2); - player.spellLevel = player.destParam3; + player.executedSpell.spellLevel = player.destParam3; break; case ACTION_SPELLWALL: StartSpell(player, static_cast(player.destParam3), player.destParam1, player.destParam2); player.tempDirection = static_cast(player.destParam3); - player.spellLevel = player.destParam4; + player.executedSpell.spellLevel = player.destParam4; break; case ACTION_SPELLMON: d = GetDirection(player.position.tile, monster->position.future); StartSpell(player, d, monster->position.future.x, monster->position.future.y); - player.spellLevel = player.destParam2; + player.executedSpell.spellLevel = player.destParam2; break; case ACTION_SPELLPLR: d = GetDirection(player.position.tile, target->position.future); StartSpell(player, d, target->position.future.x, target->position.future.y); - player.spellLevel = player.destParam2; + player.executedSpell.spellLevel = player.destParam2; break; case ACTION_OPERATE: if (IsPlayerAdjacentToObject(player, *object)) { @@ -2051,7 +2052,7 @@ player_graphic Player::getGraphic() const case PM_BLOCK: return player_graphic::Block; case PM_SPELL: - switch (spelldata[_pSpell].sType) { + switch (spelldata[executedSpell.spellId].sType) { case STYPE_FIRE: return player_graphic::Fire; case STYPE_LIGHTNING: @@ -2742,8 +2743,8 @@ void InitPlayer(Player &player, bool firstTime) if (&player == MyPlayer) LoadHotkeys(); player._pSBkSpell = SPL_INVALID; - player._pSpell = player._pRSpell; - player._pSplType = player._pRSplType; + player.queuedSpell.spellId = player._pRSpell; + player.queuedSpell.spellType = player._pRSplType; player.pManaShield = false; player.wReflections = 0; } diff --git a/Source/player.h b/Source/player.h index 0cd09d681..0a7fd8052 100644 --- a/Source/player.h +++ b/Source/player.h @@ -210,6 +210,14 @@ struct PlayerAnimationData { } }; +struct SpellCastInfo { + spell_id spellId; + spell_type spellType; + int8_t spellFrom; // TODO Create enum + /* @brief Used for spell level */ + int spellLevel; +}; + struct Player { Player() = default; Player(Player &&) noexcept = default; @@ -242,9 +250,10 @@ struct Player { float progressToNextGameTickWhenPreviewWasSet; int _plid; int _pvid; - spell_id _pSpell; - spell_type _pSplType; - int8_t _pSplFrom; // TODO Create enum + /* @brief next queued spell */ + SpellCastInfo queuedSpell; + /* @brief the spell that is currently casted */ + SpellCastInfo executedSpell; spell_id _pTSpell; spell_id _pRSpell; spell_type _pRSplType; @@ -295,8 +304,7 @@ struct Player { bool _pInfraFlag; /** Player's direction when ending movement. Also used for casting direction of SPL_FIREWALL. */ Direction tempDirection; - /** Used for spell level */ - int spellLevel; + bool _pLvlVisited[NUMLEVELS]; bool _pSLvlVisited[NUMLEVELS]; // only 10 used /** diff --git a/Source/spells.cpp b/Source/spells.cpp index 975e38593..dbf1918ae 100644 --- a/Source/spells.cpp +++ b/Source/spells.cpp @@ -176,7 +176,7 @@ void UseMana(Player &player, spell_id sn) if (&player != MyPlayer) return; - switch (player._pSplType) { + switch (player.executedSpell.spellType) { case RSPLTYPE_SKILL: case RSPLTYPE_INVALID: break; diff --git a/test/inv_test.cpp b/test/inv_test.cpp index d2a9a42a0..c00e9b3e7 100644 --- a/test/inv_test.cpp +++ b/test/inv_test.cpp @@ -198,7 +198,7 @@ TEST(Inv, RemoveCurrentSpellScroll_inventory) // Put a firebolt scroll into the inventory MyPlayer->_pNumInv = 1; - MyPlayer->_pSpell = static_cast(SPL_FIREBOLT); + MyPlayer->executedSpell.spellId = static_cast(SPL_FIREBOLT); MyPlayer->InvList[0]._itype = ItemType::Misc; MyPlayer->InvList[0]._iMiscId = IMISC_SCROLL; MyPlayer->InvList[0]._iSpell = SPL_FIREBOLT; @@ -216,7 +216,7 @@ TEST(Inv, RemoveCurrentSpellScroll_belt) MyPlayer->SpdList[i].clear(); } // Put a firebolt scroll into the belt - MyPlayer->_pSpell = static_cast(SPL_FIREBOLT); + MyPlayer->executedSpell.spellId = static_cast(SPL_FIREBOLT); MyPlayer->SpdList[3]._itype = ItemType::Misc; MyPlayer->SpdList[3]._iMiscId = IMISC_SCROLL; MyPlayer->SpdList[3]._iSpell = SPL_FIREBOLT; diff --git a/test/player_test.cpp b/test/player_test.cpp index 64e2cc70f..6a4ad4769 100644 --- a/test/player_test.cpp +++ b/test/player_test.cpp @@ -136,9 +136,9 @@ static void AssertPlayer(Player &player) ASSERT_EQ(player._pmode, 0); ASSERT_EQ(Count8(player.walkpath, MaxPathLength), 0); - ASSERT_EQ(player._pSpell, 0); - ASSERT_EQ(player._pSplType, 0); - ASSERT_EQ(player._pSplFrom, 0); + ASSERT_EQ(player.queuedSpell.spellId, 0); + ASSERT_EQ(player.queuedSpell.spellType, 0); + ASSERT_EQ(player.queuedSpell.spellFrom, 0); ASSERT_EQ(player._pTSpell, 0); ASSERT_EQ(player._pRSpell, 28); ASSERT_EQ(player._pRSplType, 0); diff --git a/test/writehero_test.cpp b/test/writehero_test.cpp index bd0eea859..5904de54f 100644 --- a/test/writehero_test.cpp +++ b/test/writehero_test.cpp @@ -268,9 +268,9 @@ static void AssertPlayer(Player &player) ASSERT_EQ(player.AnimInfo.tickCounterOfCurrentFrame, 1); ASSERT_EQ(player.AnimInfo.numberOfFrames, 20); ASSERT_EQ(player.AnimInfo.currentFrame, 0); - ASSERT_EQ(player._pSpell, -1); - ASSERT_EQ(player._pSplType, 4); - ASSERT_EQ(player._pSplFrom, 0); + ASSERT_EQ(player.queuedSpell.spellId, -1); + ASSERT_EQ(player.queuedSpell.spellType, 4); + ASSERT_EQ(player.queuedSpell.spellFrom, 0); ASSERT_EQ(player._pTSpell, 0); ASSERT_EQ(player._pRSpell, -1); ASSERT_EQ(player._pRSplType, 4);