annotate State.lua @ 81:62805e6b46c5

Fleshing out the UI for those without the addon. Announcements in the raid, bidding via whisper.
author John@Yosemite-PC
date Fri, 13 Apr 2012 22:09:17 -0400
parents 40c882db34f8
children db7e4ee34dce
rev   line source
John@71 1 local bsk=bsk
John@71 2 local _G=_G
John@71 3 local table=table
John@71 4 local pairs=pairs
John@71 5 local setmetatable=setmetatable
John@71 6 local ipairs=ipairs
John@71 7 local string=string
John@71 8 local sformat=string.format
John@71 9 local tostring=tostring
John@71 10 local type=type
John@71 11 local unpack=unpack
John@71 12 local getn=getn
John@71 13 setfenv(1,bsk)
John@71 14
John@71 15 -- simple state machine
John@71 16
John@71 17 --Begin loot
John@71 18 --Activate list ... only during looting?
John@71 19 --open bidding/rolling
John@71 20 --bid/roll occurred
John@71 21 --remove bid/roll
John@71 22 --close bidding
John@71 23 --remove item
John@71 24
John@71 25
John@71 26 -- we'll track state, but that may or may not result in a GUI change until down
John@71 27 -- the road
John@71 28
John@71 29 -- todo: transmit this all to only the raid, not the guild?
John@71 30
John@71 31 -- sample procedure
John@71 32 -- person B opens GUI.
John@71 33 -- person A begins looting, sets a list
John@71 34 -- person A begins bidding, transmists the state
John@71 35 -- person B goes into bidding state, their button activates
John@71 36 -- person B clicks the button. button changes state.
John@71 37 -- person B broadcasts their bid. if a bid, everyone just accepts it.
John@71 38 -- - if a roll, then the master does the roll and rebroadcasts
John@71 39
John@72 40 state = "neutral" -- states that are possible: neutral, looting, bidding
John@71 41 local looting = false
John@71 42 stateactive = nil
John@71 43 stateitem = nil
John@73 44 stateitemlist = {}
John@71 45 statebids = {}
John@71 46 staterolls = {}
John@78 47 staterollvalues = {}
John@73 48 stateactivelist = nil
John@71 49
John@76 50 -- todo: protect initiators to admin only
John@76 51
John@71 52 local rollListeners = {}
John@71 53 function RegisterListenerRolls(listener)
John@71 54 table.insert(rollListeners,listener)
John@71 55 end
John@71 56 function AlertRollListeners()
John@71 57 for i,v in pairs(rollListeners) do
John@71 58 print("roll out")
John@71 59 v["RollEvent"](v)
John@71 60 end
John@71 61 end
John@71 62
John@72 63 local listChangeListeners = {}
John@72 64 function RegisterListenerActiveListChanged(listener)
John@72 65 table.insert(listChangeListeners,listener)
John@72 66 end
John@72 67 function AlertActiveListChangedListeners()
John@72 68 for i,v in pairs(listChangeListeners) do
John@72 69 print("list out")
John@72 70 v["ActiveListEvent"](v)
John@72 71 end
John@72 72 end
John@72 73
John@72 74 local stateChangeListeners = {}
John@72 75 function RegisterListenerStateChange(listener)
John@72 76 table.insert(stateChangeListeners,listener)
John@72 77 end
John@72 78 function AlertStateChangeListeners()
John@72 79 for i,v in pairs(stateChangeListeners) do
John@72 80 print("state out")
John@72 81 v["StateEvent"](v)
John@72 82 end
John@72 83 end
John@72 84
John@73 85 local itemListListeners = {}
John@73 86 function RegisterItemListListener(listener)
John@73 87 table.insert(itemListListeners,listener)
John@73 88 end
John@73 89 function AlertItemListListeners()
John@73 90 for i,v in pairs(itemListListeners) do
John@73 91 print("item change")
John@73 92 v["ItemListEvent"](v)
John@73 93 end
John@73 94 end
John@73 95
John@73 96 function BeginLoot(packet)
John@73 97 local items, listValue = unpack(packet)
John@71 98 if state == "neutral" then
John@71 99 state = "looting"
John@73 100 stateactivelist = listValue
John@73 101 stateitemlist = items
John@73 102 AlertItemListListeners()
John@73 103 CreateGUI() -- todo: bad spot, but that's ok for now
John@71 104 else
John@71 105 _G.error("Bad state transition", state, "looting")
John@71 106 end
John@71 107 end
John@71 108
John@73 109 function InitiateBeginLoot(items,listValue)
John@73 110 if state == "neutral" then
John@73 111 Comm:SendStateChange("BL",items,listValue)
John@73 112 end
John@73 113 end
John@72 114
John@72 115 -- Activate List {{{
John@72 116 function ActivateList(packet) -- doesn't cause a transition, but we only enforce a list selection during certain times
John@72 117 local list = unpack(packet)
John@71 118 if state == "looting" then
John@72 119 stateactivelist = list
John@72 120 AlertActiveListChangedListeners()
John@71 121 end
John@71 122 end
John@71 123
John@72 124 function InitiateActivateList(list)
John@72 125 if state == "looting" then
John@72 126 Comm:SendStateChange("AL",list)
John@72 127 end
John@72 128 end
John@72 129 --}}}
John@72 130 -- Open Bidding {{{
John@71 131 function OpenBid(packet)
John@71 132 local item = unpack(packet)
John@73 133 if state == "looting" then
John@71 134 state = "bidding"
John@75 135 stateitem = item
John@73 136 AlertStateChangeListeners()
John@81 137 if admin then -- todo: only ML
John@81 138 local chan
John@81 139 if _G.GetNumRaidMembers() > 0 then chan = "RAID" else chan = "PARTY" end
John@81 140 _G.SendChatMessage("Bidding is now open for "..item.link.."!",chan)
John@81 141 _G.SendChatMessage("Whisper me \"bid\" to bid or \"roll\" to offset roll; \"retract\" will remove your bid",chan)
John@81 142 end
John@73 143 end
John@71 144 end
John@71 145
John@71 146 function InitiateOpenBid(item)
John@73 147 if state == "looting" then
John@73 148 Comm:SendStateChange("OB",item)
John@73 149 end
John@71 150 end
John@72 151 --}}}
John@72 152 -- Bid {{{
John@78 153 local function SortByList(lref,unordered)
John@78 154 local t = {}
John@78 155 for le in lref:OrderedListEntryIter() do
John@78 156 local lid = le:GetId()
John@78 157 for i,v in pairs(unordered) do
John@78 158 if v.value == lid then
John@78 159 print("Sort time: insert", lid)
John@78 160 table.insert(t,v)
John@78 161 table.remove(unordered,i)
John@78 162 break -- done with this inner iteration
John@78 163 end
John@78 164 end
John@78 165 end
John@78 166 if getn(t) > 0 then
John@78 167 for i,v in pairs(unordered) do
John@78 168 printf("Disregarding bid/roll from %s because they are not on the list", v.textPlain)
John@78 169 end
John@78 170 end
John@78 171 return t
John@78 172 end
John@79 173 local function SortByRoll(values,unordered)
John@79 174 local t = {}
John@79 175 for r = 100,1,-1 do -- 100:1
John@79 176 if values[r] then
John@79 177 for i,v in pairs(unordered) do
John@79 178 if v.value == values[r].value then
John@79 179 print("Sort time: insert", v.value, r)
John@79 180 table.insert(t,v)
John@79 181 table.remove(unordered,i)
John@79 182 break
John@79 183 end
John@79 184 end
John@79 185 end
John@79 186 end
John@79 187 if getn(t) > 0 then
John@79 188 for i,v in pairs(unordered) do
John@79 189 printf("Disregarding bid/roll from %s because they are not on the list", v.textPlain)
John@79 190 end
John@79 191 end
John@79 192 return t
John@79 193 end
John@71 194 function ReceivedBid(packet) -- no state transition, but only matters during one state
John@71 195 local person, roll = unpack(packet)
John@71 196
John@71 197 if state == "bidding" then
John@71 198 if roll then
John@79 199 table.insert(staterolls,person)
John@79 200 staterollvalues[roll] = person
John@79 201 staterolls = SortByRoll(staterollvalues,staterolls)
John@78 202 else
John@79 203 local lref = LootLists:Select(stateactivelist)
John@79 204 table.insert(statebids,person)
John@78 205 statebids = SortByList(lref,statebids)
John@71 206 end
John@71 207 AlertRollListeners()
John@81 208 if admin then -- todo: make ML
John@81 209 local leader
John@81 210 if getn(statebids) > 0 then
John@81 211 leader = statebids[1].textPlain
John@81 212 elseif getn(staterolls) > 0 then
John@81 213 leader = staterolls[1].textPlain
John@81 214 end
John@81 215
John@81 216 local chan -- todo: this idiom is wearing on me already
John@81 217 if _G.GetNumRaidMembers() > 0 then chan = "RAID" else chan = "PARTY" end
John@81 218
John@81 219 if roll then
John@81 220 _G.SendChatMessage(sformat("Received roll of %d from %s; current leader is %s", roll, person.textPlain, leader),chan)
John@81 221 else
John@81 222 _G.SendChatMessage(sformat("Received bid from %s; current leader is %s", person.textPlain, leader),chan) -- todo: tell what spot they're bidding from
John@81 223 end
John@81 224 end
John@71 225 end
John@71 226
John@71 227 -- else ignore ...
John@71 228 end
John@71 229
John@71 230 function InitiateBid(person,roll)
John@71 231 if state == "bidding" then
John@78 232 if not person then
John@78 233 print("You cannot bid becuase you are not on the list")
John@78 234 return
John@78 235 end
John@71 236 for i,v in pairs(statebids) do
John@78 237 if person and person.value == v.value then
John@71 238 print(person.value .. " is already on the list")
John@71 239 return -- no double adds please
John@71 240 end
John@71 241 end
John@79 242 for i,v in pairs(staterolls) do
John@79 243 if person and person.value == v.value then
John@79 244 print(person.value .. " is already on the list")
John@79 245 return -- no double adds please
John@79 246 end
John@79 247 end
John@71 248 Comm:SendStateChange("RB",person,roll)
John@71 249 end
John@71 250 end
John@72 251 --}}}
John@72 252 -- Retration {{{
John@71 253 function ReceivedRetraction(packet)
John@71 254 local person = unpack(packet)
John@71 255 if state == "bidding" then
John@71 256 for i,v in pairs(statebids) do
John@71 257 if v.value == person.value then
John@71 258 table.remove(statebids,i)
John@71 259 AlertRollListeners()
John@71 260 return
John@71 261 end
John@71 262 end
John@79 263 for i,v in pairs(staterolls) do
John@79 264 if v.value == person.value then
John@79 265 table.remove(staterolls,i)
John@79 266 AlertRollListeners()
John@79 267 return
John@79 268 end
John@79 269 end
John@71 270 end
John@71 271 end
John@71 272
John@71 273 function InitiateRetract(person)
John@71 274 if state == "bidding" then
John@81 275 Comm:SendStateChange("RR",person)
John@71 276 end
John@71 277 end
John@72 278 --}}}
John@72 279 -- Close Bidding {{{
John@80 280 function CloseBidding(packet) -- todo: does not clear enough state
John@72 281 local awardedTo = unpack(packet)
John@75 282 if state == "bidding" then
John@75 283 state = "looting"
John@75 284 AlertStateChangeListeners()
John@81 285 -- todo: record history
John@81 286 if admin then
John@81 287 local chan -- todo: pattern
John@81 288 local chan -- todo: this idiom is wearing on me already
John@81 289 if _G.GetNumRaidMembers() > 0 then chan = "RAID" else chan = "PARTY" end
John@81 290 _G.SendChatMessage("Bidding is closed",chan)
John@81 291 end
John@75 292 end
John@71 293 end
John@71 294
John@72 295 function InitiateCloseBidding(awardedTo)
John@75 296 if state == "bidding" then
John@75 297 Comm:SendStateChange("CB",awardedTo)
John@75 298 end
John@72 299 end
John@72 300 --}}}
John@73 301 -- Close Looting {{{
John@72 302 function CloseLooting(packet)
John@71 303 state = "neutral"
John@73 304 stateactive = nil
John@73 305 stateitem = nil
John@73 306 stateitemlist = {}
John@73 307 statebids = {}
John@73 308 staterolls = {}
John@78 309 staterollvalues = {}
John@73 310 AlertStateChangeListeners()
John@73 311 AlertItemListListeners()
John@71 312 end
John@72 313
John@72 314 function InitiateCloseLooting()
John@72 315 Comm:SendStateChange("CL")
John@72 316 end
John@73 317 --}}}
John@79 318 function RollRequest(packet)
John@79 319 local person = unpack(packet)
John@79 320
John@79 321 if state == "bidding" and admin then -- todo: admin should be ML
John@79 322 local roll
John@79 323 for i,v in pairs(staterollvalues) do
John@79 324 if v and v.value == person.value then
John@79 325 roll = i
John@79 326 break
John@79 327 end
John@79 328 end
John@79 329 if not roll then -- roll isn't on cache
John@79 330 repeat -- random until you find a good value
John@79 331 roll = _G.random(100)
John@79 332 until staterollvalues[roll] == nil
John@79 333 print("rolling! ", roll)
John@79 334 staterollvalues[roll] = person
John@79 335 end
John@79 336 InitiateBid(person,roll)
John@79 337 end
John@79 338 end
John@79 339 function InitiateRollRequest(person)
John@79 340 if state == "bidding" then
John@79 341 if not person then
John@79 342 print("You cannot bid becuase you are not on the list")
John@79 343 return
John@79 344 end
John@79 345 for i,v in pairs(staterolls) do
John@79 346 if person and person.value == v.value then
John@79 347 print(person.value .. " is already on the list")
John@79 348 return -- no double adds please
John@79 349 end
John@79 350 end
John@79 351 for i,v in pairs(statebids) do
John@79 352 if person and person.value == v.value then
John@79 353 print(person.value .. " is already on the list")
John@79 354 return -- no double adds please
John@79 355 end
John@79 356 end
John@79 357 Comm:SendStateChange("IR",person,roll)
John@79 358 end
John@79 359 end
John@72 360 function DispatchState(packet)
John@72 361 local state = table.remove(packet,1)
John@72 362 print("Dispatching", state)
John@72 363 if state == "RB" then
John@72 364 ReceivedBid(packet)
John@73 365 elseif state == "BL" then
John@73 366 BeginLoot(packet)
John@72 367 elseif state == "RR" then
John@72 368 ReceivedRetraction(packet)
John@72 369 elseif state == "OB" then
John@72 370 OpenBid(packet)
John@72 371 elseif state == "CB" then
John@72 372 CloseBidding(packet)
John@73 373 elseif state == "CL" then
John@72 374 CloseLooting(packet)
John@72 375 elseif state == "AL" then
John@72 376 ActivateList(packet)
John@79 377 elseif state == "IR" then
John@79 378 RollRequest(packet)
John@72 379 else -- todo ...
John@72 380
John@72 381 end
John@72 382 end
John@72 383
John@73 384 function InitializeState()
John@79 385 -- basically, find a value for stateactivelist. it really doesn't matter
John@79 386 -- which one, but I decided on trying to choose one that has entries on it
John@79 387 -- so the whole thing isn't all empty. stateactivelist being anything
John@79 388 -- besides a valid ID could trigger errors
John@73 389 local ltemp = 0
John@73 390 local lids = LootLists:GetAllIds()
John@73 391 for _,v in pairs(lids) do
John@73 392 local l = LootLists:Select(v)
John@73 393 if l:GetLength() > 0 then
John@73 394 if ltemp == 0 then
John@73 395 ltemp = l:GetId()
John@73 396 end
John@73 397 end
John@73 398 end
John@73 399 stateactivelist = ltemp
John@73 400 end
John@73 401