From ea945b98f8bb4fe563412f3f7e95b2d0a3ffc698 Mon Sep 17 00:00:00 2001 From: Lacustat Date: Sun, 1 Nov 2026 14:40:16 +0100 Subject: [PATCH] 0.1.224: Wegzeiten des Plans auf grobem Raster (viel schneller), Ruckler beim Anmelden behoben Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_016onJCSHLwhs9udhC9ZLzk9 --- CodexPath.lua | 63 ++++++++++++++++++++++++++++++-------- Freewood-OctoWoW-Codex.toc | 2 +- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/CodexPath.lua b/CodexPath.lua index 429c5ae..7a6e6e5 100644 --- a/CodexPath.lua +++ b/CodexPath.lua @@ -758,6 +758,8 @@ end local NAV_COST = { [0] = 0, 1.0 / 1.4, 1.0, 1.4, 1.8, 2.2 } -- Kostenfaktor je Klasse (a gesperrt, b Strasse, c normal, d huegelig, e steil, f Wasser) local NAV_WALKED = 0.8 local NAV_MAX_EXPAND = 30000 +local NAV_PLAN_MAX = 8000 -- Luftlinie, bis zu der der Plan (Wegzeiten) auf dem Raster rechnet +local NAV_PLAN_EXPAND = 1500 -- Suchschritte je Wegzeit-Berechnung (mehr gibt es nur fuer die Anzeige des Wegs) local NAV_SNAP = 6 -- Zellen, so weit darf ein Ort von begehbarem Gelaende entfernt sein local navs = {} -- [welt] = { w, h, cell, left, top, cls = { [idx] = klasse }, walked = { [idx] = true }, rev, built, cache = {} } @@ -777,11 +779,38 @@ local function NavLoad(world) end end end - n = { w = src.w, h = src.h, cell = src.cell, left = src.left, top = src.top, cls = cls, walked = {}, rev = -1, built = 0, cache = {} } + n = { w = src.w, h = src.h, cell = src.cell, left = src.left, top = src.top, cls = cls, walked = {}, rev = -1, built = 0, cache = {}, fail = {}, costs = NAV_COST } navs[world] = n return n end +-- grobes Raster (4 x 4 Zellen = 167 Yards) fuer die Wegzeiten des Plans: viel schneller zu durchsuchen +local COARSE = 4 +local function NavCoarse(n) + if n.coarse then return n.coarse end + local w, h, cls = n.w, n.h, n.cls + local cw, ch = math.ceil(w / COARSE), math.ceil(h / COARSE) + local c = {} + for cr = 0, ch - 1 do + for cc = 0, cw - 1 do + local sum, open, tot = 0, 0, 0 + for r = cr * COARSE, math.min(h, cr * COARSE + COARSE) - 1 do + local base = r * w + 1 + for k = cc * COARSE, math.min(w, cc * COARSE + COARSE) - 1 do + tot = tot + 1 + local cl = cls[base + k] + if cl ~= 0 then open = open + 1 sum = sum + NAV_COST[cl] end + end + end + local v = 0 + if open > 0 then v = (sum / open) * (1 + 0.5 * (1 - open / tot)) end + c[cr * cw + cc + 1] = v + end + end + n.coarse = { w = cw, h = ch, cell = n.cell * COARSE, left = n.left, top = n.top, cls = c, walked = {}, cache = {}, fail = {} } + return n.coarse +end + -- gelaufene Zellen auf das Raster legen (hoechstens alle GRAPH_STALE Sekunden neu, wenn es neue Daten gibt) local function NavWalked(n, world) local rev = Path.rev or 0 @@ -797,7 +826,7 @@ local function NavWalked(n, world) if row >= 0 and row < n.h and col >= 0 and col < n.w then walked[row * n.w + col + 1] = true end end end - n.walked, n.rev, n.built, n.cache = walked, rev, now, {} + n.walked, n.rev, n.built, n.cache, n.fail = walked, rev, now, {}, {} end local function NavCell(n, x, y) @@ -833,8 +862,8 @@ end local NAV_DIRS = { { 1, 0, 1 }, { -1, 0, 1 }, { 0, 1, 1 }, { 0, -1, 1 }, { 1, 1, 1.4142 }, { 1, -1, 1.4142 }, { -1, 1, 1.4142 }, { -1, -1, 1.4142 } } -- A* von Zelle a nach Zelle b. Rueckgabe: Liste von Zellindizes (a ... b) oder nil -local function NavSearch(n, a, b) - local w, h, cls, walked = n.w, n.h, n.cls, n.walked +local function NavSearch(n, a, b, maxExp) + local w, h, cls, walked, costs = n.w, n.h, n.cls, n.walked, n.costs local bi = b - 1 local br, bc = math.floor(bi / w), bi % w local g, prev, closed = { [a] = 0 }, {}, {} @@ -869,7 +898,7 @@ local function NavSearch(n, a, b) end return top end - local function H(r, c) return 0.7 * math.sqrt((r - br) ^ 2 + (c - bc) ^ 2) * 1.15 end + local function H(r, c) return math.sqrt((r - br) ^ 2 + (c - bc) ^ 2) end local ai = a - 1 Push(a, H(math.floor(ai / w), ai % w)) local expanded = 0 @@ -884,7 +913,7 @@ local function NavSearch(n, a, b) if not closed[k] then closed[k] = true expanded = expanded + 1 - if expanded > NAV_MAX_EXPAND then return nil end + if expanded > (maxExp or NAV_MAX_EXPAND) then return nil end local ki = k - 1 local r, c = math.floor(ki / w), ki % w local gk = g[k] @@ -895,8 +924,13 @@ local function NavSearch(n, a, b) local nk = rr * w + cc + 1 local cl = cls[nk] if cl and cl ~= 0 and not closed[nk] then - local f = walked[nk] and NAV_WALKED or NAV_COST[cl] - if walked[nk] and cl == 5 then f = NAV_COST[5] end + local f + if costs then + f = costs[cl] + if walked[nk] and cl ~= 5 then f = NAV_WALKED end + else + f = cl + end local ng = gk + d[3] * f if not g[nk] or ng < g[nk] then g[nk] = ng @@ -912,10 +946,11 @@ local function NavSearch(n, a, b) end -- Weg zwischen zwei Orten (Yards im Zellraum): Zellmitten als { x, y }, Laenge in Yards (ohne Anschluss an die Enden), Entfernung der Enden zum Netz -local function NavPath(world, ax, ay, bx, by) +local function NavPath(world, ax, ay, bx, by, maxExp, coarse) local n = NavLoad(world) if not n then return nil end NavWalked(n, world) + if coarse then n = NavCoarse(n) end local ar, ac = NavCell(n, ax, ay) local br, bc = NavCell(n, bx, by) local a, ar2, ac2 = NavSnap(n, ar, ac) @@ -924,11 +959,12 @@ local function NavPath(world, ax, ay, bx, by) local ck = a .. ":" .. b local hit = n.cache[ck] local chain - if hit ~= nil then + if hit ~= nil and (hit or (n.fail[ck] or 0) >= (maxExp or NAV_MAX_EXPAND)) then chain = hit or nil else - chain = a == b and { a } or NavSearch(n, a, b) + chain = a == b and { a } or NavSearch(n, a, b, maxExp) n.cache[ck] = chain or false + n.fail[ck] = (not chain) and (maxExp or NAV_MAX_EXPAND) or nil end if not chain then return nil end local pts = {} @@ -1072,8 +1108,9 @@ function Path.Distance(world, ax, ay, bx, by) if type(world) ~= "number" then return nil end local straight = math.sqrt((ax - bx) ^ 2 + (ay - by) ^ 2) if straight < 2 * BLOCK * CELL then return nil end - local pts, len, na, nb = NavPath(world, ax, ay, bx, by) - if pts then return na + len + nb end + if straight > NAV_PLAN_MAX then return nil end + local pts, len, na, nb = NavPath(world, ax, ay, bx, by, NAV_PLAN_EXPAND, true) + if pts then return na + len * 0.93 + nb end local g = Graph(world) if not g then return nil end local sa, da = Snap(g, ax, ay) diff --git a/Freewood-OctoWoW-Codex.toc b/Freewood-OctoWoW-Codex.toc index 26fadec..26fc7c5 100644 --- a/Freewood-OctoWoW-Codex.toc +++ b/Freewood-OctoWoW-Codex.toc @@ -3,7 +3,7 @@ ## Notes: Learns quests, creatures and drops while you play: who gives and takes a quest, rewards, objectives, drop chances. ## Notes-deDE: Lernt beim Spielen Quests, Kreaturen und Beute: wer eine Quest vergibt und annimmt, Belohnungen, Ziele, Drop-Chancen. ## Author: Lacustat -## Version: 0.1.223 +## Version: 0.1.224 ## Dependencies: Freewood-OctoWoW-Core ## SavedVariablesPerCharacter: FreewoodSnapshot ## OptionalDeps: Freewood-OctoWoW-CodexData, Freewood-OctoWoW-ForeverData