Mercurial > wow > breuesk
view State.lua @ 102:21567b74fcc7
Notes and corrections
author | John@Doomsday |
---|---|
date | Thu, 03 May 2012 09:05:24 -0400 |
parents | b89558d3e833 |
children |
line wrap: on
line source
local bsk=bsk local _G=_G local table=table local pairs=pairs local setmetatable=setmetatable local ipairs=ipairs local string=string local sformat=string.format local tostring=tostring local type=type local unpack=unpack local getn=getn setfenv(1,bsk) -- simple state machine --Begin loot --Activate list ... only during looting? --open bidding/rolling --bid/roll occurred --remove bid/roll --close bidding --remove item -- we'll track state, but that may or may not result in a GUI change until down -- the road -- todo: transmit this all to only the raid, not the guild? -- sample procedure -- person B opens GUI. -- person A begins looting, sets a list -- person A begins bidding, transmists the state -- person B goes into bidding state, their button activates -- person B clicks the button. button changes state. -- person B broadcasts their bid. if a bid, everyone just accepts it. -- - if a roll, then the master does the roll and rebroadcasts state = "neutral" -- states that are possible: neutral, looting, bidding local looting = false stateactive = nil stateitem = nil stateitemlist = {} statebids = {} staterolls = {} staterollvalues = {} stateactivelist = nil -- todo: protect initiators to admin only local rollListeners = {} function RegisterListenerRolls(listener) table.insert(rollListeners,listener) end function AlertRollListeners() for i,v in pairs(rollListeners) do print("roll out") v["RollEvent"](v) end end local listChangeListeners = {} function RegisterListenerActiveListChanged(listener) table.insert(listChangeListeners,listener) end function AlertActiveListChangedListeners() for i,v in pairs(listChangeListeners) do print("list out") v["ActiveListEvent"](v) end end local stateChangeListeners = {} function RegisterListenerStateChange(listener) table.insert(stateChangeListeners,listener) end function AlertStateChangeListeners() for i,v in pairs(stateChangeListeners) do print("state out") v["StateEvent"](v) end end local itemListListeners = {} function RegisterItemListListener(listener) table.insert(itemListListeners,listener) end function AlertItemListListeners() for i,v in pairs(itemListListeners) do print("item change") v["ItemListEvent"](v) end end function BeginLoot(packet) local items, listValue = unpack(packet) if state == "neutral" then state = "looting" stateactivelist = listValue stateitemlist = items AlertItemListListeners() CreateGUI() -- todo: bad spot, but that's ok for now else _G.error("Bad state transition", state, "looting") end end function InitiateBeginLoot(items,listValue) if state == "neutral" then Comm:SendStateChange("BL",items,listValue) end end -- Activate List {{{ function ActivateList(packet) -- doesn't cause a transition, but we only enforce a list selection during certain times local list = unpack(packet) if state == "looting" then stateactivelist = list AlertActiveListChangedListeners() end end function InitiateActivateList(list) if state == "looting" then Comm:SendStateChange("AL",list) end end --}}} -- Open Bidding {{{ function OpenBid(packet) local item = unpack(packet) if state == "looting" then state = "bidding" stateitem = item AlertStateChangeListeners() if admin and masterLooterIsMe then local chan if _G.GetNumRaidMembers() > 0 then chan = "RAID" else chan = "PARTY" end _G.SendChatMessage("Bidding is now open for "..item.link.."!",chan) _G.SendChatMessage("Whisper me \"bid\" to bid or \"roll\" to offset roll; \"retract\" will remove your bid",chan) end end end function InitiateOpenBid(item) if state == "looting" then Comm:SendStateChange("OB",item) end end --}}} -- Bid {{{ local function SortByList(lref,unordered) local t = {} for le in lref:OrderedListEntryIter() do local lid = le:GetId() for i,v in pairs(unordered) do if v.value == lid then print("Sort time: insert", lid) table.insert(t,v) table.remove(unordered,i) break -- done with this inner iteration end end end if getn(t) > 0 then for i,v in pairs(unordered) do printf("Disregarding bid/roll from %s because they are not on the list", v.textPlain) end end return t end local function SortByRoll(values,unordered) local t = {} for r = 100,1,-1 do -- 100:1 if values[r] then for i,v in pairs(unordered) do if v.value == values[r].value then print("Sort time: insert", v.value, r) table.insert(t,v) table.remove(unordered,i) break end end end end if getn(t) > 0 then for i,v in pairs(unordered) do printf("Disregarding bid/roll from %s because they are not on the list", v.textPlain) end end return t end function ReceivedBid(packet) -- no state transition, but only matters during one state local person, roll = unpack(packet) if state == "bidding" then if roll then table.insert(staterolls,person) staterollvalues[roll] = person staterolls = SortByRoll(staterollvalues,staterolls) else local lref = LootLists:Select(stateactivelist) table.insert(statebids,person) statebids = SortByList(lref,statebids) end AlertRollListeners() if admin and masterLooterIsMe then local leader if getn(statebids) > 0 then leader = statebids[1].textPlain elseif getn(staterolls) > 0 then leader = staterolls[1].textPlain end local chan -- todo: this idiom is wearing on me already if _G.GetNumRaidMembers() > 0 then chan = "RAID" else chan = "PARTY" end if roll then _G.SendChatMessage(sformat("Received roll of %d from %s; current leader is %s", roll, person.textPlain, leader),chan) else _G.SendChatMessage(sformat("Received bid from %s; current leader is %s", person.textPlain, leader),chan) -- todo: tell what spot they're bidding from end end end -- else ignore ... end function InitiateBid(person,roll) if state == "bidding" then if not person then print("You cannot bid becuase you are not on the list") return end for i,v in pairs(statebids) do if person and person.value == v.value then print(person.value .. " is already on the list") return -- no double adds please end end for i,v in pairs(staterolls) do if person and person.value == v.value then print(person.value .. " is already on the list") return -- no double adds please end end Comm:SendStateChange("RB",person,roll) end end --}}} -- Retration {{{ function ReceivedRetraction(packet) local person = unpack(packet) if state == "bidding" then for i,v in pairs(statebids) do if v.value == person.value then table.remove(statebids,i) AlertRollListeners() return end end for i,v in pairs(staterolls) do if v.value == person.value then table.remove(staterolls,i) AlertRollListeners() return end end end end function InitiateRetract(person) if state == "bidding" then Comm:SendStateChange("RR",person) end end --}}} -- Close Bidding {{{ function CloseBidding(packet) local awardedTo = unpack(packet) -- todo: unused if state == "bidding" then state = "looting" stateitem = nil statebids = {} staterolls = {} staterollvalues = {} AlertStateChangeListeners() AlertItemListListeners() -- todo: record history if admin then local chan -- todo: this idiom is wearing on me already if _G.GetNumRaidMembers() > 0 then chan = "RAID" else chan = "PARTY" end _G.SendChatMessage("Bidding is closed",chan) end end end function InitiateCloseBidding(awardedTo) if state == "bidding" then Comm:SendStateChange("CB",awardedTo) end end --}}} -- Close Looting {{{ function CloseLooting(packet) state = "neutral" stateactive = nil stateitem = nil stateitemlist = {} statebids = {} staterolls = {} staterollvalues = {} AlertStateChangeListeners() AlertItemListListeners() end function InitiateCloseLooting() Comm:SendStateChange("CL") end --}}} function RollRequest(packet) local person = unpack(packet) if state == "bidding" and admin and masterLooterIsMe then local roll for i,v in pairs(staterollvalues) do if v and v.value == person.value then roll = i break end end if not roll then -- roll isn't on cache repeat -- random until you find a good value roll = _G.random(100) until staterollvalues[roll] == nil print("rolling! ", roll) staterollvalues[roll] = person end InitiateBid(person,roll) end end function InitiateRollRequest(person) if state == "bidding" then if not person then print("You cannot bid becuase you are not on the list") return end for i,v in pairs(staterolls) do if person and person.value == v.value then print(person.value .. " is already on the list") return -- no double adds please end end for i,v in pairs(statebids) do if person and person.value == v.value then print(person.value .. " is already on the list") return -- no double adds please end end Comm:SendStateChange("IR",person,roll) end end local function LootSlotCleared(packet) local index = unpack(packet) if state == "looting" or state == "bidding" then for i,v in pairs(stateitemlist) do if v.mlid == index then v.disabled = true print("DISABLING") AlertItemListListeners() return end end end end function InitiateLSClear(index) if state == "looting" or state == "bidding" then Comm:SendStateChange("SC",index) end end function DispatchState(packet) local state = table.remove(packet,1) print("Dispatching", state) if state == "RB" then ReceivedBid(packet) elseif state == "BL" then BeginLoot(packet) elseif state == "RR" then ReceivedRetraction(packet) elseif state == "OB" then OpenBid(packet) elseif state == "CB" then CloseBidding(packet) elseif state == "CL" then CloseLooting(packet) elseif state == "AL" then ActivateList(packet) elseif state == "IR" then RollRequest(packet) elseif state == "SC" then LootSlotCleared(packet) else _G.error("Cannot dispatch message of type:",state) end end function InitializeState() -- basically, find a value for stateactivelist. it really doesn't matter -- which one, but I decided on trying to choose one that has entries on it -- so the whole thing isn't all empty. stateactivelist being anything -- besides a valid ID could trigger errors local ltemp = 0 local lids = LootLists:GetAllIds() for _,v in pairs(lids) do local l = LootLists:Select(v) if l:GetLength() > 0 then if ltemp == 0 then ltemp = l:GetId() end end end stateactivelist = ltemp end