view State.lua @ 77:0a3f590f69e6

Update todo list Helper function to print list status
author John@Yosemite-PC
date Thu, 12 Apr 2012 22:18:05 -0400
parents 39be9328acd0
children 5b507f4125d4
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 = {}
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()
    end
end

function InitiateOpenBid(item)
    if state == "looting" then
        Comm:SendStateChange("OB",item)
    end
end
--}}}
-- Bid {{{
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(statebids,person) -- todo:
        else
            table.insert(statebids,person) -- todo: keep sorted
        end
        AlertRollListeners()
    end

    -- else ignore ...
end

function InitiateBid(person,roll)
    if state == "bidding" then
        for i,v in pairs(statebids) do
            if 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
    end
end

function InitiateRetract(person)
    if state == "bidding" then
        Comm:SendStateChange("RR",person,roll)
    end
end
--}}}
-- Close Bidding {{{
function CloseBidding(packet)
    local awardedTo = unpack(packet) 
    if state == "bidding" then
        state = "looting"
        AlertStateChangeListeners()
        -- todo: remove the item from the window, record history
    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 = {}
    AlertStateChangeListeners()
    AlertItemListListeners()
end

function InitiateCloseLooting()
    Comm:SendStateChange("CL")
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)
    else -- todo ...

    end
end

function InitializeState()
    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