TotemBar v0.2.5
This commit is contained in:
+147
@@ -0,0 +1,147 @@
|
||||
-- TotemBar - core/assign.lua
|
||||
-- Assignment receiver seam: the contract + pure logic by which an external
|
||||
-- assigner (future "ShamiPower") hands TotemBar a proposed totem set.
|
||||
-- WoW-API-light so the logic below is offline-testable under real Lua 5.0.
|
||||
-- The pending-suggestion UI lives in ui.lua and is reached through the
|
||||
-- optional hook slots (ShowAssignPanel/HideAssignPanel/isTotemKnown/
|
||||
-- RefreshAll) that ui.lua fills in at load time.
|
||||
--
|
||||
-- An "assignment set" is a table keyed by element -> totem spell name:
|
||||
-- { Fire = "Searing Totem", Air = "Windfury Totem", ... }
|
||||
-- Any subset of elements; a missing element means "nothing for that slot".
|
||||
|
||||
TotemBar = TotemBar or {}
|
||||
|
||||
-- True if `key` is one of the four totem elements.
|
||||
function TotemBar.isElement(key)
|
||||
if not key then
|
||||
return false
|
||||
end
|
||||
local elements = TotemBar.TOTEM_ELEMENTS
|
||||
for i = 1, table.getn(elements) do
|
||||
if elements[i] == key then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Validates an assignment set. Returns true, or false plus a reason string.
|
||||
function TotemBar.validateAssignment(set)
|
||||
if type(set) ~= "table" then
|
||||
return false, "set must be a table"
|
||||
end
|
||||
local count = 0
|
||||
for k, v in pairs(set) do
|
||||
if not TotemBar.isElement(k) then
|
||||
return false, "unknown element key: " .. tostring(k)
|
||||
end
|
||||
if type(v) ~= "string" or v == "" then
|
||||
return false, "totem name for " .. tostring(k) .. " must be a non-empty string"
|
||||
end
|
||||
count = count + 1
|
||||
end
|
||||
if count == 0 then
|
||||
return false, "set is empty"
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Shallow copy of a set, keeping only valid element keys.
|
||||
function TotemBar.copySet(set)
|
||||
local out = {}
|
||||
if type(set) == "table" then
|
||||
for k, v in pairs(set) do
|
||||
if TotemBar.isElement(k) then
|
||||
out[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
-- Fresh copy (element -> name) of the currently chosen totems.
|
||||
function TotemBar.GetChosenSet()
|
||||
local out = {}
|
||||
local chosen = TotemBarDB and TotemBarDB.chosen
|
||||
if chosen then
|
||||
local elements = TotemBar.TOTEM_ELEMENTS
|
||||
for i = 1, table.getn(elements) do
|
||||
local e = elements[i]
|
||||
if chosen[e] then
|
||||
out[e] = chosen[e]
|
||||
end
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
-- Splits a set into applied (isKnown(name) true) and skipped (false).
|
||||
function TotemBar.filterKnown(set, isKnown)
|
||||
local applied, skipped = {}, {}
|
||||
for k, v in pairs(set) do
|
||||
if isKnown(v) then
|
||||
applied[k] = v
|
||||
else
|
||||
skipped[k] = v
|
||||
end
|
||||
end
|
||||
return applied, skipped
|
||||
end
|
||||
|
||||
-- Current pending assignment: { set = {element=name,...}, label = string } or nil.
|
||||
-- In-memory only (not a SavedVariable) - an assignment is ephemeral coordination.
|
||||
TotemBar.pending = nil
|
||||
|
||||
-- Optional hook, filled by an external assigner: called with the applied
|
||||
-- set table after the player accepts. Nil by default.
|
||||
TotemBar.onAssignmentApplied = nil
|
||||
|
||||
-- THE SEAM. An external assigner calls this to propose a set. Validates,
|
||||
-- stores it as the pending suggestion (replacing any prior), and asks the
|
||||
-- UI to show the panel. Does NOT apply. Returns true, or false + reason.
|
||||
function TotemBar.ReceiveAssignment(set, label)
|
||||
local ok, reason = TotemBar.validateAssignment(set)
|
||||
if not ok then
|
||||
return false, reason
|
||||
end
|
||||
TotemBar.pending = { set = TotemBar.copySet(set), label = label }
|
||||
if TotemBar.ShowAssignPanel then
|
||||
TotemBar.ShowAssignPanel()
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Drops any pending suggestion and hides the panel (decline / post-apply).
|
||||
function TotemBar.ClearAssignment()
|
||||
TotemBar.pending = nil
|
||||
if TotemBar.HideAssignPanel then
|
||||
TotemBar.HideAssignPanel()
|
||||
end
|
||||
end
|
||||
|
||||
-- Applies the pending suggestion: sets each KNOWN totem as the chosen
|
||||
-- default for its element (unknown totems are skipped), refreshes the bar,
|
||||
-- clears pending, hides the panel, and fires onAssignmentApplied. No cast.
|
||||
function TotemBar.ApplyPending()
|
||||
local p = TotemBar.pending
|
||||
if not p then
|
||||
return
|
||||
end
|
||||
local isKnown = TotemBar.isTotemKnown or function() return true end
|
||||
local applied = TotemBar.filterKnown(p.set, isKnown)
|
||||
TotemBarDB.chosen = TotemBarDB.chosen or {}
|
||||
for element, name in pairs(applied) do
|
||||
TotemBarDB.chosen[element] = name
|
||||
end
|
||||
if TotemBar.RefreshAll then
|
||||
TotemBar.RefreshAll()
|
||||
end
|
||||
TotemBar.pending = nil
|
||||
if TotemBar.HideAssignPanel then
|
||||
TotemBar.HideAssignPanel()
|
||||
end
|
||||
if TotemBar.onAssignmentApplied then
|
||||
TotemBar.onAssignmentApplied(applied)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user