John@71: local bsk=bsk John@71: local _G=_G John@71: local table=table John@71: local pairs=pairs John@71: local setmetatable=setmetatable John@71: local ipairs=ipairs John@71: local string=string John@71: local sformat=string.format John@71: local tostring=tostring John@71: local type=type John@71: local unpack=unpack John@71: local getn=getn John@71: setfenv(1,bsk) John@71: John@71: -- simple state machine John@71: John@71: --Begin loot John@71: --Activate list ... only during looting? John@71: --open bidding/rolling John@71: --bid/roll occurred John@71: --remove bid/roll John@71: --close bidding John@71: --remove item John@71: John@71: John@71: -- we'll track state, but that may or may not result in a GUI change until down John@71: -- the road John@71: John@71: -- todo: transmit this all to only the raid, not the guild? John@71: John@71: -- sample procedure John@71: -- person B opens GUI. John@71: -- person A begins looting, sets a list John@71: -- person A begins bidding, transmists the state John@71: -- person B goes into bidding state, their button activates John@71: -- person B clicks the button. button changes state. John@71: -- person B broadcasts their bid. if a bid, everyone just accepts it. John@71: -- - if a roll, then the master does the roll and rebroadcasts John@71: John@72: state = "neutral" -- states that are possible: neutral, looting, bidding John@71: local looting = false John@71: stateactive = nil John@71: stateitem = nil John@73: stateitemlist = {} John@71: statebids = {} John@71: staterolls = {} John@78: staterollvalues = {} John@73: stateactivelist = nil John@71: John@76: -- todo: protect initiators to admin only John@76: John@71: local rollListeners = {} John@71: function RegisterListenerRolls(listener) John@71: table.insert(rollListeners,listener) John@71: end John@71: function AlertRollListeners() John@71: for i,v in pairs(rollListeners) do John@71: print("roll out") John@71: v["RollEvent"](v) John@71: end John@71: end John@71: John@72: local listChangeListeners = {} John@72: function RegisterListenerActiveListChanged(listener) John@72: table.insert(listChangeListeners,listener) John@72: end John@72: function AlertActiveListChangedListeners() John@72: for i,v in pairs(listChangeListeners) do John@72: print("list out") John@72: v["ActiveListEvent"](v) John@72: end John@72: end John@72: John@72: local stateChangeListeners = {} John@72: function RegisterListenerStateChange(listener) John@72: table.insert(stateChangeListeners,listener) John@72: end John@72: function AlertStateChangeListeners() John@72: for i,v in pairs(stateChangeListeners) do John@72: print("state out") John@72: v["StateEvent"](v) John@72: end John@72: end John@72: John@73: local itemListListeners = {} John@73: function RegisterItemListListener(listener) John@73: table.insert(itemListListeners,listener) John@73: end John@73: function AlertItemListListeners() John@73: for i,v in pairs(itemListListeners) do John@73: print("item change") John@73: v["ItemListEvent"](v) John@73: end John@73: end John@73: John@73: function BeginLoot(packet) John@73: local items, listValue = unpack(packet) John@71: if state == "neutral" then John@71: state = "looting" John@73: stateactivelist = listValue John@73: stateitemlist = items John@73: AlertItemListListeners() John@73: CreateGUI() -- todo: bad spot, but that's ok for now John@71: else John@71: _G.error("Bad state transition", state, "looting") John@71: end John@71: end John@71: John@73: function InitiateBeginLoot(items,listValue) John@73: if state == "neutral" then John@73: Comm:SendStateChange("BL",items,listValue) John@73: end John@73: end John@72: John@72: -- Activate List {{{ John@72: function ActivateList(packet) -- doesn't cause a transition, but we only enforce a list selection during certain times John@72: local list = unpack(packet) John@71: if state == "looting" then John@72: stateactivelist = list John@72: AlertActiveListChangedListeners() John@71: end John@71: end John@71: John@72: function InitiateActivateList(list) John@72: if state == "looting" then John@72: Comm:SendStateChange("AL",list) John@72: end John@72: end John@72: --}}} John@72: -- Open Bidding {{{ John@71: function OpenBid(packet) John@71: local item = unpack(packet) John@73: if state == "looting" then John@71: state = "bidding" John@75: stateitem = item John@73: AlertStateChangeListeners() John@73: end John@71: end John@71: John@71: function InitiateOpenBid(item) John@73: if state == "looting" then John@73: Comm:SendStateChange("OB",item) John@73: end John@71: end John@72: --}}} John@72: -- Bid {{{ John@78: local function SortByList(lref,unordered) John@78: local t = {} John@78: for le in lref:OrderedListEntryIter() do John@78: local lid = le:GetId() John@78: for i,v in pairs(unordered) do John@78: if v.value == lid then John@78: print("Sort time: insert", lid) John@78: table.insert(t,v) John@78: table.remove(unordered,i) John@78: break -- done with this inner iteration John@78: end John@78: end John@78: end John@78: if getn(t) > 0 then John@78: for i,v in pairs(unordered) do John@78: printf("Disregarding bid/roll from %s because they are not on the list", v.textPlain) John@78: end John@78: end John@78: return t John@78: end John@79: local function SortByRoll(values,unordered) John@79: local t = {} John@79: for r = 100,1,-1 do -- 100:1 John@79: if values[r] then John@79: for i,v in pairs(unordered) do John@79: if v.value == values[r].value then John@79: print("Sort time: insert", v.value, r) John@79: table.insert(t,v) John@79: table.remove(unordered,i) John@79: break John@79: end John@79: end John@79: end John@79: end John@79: if getn(t) > 0 then John@79: for i,v in pairs(unordered) do John@79: printf("Disregarding bid/roll from %s because they are not on the list", v.textPlain) John@79: end John@79: end John@79: return t John@79: end John@71: function ReceivedBid(packet) -- no state transition, but only matters during one state John@71: local person, roll = unpack(packet) John@71: John@71: if state == "bidding" then John@71: if roll then John@79: print("RB: ",person.value,roll) John@79: table.insert(staterolls,person) John@79: staterollvalues[roll] = person John@79: staterolls = SortByRoll(staterollvalues,staterolls) John@78: else John@79: local lref = LootLists:Select(stateactivelist) John@79: table.insert(statebids,person) John@78: statebids = SortByList(lref,statebids) John@71: end John@71: AlertRollListeners() John@71: end John@71: John@71: -- else ignore ... John@71: end John@71: John@71: function InitiateBid(person,roll) John@71: if state == "bidding" then John@78: if not person then John@78: print("You cannot bid becuase you are not on the list") John@78: return John@78: end John@71: for i,v in pairs(statebids) do John@78: if person and person.value == v.value then John@71: print(person.value .. " is already on the list") John@71: return -- no double adds please John@71: end John@71: end John@79: for i,v in pairs(staterolls) do John@79: if person and person.value == v.value then John@79: print(person.value .. " is already on the list") John@79: return -- no double adds please John@79: end John@79: end John@71: Comm:SendStateChange("RB",person,roll) John@71: end John@71: end John@72: --}}} John@72: -- Retration {{{ John@71: function ReceivedRetraction(packet) John@71: local person = unpack(packet) John@71: if state == "bidding" then John@71: for i,v in pairs(statebids) do John@71: if v.value == person.value then John@71: table.remove(statebids,i) John@71: AlertRollListeners() John@71: return John@71: end John@71: end John@79: for i,v in pairs(staterolls) do John@79: if v.value == person.value then John@79: table.remove(staterolls,i) John@79: AlertRollListeners() John@79: return John@79: end John@79: end John@71: end John@71: end John@71: John@71: function InitiateRetract(person) John@71: if state == "bidding" then John@71: Comm:SendStateChange("RR",person,roll) John@71: end John@71: end John@72: --}}} John@72: -- Close Bidding {{{ John@72: function CloseBidding(packet) John@72: local awardedTo = unpack(packet) John@75: if state == "bidding" then John@75: state = "looting" John@75: AlertStateChangeListeners() John@75: -- todo: remove the item from the window, record history John@75: end John@71: end John@71: John@72: function InitiateCloseBidding(awardedTo) John@75: if state == "bidding" then John@75: Comm:SendStateChange("CB",awardedTo) John@75: end John@72: end John@72: --}}} John@73: -- Close Looting {{{ John@72: function CloseLooting(packet) John@71: state = "neutral" John@73: stateactive = nil John@73: stateitem = nil John@73: stateitemlist = {} John@73: statebids = {} John@73: staterolls = {} John@78: staterollvalues = {} John@73: AlertStateChangeListeners() John@73: AlertItemListListeners() John@71: end John@72: John@72: function InitiateCloseLooting() John@72: Comm:SendStateChange("CL") John@72: end John@73: --}}} John@79: function RollRequest(packet) John@79: local person = unpack(packet) John@79: John@79: if state == "bidding" and admin then -- todo: admin should be ML John@79: local roll John@79: for i,v in pairs(staterollvalues) do John@79: if v and v.value == person.value then John@79: roll = i John@79: break John@79: end John@79: end John@79: if not roll then -- roll isn't on cache John@79: repeat -- random until you find a good value John@79: roll = _G.random(100) John@79: until staterollvalues[roll] == nil John@79: print("rolling! ", roll) John@79: staterollvalues[roll] = person John@79: end John@79: InitiateBid(person,roll) John@79: end John@79: end John@79: function InitiateRollRequest(person) John@79: if state == "bidding" then John@79: if not person then John@79: print("You cannot bid becuase you are not on the list") John@79: return John@79: end John@79: for i,v in pairs(staterolls) do John@79: if person and person.value == v.value then John@79: print(person.value .. " is already on the list") John@79: return -- no double adds please John@79: end John@79: end John@79: for i,v in pairs(statebids) do John@79: if person and person.value == v.value then John@79: print(person.value .. " is already on the list") John@79: return -- no double adds please John@79: end John@79: end John@79: Comm:SendStateChange("IR",person,roll) John@79: end John@79: end John@72: function DispatchState(packet) John@72: local state = table.remove(packet,1) John@72: print("Dispatching", state) John@72: if state == "RB" then John@72: ReceivedBid(packet) John@73: elseif state == "BL" then John@73: BeginLoot(packet) John@72: elseif state == "RR" then John@72: ReceivedRetraction(packet) John@72: elseif state == "OB" then John@72: OpenBid(packet) John@72: elseif state == "CB" then John@72: CloseBidding(packet) John@73: elseif state == "CL" then John@72: CloseLooting(packet) John@72: elseif state == "AL" then John@72: ActivateList(packet) John@79: elseif state == "IR" then John@79: RollRequest(packet) John@72: else -- todo ... John@72: John@72: end John@72: end John@72: John@73: function InitializeState() John@79: -- basically, find a value for stateactivelist. it really doesn't matter John@79: -- which one, but I decided on trying to choose one that has entries on it John@79: -- so the whole thing isn't all empty. stateactivelist being anything John@79: -- besides a valid ID could trigger errors John@73: local ltemp = 0 John@73: local lids = LootLists:GetAllIds() John@73: for _,v in pairs(lids) do John@73: local l = LootLists:Select(v) John@73: if l:GetLength() > 0 then John@73: if ltemp == 0 then John@73: ltemp = l:GetId() John@73: end John@73: end John@73: end John@73: stateactivelist = ltemp John@73: end John@73: