Draw quest objective areas on the world map instead of pins - #1
Conversation
Replaces the per-spawn dots for quest objectives on the world map with numbered areas, in the style of the retail quest POI blobs: - Objective coordinates of each quest on the current map are grouped by single-linkage clustering (8 map-% threshold), so a quest whose targets live in two separate places gets two areas. - Each cluster is drawn as its padded convex hull, filled as a triangle fan with Texture:SetVertexOffset, one uniform translucent colour for all quests. Areas are children of the map canvas so they zoom with it. - A badge at the cluster centroid shows the quest's position in the quest log (main.lua now records meta.ordinal). Hovering an area or badge shows the quest title and its objective lines; clicking the badge opens the quest in the quest log via QuestLog_SetSelection. - Areas rebuild, debounced, whenever the node tables or the map change; rebuilds while the map is closed are deferred to the next OnShow. - New WorldMap setting "worldmap_quest_area" (default on) switches between areas and the previous dots. The minimap is unchanged. Geometry (clustering, monotone-chain hull with octagon padding, centroid) lives in map-area-geometry.lua and is covered by tests/geometry_test.lua, runnable with lua5.1 or via tests/run_lupa.py when only Python is around. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Each quest's areas use one of eight palette colours keyed by its quest log position, so overlapping areas of different quests stay apart. - Hulls get a thin outline in the quest colour so both boundaries remain visible where areas overlap. - Hovering an area or its badge lights up every area of that quest, turns the badge gold with a dark number and adds a glow, so it is clear which quest a click would open. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Areas whose hulls overlap (separating-axis test, new MT.AreaPolygonsOverlap) are merged into one area with one badge per quest, so areas never overlap. Badges that would land on the same spot are pushed apart; the merged area takes the colour of its lowest quest. - Hovering an area lights all its badges and lists every quest in the tooltip; hovering a badge lights that badge and every area holding its quest, and lists that quest only. - The tooltip is anchored next to the cursor for areas and badges alike and follows the cursor while hovering, like the retail quest blobs. - Fan apex is the hull's vertex mean, which is inside any convex polygon. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Two follow-ups after the first in-game look, both on
The "overlapping areas simply stack" line in the description is therefore superseded: they merge instead. |
Badges (one per quest cluster, position in the quest log) are always visible and pushed apart when they would stack. A quest's shapes appear only while its badge is hovered, with the tooltip beside the cursor, so areas of different quests never compete and the map stays fully interactive (the shapes take no mouse input). Within a cluster there is now one shape per mob or object type, so a quest shows where each of its targets actually lives instead of one hull spanning all of them. Area merging is no longer needed; MT.AreaPolygonsOverlap and its tests are removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Third pivot, after another in-game round: the merged areas hid where each quest's targets actually are, so |
Shapes are shown all the time again. Hovering a badge brings that quest's shapes to full strength and in front while the other quests' shapes dim, so overlapping areas resolve on hover instead of being hidden until then. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Splitting a cluster by mob/object type stacked a dozen shapes for quests whose item drops from many NPC types (Ghoulish Effigy). Back to a single hull per cluster; a quest still gets separate shapes only when its targets are in separate places. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The title uses the quest log's difficulty colour for the quest level (GetQuestDifficultyColor) and shows the level in front, so hovering a badge tells at a glance how dangerous the quest is. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The world map's quest clusters are converted to world yards and drawn around the player on the minimap, clipped to the minimap shape with a mask texture. Shapes are laid out once per zoom level and only shifted while walking (a rotating minimap re-lays them out in place); shapes beyond twice the visible radius are hidden. Hovering a shape focuses its quest and shows the same tooltip beside the cursor; clicks and the wheel fall through to the minimap. No badges on the minimap. Shared pieces (quest colours, tooltip, vertex-offset shape drawing, cluster collection) move behind MT.MapArea* so both maps draw the same. Minimap objective pins are skipped while the new "minimap_quest_area" setting (default on) is enabled. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Minimap now gets the areas too ( Things to watch in-game: |
The button only lifted CodexLite's temporary hide filter, which does nothing unless the quest was hidden first. It now also opens the world map on the map holding most of the quest's objective spots (its start or turn-in spot when there are none) and puts the quest in focus there. Focus is kept across rebuilds until the next badge hover ends. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Counting spots per map picked adjoining zones and continents, because CodexLite copies every spot into those maps. Only an entity's home spots count now (the first coord sharing each world-coord table), the player's current zone wins when the quest has spots there, and a finished quest falls back to the zone of its turn-in or start NPC. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
What & why
CodexLite marks every objective spawn on the world map with a dot, which for a quest with dozens of spawns turns into a cloud of dots that says little about where to go. This PR draws each quest's objectives as translucent areas with a numbered badge, the way the retail quest map does: hovering shows the quest and its objective progress, clicking the badge opens the quest in the log. A quest whose targets sit in two separate places (the Duskwood example) gets two areas.
Main changes
map-area-geometry.lua(new, pure Lua): single-linkage clustering of objective coordinates, padded convex hull (monotone chain over octagons around the hull vertices, so even a single spawn yields a proper blob), centroid. Covered bytests/geometry_test.lua.map-area.lua(new): pooled area frames as children of the map canvas so they zoom with it. Each hull is filled as a triangle fan of 1×1 textures deformed withTexture:SetVertexOffset— one uniform fill, no darker overlaps inside an area. Badge = ala'sCircletexture + quest-log position. Rebuilds are debounced through the existingMT._TimerStart, and a rebuild while the map is closed is deferred to the nextOnShow.map.lua: skips the common/large pins on the world map while area mode is on, marks the area layer dirty wherever node tables or the map change, exportswm_wrap, forwards canvas scale changes so badges keep a readable size.main.lua: recordsmeta.ordinal(position among quests in the log) and redraws when it changes.setting.lua+ locales:worldmap_quest_areatoggle (default on) under WorldMap; off restores the previous dots.Trade-offs: the hover hit-area is the polygon's bounding box, not the polygon (simpler, and it never mattered for the retail blobs either). All quests share one fill colour, as requested; overlapping areas of different quests simply stack. The minimap is untouched. Cluster distance (8 map-%) and padding (1.5 map-%) are constants at the top of
map-area.lua, tuned by eye and worth revisiting in-game.What deserves attention
Texture:SetVertexOffset,Frame:SetPropagateMouseClicks(guarded, so the map still drags through an area), andWorldMapFrame.ScrollContainer:OnMouseWheel(so zooming over an area keeps working).!/?icons stay above them; badges sit 12 above. If an icon ever renders under a fill, that offset is the knob.QuestLog_SetSelection(index)is what Classic Era's own quest log uses; it expands a collapsed header itself.How to test manually
/console scriptErrors 1,/reload, open the map in a zone with active quests: objective dots are gone, each quest shows one or more areas with a numbered badge; the number matches the quest's position in the quest log.- objective: n/mlines, finished ones green; the area brightens.PYTHONPATH=<dir with lupa> python3 tests/run_lupa.py(orlua5.1 tests/geometry_test.lua) →18 passed, 0 failed.🤖 Generated with Claude Code