From 61c1fc08abb9e9fbfecf6bcfb464a09a8214e1a1 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Sat, 14 Dec 2024 01:53:28 -0300 Subject: [PATCH 1/3] fix: infinite loop in Zone:randomPosition when no valid tile exist (#3178) This commit fixes an infinite loop issue in the `Zone:randomPosition` function. When no valid positions (walkable tiles) exist in the zone, the function would previously enter an infinite loop. The updated logic now filters all positions upfront to identify walkable tiles, and if none are found, the function returns `nil` with appropriate logging. This change ensures better error handling and prevents server freezes due to infinite loops. --- data/libs/systems/zones.lua | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/data/libs/systems/zones.lua b/data/libs/systems/zones.lua index 698a464fe87..a232a071f41 100644 --- a/data/libs/systems/zones.lua +++ b/data/libs/systems/zones.lua @@ -15,12 +15,24 @@ function Zone:randomPosition() logger.error("Zone:randomPosition() - Zone {} has no positions", self:getName()) return nil end - local destination = positions[math.random(1, #positions)] - local tile = destination:getTile() - while not tile or not tile:isWalkable(false, false, false, false, true) do - destination = positions[math.random(1, #positions)] - tile = destination:getTile() + + local validPositions = {} + for _, position in ipairs(positions) do + local tile = position:getTile() + if tile and tile:isWalkable(false, false, false, false, true) then + table.insert(validPositions, position) + else + logger.debug("Zone:randomPosition() - Position {} is invalid (Tile: {}, Walkable: {})", position, tile or "nil", tile and tile:isWalkable(false, false, false, false, true) or "false") + end end + + if #validPositions == 0 then + logger.error("Zone:randomPosition() - No valid positions in Zone {}", self:getName()) + return nil + end + + local destination = validPositions[math.random(1, #validPositions)] + logger.debug("Zone:randomPosition() - Selected valid position: {}", destination) return destination end From 03f1d1435e5460fd8ef3f277d5fe7bff91d7099c Mon Sep 17 00:00:00 2001 From: Felipe Pessoa Date: Sat, 14 Dec 2024 03:57:27 -0300 Subject: [PATCH 2/3] fix: position after try to cross bridge (#3175) The problem was that the ladder action was executed first, followed immediately by the teleportTo action, causing the Player to move above the ladder with the possibility of crossing the bridge. --- .../scripts/movements/rookgaard/rook_village.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-otservbr-global/scripts/movements/rookgaard/rook_village.lua b/data-otservbr-global/scripts/movements/rookgaard/rook_village.lua index 3b22a4c2394..b8e9b95f3bd 100644 --- a/data-otservbr-global/scripts/movements/rookgaard/rook_village.lua +++ b/data-otservbr-global/scripts/movements/rookgaard/rook_village.lua @@ -6,7 +6,7 @@ function rookVillage.onStepIn(creature, item, position, fromPosition) return true end - player:teleportTo(Position(player:getPosition().x, player:getPosition().y - 1, player:getPosition().z)) + player:teleportTo(Position(player:getPosition().x, player:getPosition().y - 3, player:getPosition().z + 1)) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You don't have any business there anymore.") return true From 05ff8be4219afb7a411e3418055c502184e50e29 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Sat, 14 Dec 2024 05:31:41 -0300 Subject: [PATCH 3/3] enhance: Monster::getDanceStep code duplication (#2997) Refactored the `getDanceStep` function to avoid code duplication by introducing a helper function `tryAddDirection`. This change improves code readability and maintainability by reducing repetitive logic. --- src/creatures/monsters/monster.cpp | 57 ++++++++---------------------- 1 file changed, 14 insertions(+), 43 deletions(-) diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp index d30c2a33471..690ebd10b39 100644 --- a/src/creatures/monsters/monster.cpp +++ b/src/creatures/monsters/monster.cpp @@ -1581,73 +1581,44 @@ bool Monster::getDanceStep(const Position &creaturePos, Direction &moveDirection uint32_t centerToDist = std::max(distance_x, distance_y); // monsters not at targetDistance shouldn't dancestep - if (centerToDist < (uint32_t)targetDistance) { + if (centerToDist < static_cast(targetDistance)) { return false; } std::vector dirList; - if (!keepDistance || offset_y >= 0) { - uint32_t tmpDist = std::max(distance_x, std::abs((creaturePos.getY() - 1) - centerPos.getY())); - if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_NORTH)) { + auto tryAddDirection = [&](Direction direction, int_fast32_t newX, int_fast32_t newY) { + uint32_t tmpDist = std::max(std::abs(newX - centerPos.getX()), std::abs(newY - centerPos.getY())); + if (tmpDist == centerToDist && canWalkTo(creaturePos, direction)) { bool result = true; if (keepAttack) { - result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x, creaturePos.y - 1, creaturePos.z), attackedCreature)); + result = (!canDoAttackNow || canUseAttack(Position(newX, newY, creaturePos.z), attackedCreature)); } if (result) { - dirList.push_back(DIRECTION_NORTH); + dirList.emplace_back(direction); } } + }; + + if (!keepDistance || offset_y >= 0) { + tryAddDirection(DIRECTION_NORTH, creaturePos.getX(), creaturePos.getY() - 1); } if (!keepDistance || offset_y <= 0) { - uint32_t tmpDist = std::max(distance_x, std::abs((creaturePos.getY() + 1) - centerPos.getY())); - if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_SOUTH)) { - bool result = true; - - if (keepAttack) { - result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x, creaturePos.y + 1, creaturePos.z), attackedCreature)); - } - - if (result) { - dirList.push_back(DIRECTION_SOUTH); - } - } + tryAddDirection(DIRECTION_SOUTH, creaturePos.getX(), creaturePos.getY() + 1); } if (!keepDistance || offset_x <= 0) { - uint32_t tmpDist = std::max(std::abs((creaturePos.getX() + 1) - centerPos.getX()), distance_y); - if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_EAST)) { - bool result = true; - - if (keepAttack) { - result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x + 1, creaturePos.y, creaturePos.z), attackedCreature)); - } - - if (result) { - dirList.push_back(DIRECTION_EAST); - } - } + tryAddDirection(DIRECTION_EAST, creaturePos.getX() + 1, creaturePos.getY()); } if (!keepDistance || offset_x >= 0) { - uint32_t tmpDist = std::max(std::abs((creaturePos.getX() - 1) - centerPos.getX()), distance_y); - if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_WEST)) { - bool result = true; - - if (keepAttack) { - result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x - 1, creaturePos.y, creaturePos.z), attackedCreature)); - } - - if (result) { - dirList.push_back(DIRECTION_WEST); - } - } + tryAddDirection(DIRECTION_WEST, creaturePos.getX() - 1, creaturePos.getY()); } if (!dirList.empty()) { - std::shuffle(dirList.begin(), dirList.end(), getRandomGenerator()); + std::ranges::shuffle(dirList, getRandomGenerator()); moveDirection = dirList[uniform_random(0, dirList.size() - 1)]; return true; }