From 9aa51bd99d07b4a9bb21480d7143efd3e2f70ec8 Mon Sep 17 00:00:00 2001 From: brightrim Date: Tue, 7 Jan 2025 11:35:18 +0100 Subject: [PATCH] Solved #428 by adding framework for illegal fields within the treasure map areas and a check for estate coordinates, with functionality that retroactively changes treasure maps coordinates upon lookat This functionality is one-time only and requires a variable "version" in the script to be changed to a higher number if estates or more illegal areas(inaccessible places for instance) are to be added to the relevant lists in order for the script to check maps that were already checked a second time --- item/base/treasure.lua | 131 ++++++++++++++++++++++++++++++++++++ item/id_505_treasuremap.lua | 2 + 2 files changed, 133 insertions(+) diff --git a/item/base/treasure.lua b/item/base/treasure.lua index bef13bbf14..0e93df5976 100644 --- a/item/base/treasure.lua +++ b/item/base/treasure.lua @@ -25,6 +25,7 @@ local money = require("base.money") local monsterHooks = require("monster.base.hooks") local scheduledFunction = require("scheduled.scheduledFunction") local safeZones = require("scheduled.safe_zones") +local propertyList = require("housing.propertyList") local M = {} @@ -87,6 +88,136 @@ local function findPosition() return nil end +--[[ + Some locations end up with treasures spawned in inaccessible areas, but have areas surrounding them in all + directions which makes it inconvenient to just shorten the treasure location above. + There are also a lot of existing maps players already obtained that lead to such locations. + As such the list below, along with the list of estate coordinates in housing, is added to a script that + checks the location when hovering over a treasure map for the first time and replaces it with new coordinates + if they are on an illegitimate tile, which means no more having to throw away bad treasure maps + (or having a GM fix it each time) and also future proofs it in regards to new housing estate locations we + might add on later. To avoid lag, a version number is added to the item data so it only checks the treasure maps + one time each time we change the list of locations. +]] + +local version = 1 --Update this to one number higher each time something is added to the list. + +local bannedLocations = { + {x = {from = 213, to = 300}, y = {from = 756, to = 830}, z = 0} --Mount letma, inaccessible +} + +function M.fetchPropertyName(user, pos) + + local direct + + if user then + direct = user:getFaceTo() + end + + local d = 1 + + local vX, vY + + if user then + vX, vY = common.GetDirectionVector(direct) + end + + local x + local y + local z + + if pos == nil then + x = user.pos.x + vX * d + y = user.pos.y + vY * d + z = user.pos.z + else + x = pos.x + y = pos.y + z = pos.z + end + for _, property in ipairs(propertyList.properties) do + if x >= property.lower.x + and x <= property.upper.x + and y >= property.lower.y + and y <= property.upper.y + and z >= property.lower.z + and z <= property.upper.z then + return property.name + end + end + return nil +end + +local function checkIfIllegalCoord(location) + + local propertyName = M.fetchPropertyName(nil, location) + + if propertyName then + return true + end + + for _, bannedLocation in pairs(bannedLocations) do + if location.x >= bannedLocation.x.from and location.x <= bannedLocation.x.to + and location.y >= bannedLocation.y.from and location.y <= bannedLocation.y.to + and location.z == bannedLocation.z then + return true + end + end +end + +local function mapLocation(map) + + local x = tonumber(map:getData("MapPosX")) + local y = tonumber(map:getData("MapPosY")) + local z = tonumber(map:getData("MapPosZ")) + + if common.IsNilOrEmpty(x) or common.IsNilOrEmpty(y) or common.IsNilOrEmpty(z) then + return false + end + + return position(x, y, z) + +end + +local function updateMapCoord(map) + + + local preventInfiniteLoop = 0 + + repeat + local newPos = findPosition() + if not newPos or checkIfIllegalCoord(newPos) then + preventInfiniteLoop = preventInfiniteLoop + 1 + else + map:setData("MapPosX", newPos.x) + map:setData("MapPosY", newPos.y) + map:setData("MapPosZ", newPos.z) + map:setData("checkedVersion", version) + world:changeItem(map) + break + end + until( preventInfiniteLoop > 10) + -- If it takes more than 10 attempts we break the loop to prevent the server crashing due to getting stuck in a loop + -- Realistically just one attempt should be plenty, but accounting for bad luck.. + +end + +function M.checkMap(map) + + if tonumber(map:getData("checkedVersion")) == version then + return + end + + local location = mapLocation(map) + + if checkIfIllegalCoord(location) then + updateMapCoord(map) + else + map:setData("checkedVersion", version) + world:changeItem(map) + end +end + local function getRandomMapLevel() return 10 - math.floor(math.sqrt(math.random(1, 99))) end diff --git a/item/id_505_treasuremap.lua b/item/id_505_treasuremap.lua index 21d99600d5..4b7bfb7462 100644 --- a/item/id_505_treasuremap.lua +++ b/item/id_505_treasuremap.lua @@ -68,6 +68,8 @@ end function M.LookAtItem(User, Item) + treasureBase.checkMap(Item) + local book = Item:getData("book") if book ~= "" then if book ~= nil then