Mercurial > wow > breuesk
changeset 0:47fac96968e1
First commit
author | John@Yosemite-PC |
---|---|
date | Fri, 02 Mar 2012 00:15:09 -0500 |
parents | |
children | 21c58930f74e |
files | .pkgmeta Core.lua Lists.lua Localization/Core.lua Localization/enUS.lua breuesk.toc |
diffstat | 5 files changed, 1002 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.pkgmeta Fri Mar 02 00:15:09 2012 -0500 @@ -0,0 +1,15 @@ +package-as: BreueSK +enable-nolib-creation: no + +externals: + libs/LibStub: svn://svn.wowace.com/wow/libstub/mainline/trunk + libs/AceAddon-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceAddon-3.0 + libs/AceConsole-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConsole-3.0 + libs/AceConfig-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConfig-3.0 + libs/AceComm-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceComm-3.0 + libs/AceDB-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDB-3.0 + libs/AceDBOptions-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDBOptions-3.0 + libs/AceEvent-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceEvent-3.0 + libs/AceHook-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceHook-3.0 + libs/AceLocale-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceLocale-3.0 + libs/AceSerializer-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceSerializer-3.0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core.lua Fri Mar 02 00:15:09 2012 -0500 @@ -0,0 +1,548 @@ +-- ideas: last attended data and/or remove people who haven't attended in X days +-- and/or just a "remove from all lists" option + + +-- order of implementation +-- ( ) lists fully functional (/script interface) +-- ( ) lists single-user functional via command line interface +-- ( ) single user + admin gui (manual suicides) +-- ( ) single user + admin gui (master loot) +-- ( ) communication and list trimming +-- ( ) admins +-- ( ) players gui +-- ( ) crypto / protection against tampering +-- ( ) alt tracking +-- ( ) reserves + +-- important things to remember: +-- 1) ipairs iterates from 1 until the first missing int index -> no gaps +-- 2) a.x === a["x"] +-- 3) a["1"] =/= a[1] + +bsk = LibStub("AceAddon-3.0"):NewAddon("bsk","AceConsole-3.0", "AceHook-3.0", "AceComm-3.0", "AceSerializer-3.0") +local L = LibStub("AceLocale-3.0"):GetLocale("bsk", false) + +local AceGUI = LibStub("AceGUI-3.0") + +function bsk:OnInitialize() + + self.db = LibStub("AceDB-3.0"):New("BskDB", self.defaults, "Default") + + self.options.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db) + LibStub("AceConfig-3.0"):RegisterOptionsTable("bsk", self.options) + self.optionsFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("bsk", "bsk") + + self:RegisterChatCommand("bsk", "HandleCommand") + bsk:CreateWorkingStateFromChanges() +end + +function bsk:OnEnable() + --self:HandleCommand() +end + +function bsk:HandleCommand(paramIn) + local param = { strsplit(" ", paramIn) } + local FixPlayerName = function(p) + p = p:lower() + -- next two lines from sylvanaar + local MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)" + return string.gsub(p, MULTIBYTE_FIRST_CHAR, string.upper, 1) + end + + if param[1] == nil or param[1] == "" then + bsk:Print("need args") + return + end + if param[1] == "players" then + bsk:PrintPlayers() + elseif param[1] == "add" then + if param[2] == nil or param[2] == "" then + bsk:PrintTable(param) + return + end + if param[3] == nil or param[3] == "" then + bsk:PrintTable(param) + return + end + if param[2] == "player" then + --if param[3] == "all" then + -- bsk:Pop + --else + local player = FixPlayerName(param[3]) + bsk:AddPlayer(player) + --end + elseif param[2] == "list" then + bsk:CreateList(param[3]) + end + elseif param[1] == "suicide" then + if param[2] == nil or param[2] == "" or param[3] == nil or param[3] == "" then + bsk:PrintTable(param) + return + end + local player = FixPlayerName(param[2]) + bsk:Print(string.format("Fixed player name %s to %s",param[2],player)) + bsk:SuicidePlayer(player,param[3]) + elseif param[1] == "show" then + if param[2] == nil or param[2] == "" then + bsk:PrintTable(param) + return + end + bsk:PrintLists(param[2]) + end + + -- TODO: add options + -- + -- for now: launch GUI + -- + + --if self.frame == nil then + --self:CreateGUI() + --self:ShowGUI() + --else + --self:ShowGUI() + --end + +end +--MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)" +--function GetNamePattern(name) +-- local u = name:match(MULTIBYTE_FIRST_CHAR):upper() + +-- if not u or u:len() == 0 then Prat.Print("GetNamePattern: name error", name) return end +-- local l = u:lower() +-- local namepat +-- if u == l then +-- namepat = name:lower() +-- elseif u:len() == 1 then +-- namepat = "["..u..l.."]"..name:sub(2):lower() +-- elseif u:len() > 1 then +-- namepat = "" +-- for i=1,u:len() do +-- namepat = namepat .. "[" .. u:sub(i,i)..l:sub(i,i).."]" +-- end +-- namepat = namepat .. name:sub(u:len()+1) +-- end +-- return "%f[%a\192-\255]"..namepat.."%f[^%a\128-\255]" +--end +--AnyNamePattern = "%f[%a\192-\255]([%a\192-\255]+)%f[^%a\128-\255]" + + +function bsk:CreateGUI() + + -- Create a container frame + self.frame = AceGUI:Create("Frame") + self.frame:SetCallback("OnClose",function(widget) AceGUI:Release(widget) end) + self.frame:SetTitle("BSK") + self.frame:SetLayout("Flow") + self.frame:SetHeight(700) + self.frame:SetWidth(350) + local tab = AceGUI:Create("TabGroup") + tab:SetLayout("Flow") + tab:SetTabs( + { + { + text="Tab 1", + value="tab1" + }, + + { + text="Tab 2", + value="tab2" + }, + { + text="Tab 3", + value="tab3" + }, + { + text="Tab 4", + value="tab4" + } + } + ) + tab.width = "fill" + tab.height = "fill" + + tab:SetCallback("OnGroupSelected",ChangeTab) + tab:SelectTab("tab1") + self.frame:AddChild(tab) + + -- Create a button + --local btn = AceGUI:Create("Button") + --btn:SetWidth(170) + --btn:SetText("Button !") + --btn:SetCallback("OnClick", function() print("Click!") end) + -- Add the button to the container + --self.frame:AddChild(btn) +end + +bsk.defaults = { + profile = { + players = {}, + changes = {}, + listBase = {} + } +} + +bsk.options = { + name= 'bsk', + type = 'group', + args = + { + version = + { + type = "execute", + name = "Version query", + desc = "Check others' versions", + func = function(self) self:Print("TODO") end + } + } +} +function ChangeTab(container, event, group) + container:ReleaseChildren() + if group == "tab2" then + local desc = AceGUI:Create("Label") + desc:SetText("This is Tab 1") + desc:SetFullWidth(true) + container:AddChild(desc) + + local button = AceGUI:Create("Button") + button:SetText("Tab 1 Button") + button:SetWidth(200) + container:AddChild(button) + elseif group == "tab1" then + local item2 = {string="item2!", color = {r=1,g=0,b=0.5} } + local itemList = {"Item1", item2, "Item3", "Item4"} + + local myMultiSelect = AceGUI:Create("MultiSelect") + myMultiSelect:SetLabel("My Multi Select") + myMultiSelect:SetWidth(200) + myMultiSelect:SetHeight(400) + myMultiSelect:SetItemList(itemList) + myMultiSelect:SetMultiSelect(false) + container:AddChild(myMultiSelect) + end +end + + + + + + + + + + + +--[[---------------------------------- +-- MultiSelect widget for AceGUI-3.0 +-- Written by Shirokuma +--]]---------------------------------- + + +--[[----------------- +-- AceGUI +--]]----------------- +--local AceGUI = LibStub("AceGUI-3.0") + +--[[----------------- +-- Lua APIs +--]]----------------- +local format, pairs, tostring = string.format, pairs, tostring + +--[[----------------- +-- WoW APIs +--]]----------------- +local CreateFrame, UIParent = CreateFrame, UIParent + +--[[----------------- +-- Frame Elements +--]]----------------- +local FrameBackdrop = { + bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", + edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", + tile = true, tileSize = 16, edgeSize = 16, + insets = { left = 3, right = 3, top = 3, bottom = 3 } +} + + +--[[----------------- +-- Widget Info +--]]----------------- +local widgetType = "MultiSelect" +local widgetVersion = 1 + + +--[[----------------- +-- Event Code +--]]----------------- +local function Label_OnEnter(label) + local self = label.obj + local value = label + self:Fire("OnLabelEnter", value) +end + +local function Label_OnLeave(label) + local self = label.obj + local value = label + self:Fire("OnLabelEnter", value) +end + +local function Label_OnClick(label) + local self = label.obj + local value = label + self:Fire("OnLabelClick", value) + AceGUI:ClearFocus() +end + + +--[[----------------- +-- MultiSelect Code +--]]----------------- +do + local function OnAcquire(self) -- set up the default size + self:SetWidth(200) + self:SetHeight(400) + end + + local function SetWidth(self, w) -- override the SetWidth function to include the labelframe + self.frame:SetWidth(w) + self.labelframe:SetWidth(w-33) + end + + local function SetLabel(self, text) -- sets the multiselect label text + self.label:SetText(text) + end + + local function SetMultiSelect(self, value) -- set if multiple values can be selected simultaneously + self.multiselect = value + end + + local function AddItem(self, str, color) -- add an item (create a new item label object) + local color = color + local label = CreateFrame("Button", nil, self.labelframe) + label.selected = false + label.obj = self + label:SetHeight(18) + label:SetPoint("TOPLEFT", self.labelframe, "TOPLEFT", 0, -(getn(self.labels) * 18)) + label:SetPoint("TOPRIGHT", self.labelframe, "TOPRIGHT", 0, -(getn(self.labels) * 18)) + self.labels[getn(self.labels) + 1] = label + self.labelframe:SetHeight(getn(self.labels) * 18) + + local text = label:CreateFontString(nil,"OVERLAY","GameFontNormalSmall") + text:SetJustifyH("LEFT") + text:SetPoint("TOPLEFT",label,"TOPLEFT",5,0) + text:SetPoint("BOTTOMRIGHT",label,"BOTTOMRIGHT",-5,0) + if color ~= nil then + text:SetTextColor(color.r,color.g,color.b) + end + text:SetText(str) + label.text = text + + local highlight = label:CreateTexture(nil, "OVERLAY") + highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") + highlight:SetBlendMode("ADD") + highlight:SetHeight(14) + highlight:ClearAllPoints() + highlight:SetPoint("RIGHT",label,"RIGHT",0,0) + highlight:SetPoint("LEFT",label,"LEFT",0,0) + highlight:Hide() + label.highlight = highlight + + label:SetScript("OnEnter", function(this) + this.highlight:Show() + Label_OnEnter(this) + end) + label:SetScript("OnLeave", function(this) + if not this.selected then + this.highlight:Hide() + end + end) + label:SetScript("OnClick", function(this) + if not this.selected then + this.selected = true + if not self.multiselect then + for index, items in pairs(self.labels) do + if self.labels[index] ~= this and self.labels[index].selected then + self.labels[index].selected = false + self.labels[index].highlight:Hide() + end + end + end + else + this.selected = false + end + Label_OnClick(this) + end) + end + + local function GetItem(self, text) -- find an object based on the text parameter + for _, value in pairs(self.labels) do + if value.text:GetText() == text then + return value + end + end + return nil + end + + local function GetText(self, value) -- get the text of a label object + for _,item in pairs(self.labels) do + if value == item then + return item.text:GetText() + end + end + return nil + end + + local function SetText(self, value, text) -- set the text of a label object + for _, item in pairs(self.labels) do + if value == item then + value.text:SetText(text) + end + end + end + + local function IsSelected(self, value) -- return if the label object is currently selected + for _, item in pairs(self.labels) do + if value == item then + return item.selected + end + end + return nil + end + + local function GetSelected(self) -- return a table of the currently selected label objects + local selectedList = {} + for _, item in pairs(self.labels) do + if item.selected then + table.insert(selectedList, item) + end + end + return selectedList + end + + local function SetItemList(self, list) -- create new labels from a list of strings + for _,item in pairs(self.labels) do + item:Hide() + item:ClearAllPoints() + end + + self.labels = {} + + if list then + for _,item in pairs(list) do + if type(item) == "string" then + self:AddItem(item) + elseif type(item) == "table" then + if item.string ~= nil and type(item.string) == "string" then + if item.color ~= nil then + if type(item.color) == "table" and item.color.r ~= nil and item.color.g ~= nil and item.color.b ~= nil then + self:AddItem(item.string, item.color) + else + assert(false and "setitemlist: item.color is set, but nonsense") + end + else + self:AddItem(item.string) + end + else + assert( false and "setitemlist: item is table without .string member") + end + else + assert(false and "SetItemList: nonsense list entry") + end + end + end + end + + local function RemoveItem(self, item) -- delete an item + local function RedrawFrame() + for index,value in pairs(self.labels) do + value:SetPoint("TOPLEFT", self.labelframe, "TOPLEFT", 0, (-(index-1) * 18)) + value:SetPoint("TOPRIGHT", self.labelframe, "TOPRIGHT", 0,(-(index-1) * 18)) + end + end + + for index, value in pairs(self.labels) do + if value == item then + table.remove(self.labels, index) + item:Hide() + item:ClearAllPoints() + RedrawFrame() + end + end + end + + local function SetSelected(self, item, value) + if value then + if not self.multiselect then -- test + for _, value in pairs(self.labels) do + value.selected = false + value.highlight:Hide() + end + end + item.selected = true + item.highlight:Show() + else + item.selected = false + item.highlight:Hide() + end + end + + local function Constructor() -- widget constructor + local frame = CreateFrame("Frame", nil, UIParent) + local backdrop = CreateFrame("Frame", nil, frame) + local self = {} + local labels = {} + + self.type = widgetType + self.frame = frame + self.backdrop = backdrop + self.labels = {} + self.multiselect = true + frame.obj = self + + local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall") + label:SetJustifyH("LEFT") + label:SetPoint("TOPLEFT", 5, 0) + label:SetPoint("TOPRIGHT", -5, 0) + label:SetHeight(14) + label:SetText("MultiSelect") + self.label = label + + backdrop:SetBackdrop(FrameBackdrop) + backdrop:SetBackdropColor(0, 0, 0) + backdrop:SetBackdropBorderColor(0.4, 0.4, 0.4) + backdrop:SetPoint("TOPLEFT", frame, "TOPLEFT", 5, -14) + backdrop:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -5, 0) + + local scrollframe = CreateFrame("ScrollFrame", format("%s@%s@%s", widgetType, "ScrollFrame", tostring(self)), frame, "UIPanelScrollFrameTemplate") + scrollframe:SetPoint("TOPLEFT", backdrop, "TOPLEFT", 5, -6) + scrollframe:SetPoint("BOTTOMRIGHT", backdrop, "BOTTOMRIGHT", -28, 6) + scrollframe.obj = self + self.scrollframe = scrollframe + + local labelframe = CreateFrame("Frame", nil, scrollframe) + labelframe:SetAllPoints() + labelframe.obj = self + scrollframe:SetScrollChild(labelframe) + self.labelframe = labelframe + + -- method listing + self.OnAcquire = OnAcquire + self.SetLabel = SetLabel + self.AddItem = AddItem + self.SetWidth = SetWidth + self.SetMultiSelect = SetMultiSelect + self.SetItemList = SetItemList + self.GetItem = GetItem + self.RemoveItem = RemoveItem + self.GetText = GetText + self.SetText = SetText + self.IsSelected = IsSelected + self.GetSelected = GetSelected + self.SetSelected = SetSelected + + AceGUI:RegisterAsWidget(self) + return self + end + AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion) +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lists.lua Fri Mar 02 00:15:09 2012 -0500 @@ -0,0 +1,408 @@ +-- lists consist of three things +-- 1) a base state - agreed on by one or more list holders +-- 2) change sets - incremental list changes (can be rolled forwards or +-- backwards) +-- 3) working state - not saved because it can be so easily calculated +-- +-- A separate user list is held - lists index into this + + +-- TODO: rename player + + + +bsk.lists = {} +bsk.players = {} + +local RaidList = {} +local ReserveList = {} +local activeList = 0 -- temporary + +local tinsert = table.insert +local sformat = string.format +local getn = table.getn + +function bsk:tcopy(to, from) + for k,v in pairs(from) do + if(type(v)=="table") then + to[k] = {} + bsk:tcopy(to[k], v); + else + to[k] = v; + end + end +end +local shallowCopy = function(t) + local u = { } + for k, v in pairs(t) do u[k] = v end + return setmetatable(u, getmetatable(t)) +end + +function bsk:PrintTable(table, depth) + depth = depth or "" + if not table then return end + for i,v in pairs(table) do + if( type(v) == "string" ) then + self:Print(depth .. i .. " - " .. v) + elseif( type(v) == "number" ) then + self:Print(depth .. i .. " - " .. tostring(v)) + elseif( type(v) == "table" ) then + self:Print(depth .. i .." - ") + self:PrintTable(v,depth.." ") + elseif( type(v) == "boolean" ) then + self:Print(depth .. i .. " - " .. tostring(v)) + else + self:Print(depth .. i .. " - not sure how to print type: " .. type(v) ) + end + end +end + +-- Debugging {{{ +function bsk:PrintLists() + bsk:PrintTable(bsk.lists) +end +function bsk:PrintChanges() + bsk:PrintTable(bsk.db.profile.changes) +end +function bsk:PrintPlayers() + bsk:PrintTable(bsk.players) +end +--}}} + +function bsk:CreateWorkingStateFromChanges() + local playerBase = self.db.profile.players + local listBase = self.db.profile.listBase + local changes = self.db.profile.changes + + -- copy the base to the working state + wipe(bsk.lists) + wipe(bsk.players) + bsk:tcopy(bsk.lists,listBase) + bsk:tcopy(bsk.players,playerBase) + + -- now just go through the changes list applying each + for i,v in pairs(changes) do + bsk:ProcessChange(v) + end +end + +function bsk:CreateChange(change) + -- sanity + assert(change) + assert(change.action) + assert(change.arg) + + bsk:StartChange(change) + bsk:CommitChange(change) +end + +function bsk:StartChange(change) + local changes = self.db.profile.changes + change.time = time() + local n = getn(changes) + if n > 0 then + if changes[n].time >= change.time then + change.time = changes[n].time + 1 + end + end +end + +function bsk:CommitChange(change) + local changes = self.db.profile.changes + tinsert(changes,change) + -- TODO: broadcast change +end + + +-- timestamp logic: +-- use time() for comparisons - local clients use date() to make it pretty. only +-- dowisde - we can't have a server timestamp. Which kind of sucks, but it turns +-- out you can change timezones when you enter an instance server, so you really +-- never know what time it is. +-- There's unfortunately no hard-and-proven method for determining the true time +-- difference between local time and server time. You can't just query the two +-- and compare them because your server timezone can change (!) if you go into +-- an instance server with a different timezone. This is apparently a big +-- problem on Oceanic realms. +-- +-- Timestamp handling (brainstorming how to deal with drift): +-- (not an issue) if someone sends you time in the future, update your offset so you won't +-- send out events in the "past" to that person +-- (not an issue - using local UTC now) on change-zone-event: check if you've changed timezones - might need update +-- each time you add a change, check the tail of the change list; if this is +-- less than that, you have a problem. Print a message. if this is equal, then +-- that's ok, just bump it by 1 second. This could happen in the case of, say, +-- spam-clicking the undo button or adding names to the list. The recipients +-- should be ok with this since they'll follow the same algorithm. The only +-- real chance for a problem is if two people click within the 1 second window? +-- if someone sends you a past event, +-- it's ok if it's newer than anything in the changes list +-- otherwise ... causality has been violated. +-- Whenever an admin signon event happens, have the admins each perform a +-- timestamp check. Issue warnings for anyone with a clock that's more than +-- X seconds out of sync with the others. Seriously, why isn't NTP a standard +-- setting on all operating systems ... + +function bsk:ProcessChange(change) + if change.action == "AddPlayer" then + bsk:DoAddPlayer(change) + elseif change.action == "CreateList" then + bsk:DoCreateList(change) + elseif change.action == "AddPlayerToList" then + bsk:DoAddPlayerToList(change) + elseif change.action == "SuicidePlayer" then + bsk:DoSuicidePlayer(change) + else + bsk:Print("Unknown message encountered") + bsk:PrintTable(change) + assert(false) + end +end + + +-- +-- The actual actions for changes start here +-- +-- Each action occurs as a pair of functions. The bsk:Action() function is from +-- a list admin's point of view. Each will check for admin status, then create a +-- change bundle, call the handler for that change (ie the DoAction func), and +-- then record/transmist the bundle. These are simple and repetitive functions. +-- +-- The bsk:DoAction() function is tasked with executing the bundle and is what +-- non-admins and admins alike will call to transform their working state via a +-- change packet. Each Do() function will accept *only* a change packet, and +-- it's assumed that the change has been vetted elsewhere. These are very blunt +-- routines. +-- +-- Note that "undo" has no special voodoo to it. It's basically a change that +-- reverses the prior change on the stack. + +-- Players list +function bsk:DoAddPlayer(change) + assert(change) + assert(change.arg.guid) + local arg = change.arg + -- require admin + local players = bsk.players + local name = arg.name + local guid = arg.guid + assert(players[guid]==nil) + players[guid] = name + players.time=change.time + return true +end + +function bsk:AddPlayer(name) + local players = bsk.players + local guid = UnitGUID(name) + -- TODO: check guid to be sure it's a player + if not guid then + self:Print(sformat("Could not add player %s - they must be in range or group",name)) + return + end + if players[guid] and players[guid] ~= name then + self:Print(sformat("Namechange detected for %s - new is %s, please rename the existing entry", players[guid], name)) + return + end + if players[guid] ~= nil then + self:Print(sformat("%s is already in the players list; disregarding", name)) + return + end + local change = {action="AddPlayer",arg={name=name,guid=guid}} + if bsk:DoAddPlayer(change) then + bsk:CreateChange(change) + end +end + +function bsk:CreateFakeLists() + -- testing only +end + +function bsk:DoCreateList(change) + -- TODO: this segment will probably be useful as bsk:SearchForListByName + local lists = bsk.lists + for i,v in pairs(lists) do + if v.name == change.arg.name then + self:Print(sformat("List %s already exists",v.name)) + return false + end + end + tinsert(lists,{name=change.arg.name,time=change.time}) + return true +end + +function bsk:CreateList(name) + -- require admin + local change={action="CreateList",arg={name=name}} + bsk:StartChange(change) + self:Print("Creating ... " .. name) + if bsk:DoCreateList(change) then + bsk:CommitChange(change) + end +end + +function bsk:DoAddPlayerToList(change) + local listIndex = change.arg.listIndex + local slist = change.arg.slist + local list = bsk.lists[listIndex] + + if #slist == 1 then -- end of list insertion - just one person + tinsert(list,slist[1]) + list.time = change.time + else + self:Print("Adding to middle of list is not yet supported") + return false + end + return true +end + +function bsk:AddPlayerToList(name,list) + -- require admin + local listIndex = bsk:GetListIndex(list) + local slist = {name} -- TODO: support adding to elsewhere besides the end + local change = {action="AddPlayerToList",arg={name=name,listIndex=listIndex,slist=slist}} + bsk:StartChange(change) + if bsk:DoAddPlayerToList(change) then + bsk:CommitChange(change) + end +end + +function bsk:DoRemovePlayer(change) + + -- return true +end + +function bsk:RemovePlayer(name) + -- from both players and lists +end + +function bsk:GetSuicideList(name,list) + --self:Print("Calculating changeset for "..name.." from list -") + --self:PrintTable(list) + local t = {} + local ret = {} + local pushing = false + for i = 1, #list do + if list[i] == name then + pushing = true + end + if pushing and (RaidList[list[i]] or ReserveList[list[i]]) then + tinsert(ret,list[i]) + end + end + return ret +end + +function bsk:GetActiveList() + return bsk.lists[1] -- todo! +end + +function bsk:DoSuicidePlayer(change) + local listIndex = change.arg.listIndex + local list = bsk.lists[listIndex] + local slist = shallowCopy(change.arg.list) + -- the goal here is to rotate the suicide list by 1 + -- then we can just mash it on top of the intersection between the original + -- list and the working copy + local stemp = shallowCopy(change.arg.list) + local temp = table.remove(stemp,1) -- pop + tinsert(stemp,temp) -- push_back + --bsk:Print(sformat("Before suicide of %s on list %s",slist[1],list.name)) + --bsk:PrintTable(list) + for i = 1, #list do + if list[i] == slist[1] then + table.remove(slist,1) + list[i] = stemp[1] + table.remove(stemp,1) + end + end + list.time=change.time + --bsk:Print("After") + --bsk:PrintTable(list) + return true +end + +function bsk:SuicidePlayer(name,list) + -- require admin + local l=bsk:GetActiveList() + bsk:PopulateRaidList() + local slist=bsk:GetSuicideList(name,l) + local listIndex = bsk:GetListIndex(list) + local change = {action="SuicidePlayer",arg={names=names,list=slist,listIndex=listIndex}} + bsk:StartChange(change) + if bsk:DoSuicidePlayer(change) then + bsk:CommitChange(change) + end +end + +-- The following code is from Xinhuan (wowace forum member) +-- Pre-create the unitID strings we will use +local pID = {} +local rID = {} +for i = 1, 4 do + pID[i] = format("party%d", i) +end +for i = 1, 40 do + rID[i] = format("raid%d", i) +end +function bsk:PopulateRaidList() + local inParty = GetNumPartyMembers() + local inRaid = GetNumRaidMembers() + + wipe(RaidList) + if inRaid > 0 then + for i = 1, inRaid do + RaidList[UnitName(rID[i])]=true + end + elseif inParty > 0 then + for i = 1, inParty do + RaidList[UnitName(pID[i])]=true + end + -- Now add yourself as the last party member + RaidList[UnitName("player")]=true + else + -- You're alone + RaidList[UnitName("player")]=true + end +end + +-- undo rules! +-- only the most recent event can be undone +-- ^^^ on a given list? +-- algorithm is easy, given "Suicide A B C" +-- just find A,B,C in the list and replace in order from the s message +-- while undo is allowed *per-list*, certain events in the stream will +-- prevent proper undo, such as add/delete player or add/delete list + + + + +-- reserves +function bsk:AddReserve(name) + ReserveList[name]=true + -- TODO: communicate to others. don't store this in any way. +end + +function bsk:RemoveReserve(name) + ReserveList[name]=false + -- TODO: communicate to others. don't store this in any way. +end + + + + + + + + + +-- Support functions + +function bsk:GetListIndex(name) + for i,v in pairs(bsk.lists) do + if v.name == name then + return i + end + end + assert(false) +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Localization/enUS.lua Fri Mar 02 00:15:09 2012 -0500 @@ -0,0 +1,6 @@ +local AceLocale = LibStub:GetLibrary("AceLocale-3.0") +local L = AceLocale:NewLocale("bsk","enUS",true) +if not L then return end + +-- English +L["test"] = true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breuesk.toc Fri Mar 02 00:15:09 2012 -0500 @@ -0,0 +1,25 @@ +## Interface: 40300 + +## Title: Breue SK +## Name: Breue SK +## Notes: Suicide Kings Addon +## Version: 4.3 + +## SavedVariables: BskDB + +Libs\LibStub\LibStub.lua +Libs\AceAddon-3.0\AceAddon-3.0.xml +Libs\AceConsole-3.0\AceConsole-3.0.xml +Libs\AceConfig-3.0\AceConfig-3.0.xml +Libs\AceComm-3.0\AceComm-3.0.xml +Libs\AceDB-3.0\AceDB-3.0.xml +Libs\AceDBOptions-3.0\AceDBOptions-3.0.xml +Libs\AceEvent-3.0\AceEvent-3.0.xml +Libs\AceHook-3.0\AceHook-3.0.xml +Libs\AceLocale-3.0\AceLocale-3.0.xml +Libs\AceSerializer-3.0\AceSerializer-3.0.xml + +Localization\enUS.lua +Core.lua +Lists.lua +