-- Questie-Octo item-start geographic aggregation. -- -- Item-start quests are presented as one marker per meaningful hunting area, -- even when several different creature IDs can drop the same starter item. -- Active quest objectives are NOT affected by this layer. QuestieOcto.ItemStartAreas = QuestieOcto.ItemStartAreas or {} local A = QuestieOcto.ItemStartAreas A.radius=14.0 A.zoneWideRareThreshold=0.1 function A:IsZoneWideRareChance(chance) chance=tonumber(chance) or 0 return chance>0 and chanceb.count end) return result end function A:BuildForMap(nodes,mapID,includeNode) local groups={} -- Group by quest + starter item first. Different starter quests never merge. for _,node in pairs(nodes or {}) do if node.role=="itemStart" and tonumber(node.itemID) and node.coords and (not includeNode or includeNode(node)) then local groupKey=tostring(node.questID)..":"..tostring(node.itemID) local group=groups[groupKey] if not group then group={ questID=node.questID, itemID=node.itemID, itemName=node.itemName, points={} } groups[groupKey]=group end for _,coord in pairs(node.coords) do if type(coord)=="table" and tonumber(coord[3])==tonumber(mapID) then local x=tonumber(coord[1]) local y=tonumber(coord[2]) if x and y then table.insert(group.points,{ x=x, y=y, sourceID=node.sourceID, sourceName=node.sourceName, sourceRank=node.sourceRank, respawnSeconds=node.respawnSeconds, chance=node.chance }) end end end end end local result={} for _,group in pairs(groups) do SortPoints(group.points) local areas={} -- Greedy geographic clustering around the evolving area centroid. -- This intentionally merges different mob types only when they truly share -- a hunting area. A mob population on the other side of the zone remains -- a separate marker. for _,point in pairs(group.points) do local best=nil local bestDistance=nil for _,area in pairs(areas) do local cx=area.sx/area.n local cy=area.sy/area.n local d=Distance(point.x,point.y,cx,cy) if d<=A.radius and (not bestDistance or d0 then SortPoints(group.points) local area=NewArea(group.points[1]) local i for i=2,table.getn(group.points) do AddPointToArea(area,group.points[i]) end local cx=area.sx/area.n local cy=area.sy/area.n local best=group.points[1] local bestDistance=Distance(best.x,best.y,cx,cy) for _,point in pairs(group.points) do local d=Distance(point.x,point.y,cx,cy) if d