From 3af11ad35564df372ac29d8ad717737f861063bc Mon Sep 17 00:00:00 2001 From: ephphatha Date: Tue, 21 Jun 2022 23:48:43 +1000 Subject: [PATCH] Use the same function when checking and actually dropping an item --- Source/controls/plrctrls.cpp | 10 +-- Source/diablo.cpp | 2 +- Source/inv.cpp | 121 +++++++++++++---------------------- Source/inv.h | 25 ++++---- 4 files changed, 63 insertions(+), 95 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 9497ac0ad..794b46db5 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -1831,13 +1831,9 @@ bool TryDropItem() Point position = myPlayer.position.future; Direction direction = myPlayer._pdir; - if (!CanPut(position, direction)) { - direction = Opposite(direction); - // if we can't drop in front of the player, can we drop it behind? - if (!CanPut(position, direction)) { - myPlayer.Say(HeroSpeech::WhereWouldIPutThis); - return false; - } + if (!FindAdjacentPositionForItem(position, direction)) { + myPlayer.Say(HeroSpeech::WhereWouldIPutThis); + return false; } NetSendCmdPItem(true, CMD_PUTITEM, position + direction, myPlayer.HoldItem); diff --git a/Source/diablo.cpp b/Source/diablo.cpp index ad22947fb..b0f1b968c 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -342,7 +342,7 @@ void LeftMouseDown(int wParam) CheckSBook(); } else if (!MyPlayer->HoldItem.isEmpty()) { Point currentPosition = MyPlayer->position.tile; - if (CanPut(currentPosition, GetDirection(currentPosition, cursPosition))) { + if (FindAdjacentPositionForItem(currentPosition, GetDirection(currentPosition, cursPosition))) { NetSendCmdPItem(true, CMD_PUTITEM, cursPosition, MyPlayer->HoldItem); NewCursor(CURSOR_HAND); } diff --git a/Source/inv.cpp b/Source/inv.cpp index 08c026266..bbe7e5c31 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -972,51 +972,6 @@ void CleanupItems(int ii) } } -bool PutItem(Player &player, Point &position) -{ - if (ActiveItemCount >= MAXITEMS) - return false; - - Direction d = GetDirection(player.position.tile, position); - - if (position.WalkingDistance(player.position.tile) > 1) { - position = player.position.tile + d; - } - if (CanPut(position)) - return true; - - position = player.position.tile + Left(d); - if (CanPut(position)) - return true; - - position = player.position.tile + Right(d); - if (CanPut(position)) - return true; - - position = player.position.tile + Left(Left(d)); - if (CanPut(position)) - return true; - - position = player.position.tile + Right(Right(d)); - if (CanPut(position)) - return true; - - position = player.position.tile + Left(Left(Left(d))); - if (CanPut(position)) - return true; - - position = player.position.tile + Right(Right(Right(d))); - if (CanPut(position)) - return true; - - position = player.position.tile + Opposite(d); - if (CanPut(position)) - return true; - - position = player.position.tile; - return CanPut(position); -} - bool CanUseStaff(Item &staff, spell_id spell) { return !staff.isEmpty() @@ -1610,6 +1565,41 @@ void InvGetItem(Player &player, int ii) pcursitem = -1; } +std::optional FindAdjacentPositionForItem(Point origin, Direction facing) +{ + if (ActiveItemCount >= MAXITEMS) + return {}; + + if (CanPut(origin + facing)) + return origin + facing; + + if (CanPut(origin + Left(facing))) + return origin + Left(facing); + + if (CanPut(origin + Right(facing))) + return origin + Right(facing); + + if (CanPut(origin + Left(Left(facing)))) + return origin + Left(Left(facing)); + + if (CanPut(origin + Right(Right(facing)))) + return origin + Right(Right(facing)); + + if (CanPut(origin + Left(Left(Left(facing))))) + return origin + Left(Left(Left(facing))); + + if (CanPut(origin + Right(Right(Right(facing))))) + return origin + Right(Right(Right(facing))); + + if (CanPut(origin + Opposite(facing))) + return origin + Opposite(facing); + + if (CanPut(origin)) + return origin; + + return {}; +} + void AutoGetItem(int pnum, Item *itemPointer, int ii) { Item &item = *itemPointer; @@ -1738,27 +1728,7 @@ bool CanPut(Point position) return true; } -bool CanPut(Point position, Direction dir) -{ - if (ActiveItemCount >= MAXITEMS) - return false; - - if (CanPut(position + dir)) { - return true; - } - - if (CanPut(position + Left(dir))) { - return true; - } - - if (CanPut(position + Right(dir))) { - return true; - } - - return CanPut(position); -} - -int InvPutItem(Player &player, Point position, Item &item) +int InvPutItem(const Player &player, Point position, const Item &item) { if (player.isOnLevel(0)) { if (item.IDidx == IDI_RUNEBOMB && OpensHive(position)) { @@ -1771,18 +1741,18 @@ int InvPutItem(Player &player, Point position, Item &item) } } - if (!PutItem(player, position)) + std::optional itemTile = FindAdjacentPositionForItem(player.position.tile, GetDirection(player.position.tile, position)); + if (!itemTile) return -1; - assert(CanPut(position)); int ii = AllocateItem(); - dItem[position.x][position.y] = ii + 1; + dItem[itemTile->x][itemTile->y] = ii + 1; Items[ii] = item; - Items[ii].position = position; + Items[ii].position = *itemTile; RespawnItem(Items[ii], true); - if (currlevel == 21 && position == CornerStone.position) { + if (currlevel == 21 && *itemTile == CornerStone.position) { CornerStone.item = Items[ii]; InitQTextMsg(TEXT_CORNSTN); Quests[Q_CORNSTN]._qlog = false; @@ -1792,7 +1762,7 @@ int InvPutItem(Player &player, Point position, Item &item) return ii; } -int SyncPutItem(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 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) { if (player.isOnLevel(0)) { if (idx == IDI_RUNEBOMB && OpensHive(position)) @@ -1801,12 +1771,11 @@ int SyncPutItem(Player &player, Point position, int idx, uint16_t icreateinfo, i return -1; } - if (!PutItem(player, position)) + std::optional itemTile = FindAdjacentPositionForItem(player.position.tile, GetDirection(player.position.tile, position)); + if (!itemTile) return -1; - assert(CanPut(position)); - - return SyncDropItem(position, idx, icreateinfo, iseed, id, dur, mdur, ch, mch, ivalue, ibuff, toHit, maxDam, minStr, minMag, minDex, ac); + return SyncDropItem(*itemTile, idx, icreateinfo, iseed, id, dur, mdur, ch, mch, ivalue, ibuff, toHit, maxDam, minStr, minMag, minDex, 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) diff --git a/Source/inv.h b/Source/inv.h index 91e6ef436..7ebaa2d88 100644 --- a/Source/inv.h +++ b/Source/inv.h @@ -188,6 +188,18 @@ void CheckInvItem(bool isShiftHeld = false, bool isCtrlHeld = false); */ void CheckInvScrn(bool isShiftHeld, bool isCtrlHeld); void InvGetItem(Player &player, int ii); + +/** + * @brief Returns the first free space that can take an item preferencing tiles in front of the current position + * + * The search starts with the adjacent tile in the desired direction and alternates sides until it ends up checking the + * opposite tile, before finally checking the origin tile + * + * @param origin center tile of the search space + * @param facing direction of the adjacent tile to check first + * @return the first valid point or an empty optional + */ +std::optional FindAdjacentPositionForItem(Point origin, Direction facing); void AutoGetItem(int pnum, Item *item, int ii); /** @@ -207,17 +219,8 @@ void SyncGetItem(Point position, int32_t iseed, _item_indexes idx, uint16_t ci); */ bool CanPut(Point position); -/** - * @brief Checks for free spaces in the three "adjacent" tiles in the given direction and also the given position. - * @see CanPut - * @param position base tile coordinates - * @param facing direction to check, tiles "left" and "right" of this direction will also be checked. - * @return True if any of the four tiles checked can accept an item, false if all blocked - */ -bool CanPut(Point position, Direction facing); - -int InvPutItem(Player &player, Point position, Item &item); -int SyncPutItem(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 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);