annotate State.lua @ 98:0cd1d46e7b66

Admin detection from a string of the format "BSKADMIN: admin1, admin2, ..." in the guild info box
author John@Doomsday
date Fri, 27 Apr 2012 09:41:26 -0400
parents b89558d3e833
children
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@89 137 if admin and masterLooterIsMe then
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@89 208 if admin and masterLooterIsMe then
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@89 280 function CloseBidding(packet)
John@89 281 local awardedTo = unpack(packet) -- todo: unused
John@75 282 if state == "bidding" then
John@75 283 state = "looting"
John@89 284 stateitem = nil
John@89 285 statebids = {}
John@89 286 staterolls = {}
John@89 287 staterollvalues = {}
John@75 288 AlertStateChangeListeners()
John@89 289 AlertItemListListeners()
John@81 290 -- todo: record history
John@81 291 if admin then
John@81 292 local chan -- todo: this idiom is wearing on me already
John@81 293 if _G.GetNumRaidMembers() > 0 then chan = "RAID" else chan = "PARTY" end
John@81 294 _G.SendChatMessage("Bidding is closed",chan)
John@81 295 end
John@75 296 end
John@71 297 end
John@71 298
John@72 299 function InitiateCloseBidding(awardedTo)
John@75 300 if state == "bidding" then
John@75 301 Comm:SendStateChange("CB",awardedTo)
John@75 302 end
John@72 303 end
John@72 304 --}}}
John@73 305 -- Close Looting {{{
John@72 306 function CloseLooting(packet)
John@71 307 state = "neutral"
John@73 308 stateactive = nil
John@73 309 stateitem = nil
John@73 310 stateitemlist = {}
John@73 311 statebids = {}
John@73 312 staterolls = {}
John@78 313 staterollvalues = {}
John@73 314 AlertStateChangeListeners()
John@73 315 AlertItemListListeners()
John@71 316 end
John@72 317
John@72 318 function InitiateCloseLooting()
John@72 319 Comm:SendStateChange("CL")
John@72 320 end
John@73 321 --}}}
John@79 322 function RollRequest(packet)
John@79 323 local person = unpack(packet)
John@79 324
John@89 325 if state == "bidding" and admin and masterLooterIsMe then
John@79 326 local roll
John@79 327 for i,v in pairs(staterollvalues) do
John@79 328 if v and v.value == person.value then
John@79 329 roll = i
John@79 330 break
John@79 331 end
John@79 332 end
John@79 333 if not roll then -- roll isn't on cache
John@79 334 repeat -- random until you find a good value
John@79 335 roll = _G.random(100)
John@79 336 until staterollvalues[roll] == nil
John@79 337 print("rolling! ", roll)
John@79 338 staterollvalues[roll] = person
John@79 339 end
John@79 340 InitiateBid(person,roll)
John@79 341 end
John@79 342 end
John@79 343 function InitiateRollRequest(person)
John@79 344 if state == "bidding" then
John@79 345 if not person then
John@79 346 print("You cannot bid becuase you are not on the list")
John@79 347 return
John@79 348 end
John@79 349 for i,v in pairs(staterolls) do
John@79 350 if person and person.value == v.value then
John@79 351 print(person.value .. " is already on the list")
John@79 352 return -- no double adds please
John@79 353 end
John@79 354 end
John@79 355 for i,v in pairs(statebids) do
John@79 356 if person and person.value == v.value then
John@79 357 print(person.value .. " is already on the list")
John@79 358 return -- no double adds please
John@79 359 end
John@79 360 end
John@79 361 Comm:SendStateChange("IR",person,roll)
John@79 362 end
John@79 363 end
John@82 364
John@82 365 local function LootSlotCleared(packet)
John@82 366 local index = unpack(packet)
John@82 367 if state == "looting" or state == "bidding" then
John@82 368 for i,v in pairs(stateitemlist) do
John@82 369 if v.mlid == index then
John@82 370 v.disabled = true
John@82 371 print("DISABLING")
John@82 372 AlertItemListListeners()
John@82 373 return
John@82 374 end
John@82 375 end
John@82 376 end
John@82 377 end
John@82 378 function InitiateLSClear(index)
John@82 379 if state == "looting" or state == "bidding" then
John@82 380 Comm:SendStateChange("SC",index)
John@82 381 end
John@82 382 end
John@72 383 function DispatchState(packet)
John@72 384 local state = table.remove(packet,1)
John@72 385 print("Dispatching", state)
John@72 386 if state == "RB" then
John@72 387 ReceivedBid(packet)
John@73 388 elseif state == "BL" then
John@73 389 BeginLoot(packet)
John@72 390 elseif state == "RR" then
John@72 391 ReceivedRetraction(packet)
John@72 392 elseif state == "OB" then
John@72 393 OpenBid(packet)
John@72 394 elseif state == "CB" then
John@72 395 CloseBidding(packet)
John@73 396 elseif state == "CL" then
John@72 397 CloseLooting(packet)
John@72 398 elseif state == "AL" then
John@72 399 ActivateList(packet)
John@79 400 elseif state == "IR" then
John@79 401 RollRequest(packet)
John@82 402 elseif state == "SC" then
John@82 403 LootSlotCleared(packet)
John@89 404 else
John@82 405 _G.error("Cannot dispatch message of type:",state)
John@72 406 end
John@72 407 end
John@72 408
John@73 409 function InitializeState()
John@79 410 -- basically, find a value for stateactivelist. it really doesn't matter
John@79 411 -- which one, but I decided on trying to choose one that has entries on it
John@79 412 -- so the whole thing isn't all empty. stateactivelist being anything
John@79 413 -- besides a valid ID could trigger errors
John@73 414 local ltemp = 0
John@73 415 local lids = LootLists:GetAllIds()
John@73 416 for _,v in pairs(lids) do
John@73 417 local l = LootLists:Select(v)
John@73 418 if l:GetLength() > 0 then
John@73 419 if ltemp == 0 then
John@73 420 ltemp = l:GetId()
John@73 421 end
John@73 422 end
John@73 423 end
John@73 424 stateactivelist = ltemp
John@73 425 end
John@73 426