From 279e92e69c1f91eecc8f2e9266bccf8f230a8c3c Mon Sep 17 00:00:00 2001 From: obligaron Date: Sat, 26 Feb 2022 16:33:03 +0100 Subject: [PATCH] Checks conditions for spell again, cause initial check was done when spell was queued --- Source/inv.cpp | 17 ++++------------- Source/inv.h | 4 ++-- Source/player.cpp | 25 +++++++++++++++++++++++-- Source/spells.cpp | 3 --- test/inv_test.cpp | 29 ++++++++++++----------------- 5 files changed, 41 insertions(+), 37 deletions(-) diff --git a/Source/inv.cpp b/Source/inv.cpp index ab3e71d9d..66ac4dbb4 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -1897,15 +1897,12 @@ int8_t CheckInvHLight() return rv; } -bool UseScroll(const spell_id spell) +bool UseScroll(Player &player, spell_id spell) { - if (pcurs != CURSOR_HAND) - return false; - if (leveltype == DTYPE_TOWN && !spelldata[spell].sTownSpell) return false; - return HasInventoryOrBeltItem(*MyPlayer, [spell](const Item &item) { + return HasInventoryOrBeltItem(player, [spell](const Item &item) { return item.isScrollOf(spell); }); } @@ -1921,15 +1918,9 @@ void UseStaffCharge(Player &player) CalcPlrStaff(player); } -bool UseStaff(const spell_id spell) +bool CanUseStaff(Player &player, spell_id spellId) { - if (pcurs != CURSOR_HAND) { - return false; - } - - Player &myPlayer = *MyPlayer; - - return CanUseStaff(myPlayer.InvBody[INVLOC_HAND_LEFT], spell); + return CanUseStaff(player.InvBody[INVLOC_HAND_LEFT], spellId); } Item &GetInventoryItem(Player &player, int location) diff --git a/Source/inv.h b/Source/inv.h index 7f0017171..5629e8d05 100644 --- a/Source/inv.h +++ b/Source/inv.h @@ -225,9 +225,9 @@ int InvPutItem(const Player &player, Point position, const Item &item); int SyncPutItem(const Player &player, Point position, int idx, uint16_t icreateinfo, int iseed, int Id, int dur, int mdur, int ch, int mch, int ivalue, uint32_t ibuff, int toHit, int maxDam, int minStr, int minMag, int minDex, int ac); int SyncDropItem(Point position, int idx, uint16_t icreateinfo, int iseed, int id, int dur, int mdur, int ch, int mch, int ivalue, uint32_t ibuff, int toHit, int maxDam, int minStr, int minMag, int minDex, int ac); int8_t CheckInvHLight(); -bool UseScroll(spell_id spell); +bool UseScroll(Player &player, spell_id spell); void UseStaffCharge(Player &player); -bool UseStaff(spell_id spell); +bool CanUseStaff(Player &player, spell_id spellId); Item &GetInventoryItem(Player &player, int location); bool UseInvItem(int pnum, int cii); void DoTelekinesis(); diff --git a/Source/player.cpp b/Source/player.cpp index 4b72de6ea..c712daeb4 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -498,6 +498,27 @@ void StartSpell(Player &player, Direction d, WorldTileCoord cx, WorldTileCoord c return; } + // Checks conditions for spell again, cause initial check was done when spell was queued and the parameters could be changed meanwhile + bool isValid = true; + switch (player.queuedSpell.spellType) { + case RSPLTYPE_SKILL: + case RSPLTYPE_SPELL: + isValid = CheckSpell(player, player.queuedSpell.spellId, player.queuedSpell.spellType, true) == SpellCheckResult::Success; + break; + case RSPLTYPE_SCROLL: + isValid = UseScroll(player, player.queuedSpell.spellId); + break; + case RSPLTYPE_CHARGES: + isValid = CanUseStaff(player, player.queuedSpell.spellId); + break; + case RSPLTYPE_INVALID: + // Scroll is removed previous, so don't check again + isValid = true; + break; + } + if (!isValid) + return; + auto animationFlags = AnimationDistributionFlags::ProcessAnimationPending; if (player._pmode == PM_SPELL) animationFlags = static_cast(animationFlags | AnimationDistributionFlags::RepeatedAction); @@ -3448,10 +3469,10 @@ void CheckPlrSpell(bool isShiftHeld, spell_id spellID, spell_type spellType) addflag = spellcheck == SpellCheckResult::Success; break; case RSPLTYPE_SCROLL: - addflag = UseScroll(spellID); + addflag = pcurs == CURSOR_HAND && UseScroll(myPlayer, spellID); break; case RSPLTYPE_CHARGES: - addflag = UseStaff(spellID); + addflag = pcurs == CURSOR_HAND && CanUseStaff(myPlayer, spellID); break; case RSPLTYPE_INVALID: return; diff --git a/Source/spells.cpp b/Source/spells.cpp index dbf1918ae..4f6a58bda 100644 --- a/Source/spells.cpp +++ b/Source/spells.cpp @@ -173,9 +173,6 @@ int GetManaAmount(const Player &player, spell_id sn) void UseMana(Player &player, spell_id sn) { - if (&player != MyPlayer) - return; - switch (player.executedSpell.spellType) { case RSPLTYPE_SKILL: case RSPLTYPE_INVALID: diff --git a/test/inv_test.cpp b/test/inv_test.cpp index c00e9b3e7..e58b7d456 100644 --- a/test/inv_test.cpp +++ b/test/inv_test.cpp @@ -32,14 +32,14 @@ TEST(Inv, UseScroll_from_inventory) { set_up_scroll(MyPlayer->InvList[2], SPL_FIREBOLT); MyPlayer->_pNumInv = 5; - EXPECT_TRUE(UseScroll(MyPlayer->_pRSpell)); + EXPECT_TRUE(UseScroll(*MyPlayer, SPL_FIREBOLT)); } // Test that the scroll is used in the belt in correct conditions TEST(Inv, UseScroll_from_belt) { set_up_scroll(MyPlayer->SpdList[2], SPL_FIREBOLT); - EXPECT_TRUE(UseScroll(MyPlayer->_pRSpell)); + EXPECT_TRUE(UseScroll(*MyPlayer, SPL_FIREBOLT)); } // Test that the scroll is not used in the inventory for each invalid condition @@ -50,25 +50,24 @@ TEST(Inv, UseScroll_from_inventory_invalid_conditions) MyPlayer->SpdList[i].clear(); } - set_up_scroll(MyPlayer->InvList[2], SPL_FIREBOLT); - pcurs = CURSOR_IDENTIFY; - EXPECT_FALSE(UseScroll(MyPlayer->_pRSpell)); + // Adjust inventory size + MyPlayer->_pNumInv = 5; set_up_scroll(MyPlayer->InvList[2], SPL_FIREBOLT); leveltype = DTYPE_TOWN; - EXPECT_FALSE(UseScroll(MyPlayer->_pRSpell)); + EXPECT_FALSE(UseScroll(*MyPlayer, SPL_FIREBOLT)); set_up_scroll(MyPlayer->InvList[2], SPL_FIREBOLT); MyPlayer->_pRSpell = static_cast(SPL_HEAL); - EXPECT_FALSE(UseScroll(MyPlayer->_pRSpell)); + EXPECT_FALSE(UseScroll(*MyPlayer, SPL_HEAL)); set_up_scroll(MyPlayer->InvList[2], SPL_FIREBOLT); MyPlayer->InvList[2]._iMiscId = IMISC_STAFF; - EXPECT_FALSE(UseScroll(MyPlayer->_pRSpell)); + EXPECT_FALSE(UseScroll(*MyPlayer, SPL_FIREBOLT)); set_up_scroll(MyPlayer->InvList[2], SPL_FIREBOLT); MyPlayer->InvList[2].clear(); - EXPECT_FALSE(UseScroll(MyPlayer->_pRSpell)); + EXPECT_FALSE(UseScroll(*MyPlayer, SPL_FIREBOLT)); } // Test that the scroll is not used in the belt for each invalid condition @@ -77,25 +76,21 @@ TEST(Inv, UseScroll_from_belt_invalid_conditions) // Disable the inventory to prevent using a scroll from the inventory MyPlayer->_pNumInv = 0; - set_up_scroll(MyPlayer->SpdList[2], SPL_FIREBOLT); - pcurs = CURSOR_IDENTIFY; - EXPECT_FALSE(UseScroll(MyPlayer->_pRSpell)); - set_up_scroll(MyPlayer->SpdList[2], SPL_FIREBOLT); leveltype = DTYPE_TOWN; - EXPECT_FALSE(UseScroll(MyPlayer->_pRSpell)); + EXPECT_FALSE(UseScroll(*MyPlayer, SPL_FIREBOLT)); set_up_scroll(MyPlayer->SpdList[2], SPL_FIREBOLT); MyPlayer->_pRSpell = static_cast(SPL_HEAL); - EXPECT_FALSE(UseScroll(MyPlayer->_pRSpell)); + EXPECT_FALSE(UseScroll(*MyPlayer, SPL_HEAL)); set_up_scroll(MyPlayer->SpdList[2], SPL_FIREBOLT); MyPlayer->SpdList[2]._iMiscId = IMISC_STAFF; - EXPECT_FALSE(UseScroll(MyPlayer->_pRSpell)); + EXPECT_FALSE(UseScroll(*MyPlayer, SPL_FIREBOLT)); set_up_scroll(MyPlayer->SpdList[2], SPL_FIREBOLT); MyPlayer->SpdList[2].clear(); - EXPECT_FALSE(UseScroll(MyPlayer->_pRSpell)); + EXPECT_FALSE(UseScroll(*MyPlayer, SPL_FIREBOLT)); } // Test gold calculation