From 0ce76a3f137326bd1f536389fdd0d0de5a1bd6dd Mon Sep 17 00:00:00 2001 From: ephphatha Date: Thu, 28 Jul 2022 19:50:23 +1000 Subject: [PATCH] Add Object lookup method to mimic map::at() --- Source/controls/plrctrls.cpp | 2 +- Source/cursor.cpp | 6 +++--- Source/debug.cpp | 4 ++-- Source/engine/path.cpp | 2 +- Source/engine/render/scrollrt.cpp | 2 +- Source/levels/setmaps.cpp | 22 +++++++++++----------- Source/missiles.cpp | 6 +++--- Source/msg.cpp | 6 +++--- Source/objects.cpp | 22 +++++++++++----------- Source/objects.h | 16 ++++++++++++++-- Source/player.cpp | 6 +++--- 11 files changed, 53 insertions(+), 41 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 1894d317c..a52193052 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -178,7 +178,7 @@ void FindItemOrObject() } for (Point targetPosition : searchArea) { - Object *object = ObjectAtPosition(targetPosition); + Object *object = FindObjectAtPosition(targetPosition); if (object == nullptr || object->_oSelFlag == 0) { // No object or non-interactive object continue; diff --git a/Source/cursor.cpp b/Source/cursor.cpp index 7cd4f875f..68ff96b80 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -612,18 +612,18 @@ void CheckCursMove() // No monsters or players under the cursor, try find an object starting with the tile below the current tile (tall // objects like doors) Point testPosition = currentTile + Direction::South; - Object *object = ObjectAtPosition(testPosition); + Object *object = FindObjectAtPosition(testPosition); if (object == nullptr || object->_oSelFlag < 2) { // Either no object or can't interact from the test position, try the current tile testPosition = currentTile; - object = ObjectAtPosition(testPosition); + object = FindObjectAtPosition(testPosition); if (object == nullptr || IsNoneOf(object->_oSelFlag, 1, 3)) { // Still no object (that could be activated from this position), try the tile to the bottom left or right // (whichever is closest to the cursor as determined when we set flipflag earlier) testPosition = currentTile + (flipflag ? Direction::SouthWest : Direction::SouthEast); - object = ObjectAtPosition(testPosition); + object = FindObjectAtPosition(testPosition); if (object != nullptr && object->_oSelFlag < 2) { // Found an object but it's not in range, clear the pointer diff --git a/Source/debug.cpp b/Source/debug.cpp index 7bf9d364c..364df73d6 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -334,7 +334,7 @@ std::string ExportDun(const string_view parameter) for (int y = 16; y < MAXDUNY - 16; y++) { for (int x = 16; x < MAXDUNX - 16; x++) { uint16_t objectId = 0; - Object *object = ObjectAtPosition({ x, y }, false); + Object *object = FindObjectAtPosition({ x, y }, false); if (object != nullptr) { for (int i = 0; i < 147; i++) { if (ObjTypeConv[i] == object->_otype) { @@ -1077,7 +1077,7 @@ bool GetDebugGridText(Point dungeonCoords, char *debugGridTextBuffer) return true; case DebugGridTextItem::objectindex: { info = 0; - Object *object = ObjectAtPosition(dungeonCoords); + Object *object = FindObjectAtPosition(dungeonCoords); if (object != nullptr) { info = static_cast(object->_otype); } diff --git a/Source/engine/path.cpp b/Source/engine/path.cpp index afb477763..bf93e0eb9 100644 --- a/Source/engine/path.cpp +++ b/Source/engine/path.cpp @@ -327,7 +327,7 @@ bool IsTileSolid(Point position) bool IsTileWalkable(Point position, bool ignoreDoors) { - Object *object = ObjectAtPosition(position); + Object *object = FindObjectAtPosition(position); if (object != nullptr) { if (ignoreDoors && object->IsDoor()) { return true; diff --git a/Source/engine/render/scrollrt.cpp b/Source/engine/render/scrollrt.cpp index 54e0b9b08..1b1f7b606 100644 --- a/Source/engine/render/scrollrt.cpp +++ b/Source/engine/render/scrollrt.cpp @@ -603,7 +603,7 @@ void DrawObject(const Surface &out, Point tilePosition, Point targetBufferPositi return; } - Object *object = ObjectAtPosition(tilePosition); + Object *object = FindObjectAtPosition(tilePosition); if (object == nullptr) { return; } diff --git a/Source/levels/setmaps.cpp b/Source/levels/setmaps.cpp index a3d9a54b7..958f81fa0 100644 --- a/Source/levels/setmaps.cpp +++ b/Source/levels/setmaps.cpp @@ -33,29 +33,29 @@ namespace { void AddSKingObjs() { constexpr Rectangle SmallSecretRoom { { 20, 7 }, { 3, 3 } }; - ObjectAtPosition({ 64, 34 })->InitializeLoadedObject(SmallSecretRoom, 1); + ObjectAtPosition({ 64, 34 }).InitializeLoadedObject(SmallSecretRoom, 1); constexpr Rectangle Gate { { 20, 14 }, { 1, 2 } }; - ObjectAtPosition({ 64, 59 })->InitializeLoadedObject(Gate, 2); + ObjectAtPosition({ 64, 59 }).InitializeLoadedObject(Gate, 2); constexpr Rectangle LargeSecretRoom { { 8, 1 }, { 7, 10 } }; - ObjectAtPosition({ 27, 37 })->InitializeLoadedObject(LargeSecretRoom, 3); - ObjectAtPosition({ 46, 35 })->InitializeLoadedObject(LargeSecretRoom, 3); - ObjectAtPosition({ 49, 53 })->InitializeLoadedObject(LargeSecretRoom, 3); - ObjectAtPosition({ 27, 53 })->InitializeLoadedObject(LargeSecretRoom, 3); + ObjectAtPosition({ 27, 37 }).InitializeLoadedObject(LargeSecretRoom, 3); + ObjectAtPosition({ 46, 35 }).InitializeLoadedObject(LargeSecretRoom, 3); + ObjectAtPosition({ 49, 53 }).InitializeLoadedObject(LargeSecretRoom, 3); + ObjectAtPosition({ 27, 53 }).InitializeLoadedObject(LargeSecretRoom, 3); } void AddSChamObjs() { - ObjectAtPosition({ 37, 30 })->InitializeLoadedObject({ { 17, 0 }, { 4, 5 } }, 1); - ObjectAtPosition({ 37, 46 })->InitializeLoadedObject({ { 13, 0 }, { 3, 5 } }, 2); + ObjectAtPosition({ 37, 30 }).InitializeLoadedObject({ { 17, 0 }, { 4, 5 } }, 1); + ObjectAtPosition({ 37, 46 }).InitializeLoadedObject({ { 13, 0 }, { 3, 5 } }, 2); } void AddVileObjs() { - ObjectAtPosition({ 26, 45 })->InitializeLoadedObject({ { 1, 1 }, { 8, 9 } }, 1); - ObjectAtPosition({ 45, 46 })->InitializeLoadedObject({ { 11, 1 }, { 9, 9 } }, 2); - ObjectAtPosition({ 35, 36 })->InitializeLoadedObject({ { 7, 11 }, { 6, 7 } }, 3); + ObjectAtPosition({ 26, 45 }).InitializeLoadedObject({ { 1, 1 }, { 8, 9 } }, 1); + ObjectAtPosition({ 45, 46 }).InitializeLoadedObject({ { 11, 1 }, { 9, 9 } }, 2); + ObjectAtPosition({ 35, 36 }).InitializeLoadedObject({ { 7, 11 }, { 6, 7 } }, 3); } void SetMapTransparency(const char *path) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index adc90422c..966eb9965 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -439,7 +439,7 @@ void CheckMissileCol(Missile &missile, int minDamage, int maxDamage, bool isDama } if (IsMissileBlockedByTile({ mx, my })) { - Object *object = ObjectAtPosition({ mx, my }); + Object *object = FindObjectAtPosition({ mx, my }); if (object != nullptr && object->IsBreakable()) { BreakObjectMissile(*object); } @@ -686,7 +686,7 @@ bool IsMissileBlockedByTile(Point tile) return true; } - Object *object = ObjectAtPosition(tile); + Object *object = FindObjectAtPosition(tile); // _oMissFlag is true if the object allows missiles to pass through so we need to invert the check here... return object != nullptr && !object->_oMissFlag; } @@ -2844,7 +2844,7 @@ void MI_Lightball(Missile &missile) missile._mirange = j; if (missile.position.tile == targetPosition) { - Object *object = ObjectAtPosition(targetPosition); + Object *object = FindObjectAtPosition(targetPosition); if (object != nullptr && object->IsShrine()) { missile._mirange = j; } diff --git a/Source/msg.cpp b/Source/msg.cpp index 83cefb50e..53b9c3e4b 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -1222,7 +1222,7 @@ size_t OnObjectTileAction(const TCmd &cmd, Player &player, action_id action, boo { const auto &message = reinterpret_cast(cmd); const Point position { message.x, message.y }; - const Object *object = ObjectAtPosition(position); + const Object *object = FindObjectAtPosition(position); if (gbBufferMsgs != 1 && player.isOnActiveLevel() && object != nullptr) { if (pathToObject) @@ -1641,7 +1641,7 @@ size_t OnPlayerDamage(const TCmd *pCmd, Player &player) size_t OnOperateObject(const TCmd &pCmd, int pnum) { const auto &message = reinterpret_cast(pCmd); - Object *object = ObjectAtPosition({ message.x, message.y }); + Object *object = FindObjectAtPosition({ message.x, message.y }); if (gbBufferMsgs == 1) { SendPacket(pnum, &message, sizeof(message)); @@ -1658,7 +1658,7 @@ size_t OnOperateObject(const TCmd &pCmd, int pnum) size_t OnBreakObject(const TCmd &pCmd, int pnum) { const auto &message = reinterpret_cast(pCmd); - Object *breakable = ObjectAtPosition({ message.x, message.y }); + Object *breakable = FindObjectAtPosition({ message.x, message.y }); if (gbBufferMsgs == 1) { SendPacket(pnum, &message, sizeof(message)); diff --git a/Source/objects.cpp b/Source/objects.cpp index a556a5b9c..464d73f4f 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -569,7 +569,7 @@ void AddObjTraps() rndv = 25; for (int j = 0; j < MAXDUNY; j++) { for (int i = 0; i < MAXDUNX; i++) { - Object *triggerObject = ObjectAtPosition({ i, j }, false); + Object *triggerObject = FindObjectAtPosition({ i, j }, false); if (triggerObject == nullptr || GenerateRnd(100) >= rndv) continue; @@ -611,7 +611,7 @@ void AddChestTraps() { for (int j = 0; j < MAXDUNY; j++) { for (int i = 0; i < MAXDUNX; i++) { // NOLINT(modernize-loop-convert) - Object *chestObject = ObjectAtPosition({ i, j }, false); + Object *chestObject = FindObjectAtPosition({ i, j }, false); if (chestObject != nullptr && chestObject->IsUntrappedChest() && GenerateRnd(100) < 10) { switch (chestObject->_otype) { case OBJ_CHEST1: @@ -2192,7 +2192,7 @@ void OperateBook(Player &player, Object &book) if (doAddMissile) { questObject._oVar6 = 4; - ObjectAtPosition({ 35, 36 })->_oVar5++; + ObjectAtPosition({ 35, 36 })._oVar5++; AddMissile(player.position.tile, target, Direction::South, MIS_RNDTELEPORT, TARGET_BOTH, player.getId(), 0, 0); missileAdded = true; } @@ -3813,7 +3813,7 @@ void BreakBarrel(const Player &player, Object &barrel, bool forcebreak, bool sen PlayerMHit(dPlayer[xp][yp] - 1, nullptr, 0, 8, 16, MIS_FIREBOLT, false, 0, &unused); } // don't really need to exclude large objects as explosive barrels are single tile objects, but using considerLargeObjects == false as this matches the old logic. - Object *adjacentObject = ObjectAtPosition({ xp, yp }, false); + Object *adjacentObject = FindObjectAtPosition({ xp, yp }, false); if (adjacentObject != nullptr && adjacentObject->isExplosive() && !adjacentObject->IsBroken()) { BreakBarrel(player, *adjacentObject, true, sendmsg); } @@ -4001,7 +4001,7 @@ bool Object::IsDisabled() const return IsAnyOf(static_cast(_oVar1), shrine_type::ShrineFascinating, shrine_type::ShrineOrnate, shrine_type::ShrineSacred); } -Object *ObjectAtPosition(Point position, bool considerLargeObjects) +Object *FindObjectAtPosition(Point position, bool considerLargeObjects) { if (!InDungeonBounds(position)) { return nullptr; @@ -4019,21 +4019,21 @@ Object *ObjectAtPosition(Point position, bool considerLargeObjects) bool IsItemBlockingObjectAtPosition(Point position) { - Object *object = ObjectAtPosition(position); + Object *object = FindObjectAtPosition(position); if (object != nullptr && object->_oSolidFlag) { // solid object return true; } - object = ObjectAtPosition(position + Direction::South); + object = FindObjectAtPosition(position + Direction::South); if (object != nullptr && object->_oSelFlag != 0) { // An unopened container or breakable object exists which potentially overlaps this tile, the player might not be able to pick up an item dropped here. return true; } - object = ObjectAtPosition(position + Direction::SouthEast, false); + object = FindObjectAtPosition(position + Direction::SouthEast, false); if (object != nullptr) { - Object *otherDoor = ObjectAtPosition(position + Direction::SouthWest, false); + Object *otherDoor = FindObjectAtPosition(position + Direction::SouthWest, false); if (otherDoor != nullptr && object->_oSelFlag != 0 && otherDoor->_oSelFlag != 0) { // Two interactive objects potentially overlap both sides of this tile, as above the player might not be able to pick up an item which is dropped here. return true; @@ -4533,7 +4533,7 @@ void OperateTrap(Object &trap) if (trap._oVar4 != 0) return; - Object &trigger = *ObjectAtPosition({ trap._oVar1, trap._oVar2 }); + Object &trigger = ObjectAtPosition({ trap._oVar1, trap._oVar2 }); switch (trigger._otype) { case OBJ_L1LDOOR: case OBJ_L1RDOOR: @@ -4685,7 +4685,7 @@ void RedoPlayerVision() void MonstCheckDoors(const Monster &monster) { for (Direction dir : { Direction::NorthEast, Direction::SouthWest, Direction::North, Direction::East, Direction::South, Direction::West, Direction::NorthWest, Direction::SouthEast }) { - Object *object = ObjectAtPosition(monster.position.tile + dir); + Object *object = FindObjectAtPosition(monster.position.tile + dir); if (object == nullptr) continue; diff --git a/Source/objects.h b/Source/objects.h index c6f1445e6..b3ada6b73 100644 --- a/Source/objects.h +++ b/Source/objects.h @@ -265,7 +265,7 @@ extern bool LoadingMapObjects; * this param to false if you only want the object whose base position matches this tile * @return A pointer to the object or nullptr if no object exists at this location */ -Object *ObjectAtPosition(Point position, bool considerLargeObjects = true); +Object *FindObjectAtPosition(Point position, bool considerLargeObjects = true); /** * @brief Check whether an item occupies this tile position @@ -274,7 +274,19 @@ Object *ObjectAtPosition(Point position, bool considerLargeObjects = true); */ inline bool IsObjectAtPosition(Point position) { - return ObjectAtPosition(position) != nullptr; + return FindObjectAtPosition(position) != nullptr; +} + +/** + * @brief Get a reference to the object located at this tile + * + * This function is unchecked. Trying to access an invalid position will result in out of bounds memory access + * @param position The map coordinate of the object + * @return a reference to the object + */ +inline Object &ObjectAtPosition(Point position) +{ + return Objects[abs(dObject[position.x][position.y]) - 1]; } /** diff --git a/Source/player.cpp b/Source/player.cpp index 527d558f3..9d390c547 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -1057,7 +1057,7 @@ bool DoAttack(Player &player) } else if (PlayerAtPosition(position) != nullptr && !player.friendlyMode) { didhit = PlrHitPlr(player, *PlayerAtPosition(position)); } else { - Object *object = ObjectAtPosition(position, false); + Object *object = FindObjectAtPosition(position, false); if (object != nullptr) { didhit = PlrHitObj(player, *object); } @@ -1321,7 +1321,7 @@ bool IsPlayerAdjacentToObject(Player &player, Object &object) { int x = abs(player.position.tile.x - object.position.x); int y = abs(player.position.tile.y - object.position.y); - if (y > 1 && object.position.y >= 1 && ObjectAtPosition(object.position + Direction::NorthEast) == &object) { + if (y > 1 && object.position.y >= 1 && FindObjectAtPosition(object.position + Direction::NorthEast) == &object) { // special case for activating a large object from the north-east side y = abs(player.position.tile.y - object.position.y + 1); } @@ -1341,7 +1341,7 @@ void TryDisarm(const Player &player, Object &object) } for (int j = 0; j < ActiveObjectCount; j++) { Object &trap = Objects[ActiveObjects[j]]; - if (trap.IsTrap() && ObjectAtPosition({ trap._oVar1, trap._oVar2 }) == &object) { + if (trap.IsTrap() && FindObjectAtPosition({ trap._oVar1, trap._oVar2 }) == &object) { trap._oVar4 = 1; object._oTrapFlag = false; }