From 106c63d721608db2c5ff9173198e90a70e7494d0 Mon Sep 17 00:00:00 2001 From: Road-block Date: Tue, 21 Nov 2017 03:26:12 +0200 Subject: [PATCH] Changed default baseGP to 100 and default decay to 10%. If you are an admin verify your settings. A number of settings have moved from global saved variables to per character to facilitate usage for players that raid in multiple guilds. First character that logins with a 3.30+ version will keep the old values for main, decay, progress, offspec discount and standby (reserves) channel. Subsequent characters that login will get new defaults. Add a more detailed breakdown of PR changes to item tooltips (shows both the change and result). Add EPGP cap calculations, show PR loss on next Decay when player is nearing cap. Add an import option for the guild leader in the EPGP standings window menu. Refactor the export epgp dialog so that it can also work as an import. Add an asterisk to the player's name in standings to make it easier to spot. Add the loss of PR in next Decay next to current PR value when they are getting close to EPGP cap. --- shootyepgp.lua | 72 +++++++++++++++++++------- shootyepgp.toc | 9 ++-- standings.lua | 133 +++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 165 insertions(+), 49 deletions(-) diff --git a/shootyepgp.lua b/shootyepgp.lua index ab35165..1b6c775 100644 --- a/shootyepgp.lua +++ b/shootyepgp.lua @@ -7,9 +7,9 @@ local BC = AceLibrary("Babble-Class-2.2") local DF = AceLibrary("Deformat-2.0") local G = AceLibrary("Gratuity-2.0") sepgp.VARS = { - basegp = 135, + basegp = 100, baseaward_ep = 100, - decay = 0.85, + decay = 0.9, max = 5000, timeout = 60, maxloglines = 500, @@ -22,7 +22,7 @@ sepgp.VARS = { bankde = "Bank-D/E", reminder = C:Red("Unassigned"), } -local playerName = (UnitName("player")) +sepgp._playerName = (UnitName("player")) local shooty_reservechan = "Reserves" local shooty_reservecall = string.format("{shootyepgp}Type \"+\" if on main, or \"+\" (without quotes) if on alt within %dsec.",sepgp.VARS.timeout) local shooty_reserveanswer = "^(%+)(%a*)$" @@ -50,8 +50,7 @@ do hexColorQuality[ITEM_QUALITY_COLORS[i].hex] = i end end --- TODO: --- 2. Implement an Import facility to mirror Export. + sepgp.reserves = {} sepgp.bids_main,sepgp.bids_off,sepgp.bid_item = {},{},{} sepgp.timer = CreateFrame("Frame") @@ -260,20 +259,22 @@ function sepgp:AddDataToTooltip(tooltip,itemlink,itemstring,is_master) if not price then return end local line_limit, left1,right1 if (is_master) then - line_limit = 28 + line_limit = 27 left1,right1 = C:Yellow("Alt Click/RClick/MClick"), C:Orange("Call for: MS/OS/Both") else - line_limit = 29 + line_limit = 28 end - local ep,gp = (self:get_ep_v3(playerName) or 0), (self:get_gp_v3(playerName) or sepgp.VARS.basegp) + local ep,gp = (self:get_ep_v3(self._playerName) or 0), (self:get_gp_v3(self._playerName) or sepgp.VARS.basegp) local off_price = math.floor(price*sepgp_discount) local pr,new_pr,new_pr_off = ep/gp, ep/(gp+price), ep/(gp+off_price) local pr_delta = new_pr - pr local pr_delta_off = new_pr_off - pr - local textRight = string.format("gp:|cff32cd32%d|r(|cffff0000%.02f|r|cffff7f00pr|r) os:|cff20b2aa%d|r(|cffff0000%.02f|r|cffff7f00pr|r)",price,new_pr,off_price,new_pr_off) + local textRight = string.format("gp:|cff32cd32%d|r gp_os:|cff20b2aa%d|r",price,off_price) + local textRight2 = string.format("pr:|cffff0000%.02f|r(%.02f) pr_os:|cffff0000%.02f|r(%.02f)",pr_delta,new_pr,pr_delta_off,new_pr_off) if (tooltip:NumLines() < line_limit) then tooltip:AddLine(" ") tooltip:AddDoubleLine("|cff9664c8shootyepgp|r",textRight) + tooltip:AddDoubleLine(" ",textRight2) if (is_master) then tooltip:AddDoubleLine(left1,right1) end @@ -285,7 +286,8 @@ function sepgp:AddDataToTooltip(tooltip,itemlink,itemstring,is_master) sepgp.extratip:SetPoint("TOPLEFT", tooltip, "BOTTOMLEFT", 0, -5) --sepgp.extratip:SetPoint("TOPRIGHT", tooltip, "BOTTOMRIGHT", 0, -5) sepgp.extratip:SetText("|cff9664c8shootyepgp|r") - sepgp.extratip:AddLine(textRight) + sepgp.extratip:AddDoubleLine(" ",textRight) + sepgp.extratip:AddDoubleLine(" ",textRight2) if (is_master) then sepgp.extratip:AddDoubleLine(left1,right1) end @@ -531,7 +533,7 @@ end function sepgp:addonComms(prefix,message,channel,sender) if not prefix == self.VARS.prefix then return end -- we don't care for messages from other addons - if sender == playerName then return end -- we don't care for messages from ourselves + if sender == self._playerName then return end -- we don't care for messages from ourselves local name_g,class,rank = self:verifyGuildMember(sender,true) if not (name_g) then return end -- only accept messages from guild members local who,what,amount @@ -542,7 +544,7 @@ function sepgp:addonComms(prefix,message,channel,sender) end if (who) and (what) and (amount) then local msg - if who == playerName then + if who == self._playerName then if what == "EP" then if amount < 0 then msg = string.format("You have received a %d EP penalty.",amount) @@ -886,16 +888,41 @@ function sepgp:gp_reset_v3() end end +function sepgp:capcalc(ep,gp,gain) + -- CAP_EP = EP_GAIN*DECAY/(1-DECAY) CAP_PR = CAP_EP/base_gp + local pr = ep/gp + local ep_decayed = self:num_round(ep*sepgp_decay) + local gp_decayed = math.max(sepgp.VARS.basegp,self:num_round(gp*sepgp_decay)) + local pr_decay = tonumber(string.format("%.03f",pr))-tonumber(string.format("%.03f",ep_decayed/gp_decayed)) + if pr_decay < 0.01 then + pr_decay = 0 + else + pr_decay = -tonumber(string.format("%.02f",pr_decay)) + end + local cycle_gain = tonumber(gain) + local cap_ep, cap_pr + if (cycle_gain) then + cap_ep = self:num_round(cycle_gain*sepgp_decay/(1-sepgp_decay)) + cap_pr = tonumber(string.format("%.03f",cap_ep/sepgp.VARS.basegp)) + end + return pr_decay, cap_ep, cap_pr +end + function sepgp:my_epgp_announce() - local ep,gp = (self:get_ep_v3(playerName) or 0), (self:get_gp_v3(playerName) or sepgp.VARS.basegp) + local ep,gp = (self:get_ep_v3(self._playerName) or 0), (self:get_gp_v3(self._playerName) or sepgp.VARS.basegp) local pr = ep/gp local msg = string.format("You now have: %d EP %d GP |cffffff00%.03f|r|cffff7f00PR|r.", ep,gp,pr) self:defaultPrint(msg) + local pr_decay, cap_ep, cap_pr = self:capcalc(ep,gp) + if pr_decay < 0 then + msg = string.format("Close to EPGP Cap. Next Decay will change your |cffff7f00PR|r by |cffff0000%.4g|r.",pr_decay) + self:defaultPrint(msg) + end end function sepgp:my_epgp() GuildRoster() - self:ScheduleEvent("shootyepgpRosterRefresh",self.my_epgp_announce,2,self) + self:ScheduleEvent("shootyepgpRosterRefresh",self.my_epgp_announce,3,self) end --------- @@ -1244,7 +1271,7 @@ end function sepgp:sendReserverResponce() if sepgp.reservesChannelID ~= nil then if (sepgp_main) then - if sepgp_main == playerName then + if sepgp_main == self._playerName then SendChatMessage("+","CHANNEL",nil,sepgp.reservesChannelID) else SendChatMessage(string.format("+%s",sepgp_main),"CHANNEL",nil,sepgp.reservesChannelID) @@ -1352,7 +1379,7 @@ function sepgp:captureLootCall(text, sender) if (link_found) then local quality = hexColorQuality[itemColor] or -1 if (quality >= 3) then - if (IsRaidLeader() or self:lootMaster()) and (sender == playerName) then + if (IsRaidLeader() or self:lootMaster()) and (sender == self._playerName) then self:clearBids(true) sepgp.bid_item.link = itemString sepgp.bid_item.linkFull = itemLink @@ -1594,6 +1621,13 @@ function sepgp:num_round(i) return math.floor(i+0.5) end +function sepgp:strsplit(delimiter, subject) + local delimiter, fields = delimiter or ":", {} + local pattern = string.format("([^%s]+)", delimiter) + string.gsub(subject, pattern, function(c) fields[table.getn(fields)+1] = c end) + return unpack(fields) +end + function sepgp:verifyGuildMember(name,silent) for i=1,GetNumGuildMembers(1) do local g_name, g_rank, g_rankIndex, g_level, g_class, g_zone, g_note, g_officernote, g_online = GetGuildRosterInfo(i) @@ -1791,7 +1825,7 @@ local sepgp_auto_gp_menu = { if (dialog) then local data = dialog.data local player, price = data[sepgp.loot_index.player], data[sepgp.loot_index.price] - sepgp:givename_gp((player==YOU and playerName or player),price) + sepgp:givename_gp((player==YOU and sepgp._playerName or player),price) data[sepgp.loot_index.action] = sepgp.VARS.msgp local update = data[sepgp.loot_index.update] ~= nil sepgp:addOrUpdateLoot(data,update) @@ -1804,7 +1838,7 @@ local sepgp_auto_gp_menu = { if (dialog) then local data = dialog.data local player, off_price = data[sepgp.loot_index.player], data[sepgp.loot_index.off_price] - sepgp:givename_gp((player==YOU and playerName or player),off_price) + sepgp:givename_gp((player==YOU and sepgp._playerName or player),off_price) data[sepgp.loot_index.action] = sepgp.VARS.osgp local update = data[sepgp.loot_index.update] ~= nil sepgp:addOrUpdateLoot(data,update) @@ -1873,4 +1907,4 @@ function sepgp:EasyMenu_Initialize(level, menuList) end -- GLOBALS: sepgp_saychannel,sepgp_groupbyclass,sepgp_raidonly,sepgp_decay,sepgp_reservechannel,sepgp_main,sepgp_progress,sepgp_discount,sepgp_log,sepgp_dbver,sepgp_looted --- GLOBALS: sepgp,sepgp_prices,sepgp_standings,sepgp_bids,sepgp_loot,sepgp_reserves,sepgp_logs \ No newline at end of file +-- GLOBALS: sepgp,sepgp_prices,sepgp_standings,sepgp_bids,sepgp_loot,sepgp_reserves,sepgp_logs diff --git a/shootyepgp.toc b/shootyepgp.toc index b4654e3..1060774 100644 --- a/shootyepgp.toc +++ b/shootyepgp.toc @@ -5,10 +5,11 @@ ## X-Website: https://github.com/Road-block/shootyepgp/releases/latest ## X-Category: Guild ## X-Credits: shooty -## Version: 3.21.2 +## Version: 3.30 +## X-Alpha: ## OptionalDeps: Ace2 -## SavedVariables: sepgp_saychannel,sepgp_groupbyclass,sepgp_raidonly,sepgp_decay,sepgp_reservechannel,sepgp_main,sepgp_progress,sepgp_discount -## SavedVariablesPerCharacter: sepgp_log, sepgp_dbver, sepgp_looted +## SavedVariables: sepgp_saychannel, sepgp_groupbyclass, sepgp_raidonly, sepgp_dbver +## SavedVariablesPerCharacter: sepgp_main, sepgp_log, sepgp_looted, sepgp_decay, sepgp_reservechannel, sepgp_progress, sepgp_discount Libs\AceLibrary\AceLibrary.lua Libs\AceOO-2.0\AceOO-2.0.lua @@ -38,4 +39,4 @@ standings.lua bids.lua loot.lua reserves.lua -logs.lua \ No newline at end of file +logs.lua diff --git a/standings.lua b/standings.lua index 3608d72..0041a12 100644 --- a/standings.lua +++ b/standings.lua @@ -21,13 +21,19 @@ shooty_export:SetBackdrop({ }) shooty_export:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) shooty_export:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) +shooty_export.action = CreateFrame("Button","shooty_exportaction", shooty_export, "UIPanelButtonTemplate") +shooty_export.action:SetWidth(100) +shooty_export.action:SetHeight(22) +shooty_export.action:SetPoint("BOTTOM",0,-20) +shooty_export.action:SetText("Import") +shooty_export.action:Hide() +shooty_export.action:SetScript("OnClick",function() sepgp_standings.import() end) shooty_export.title = shooty_export:CreateFontString(nil,"OVERLAY") shooty_export.title:SetPoint("TOP",0,-5) shooty_export.title:SetFont("Fonts\\FRIZQT__.TTF", 12) shooty_export.title:SetWidth(200) shooty_export.title:SetJustifyH("LEFT") shooty_export.title:SetJustifyV("CENTER") -shooty_export.title:SetText(C:Gold("Ctrl-C to copy. Esc to close.")) shooty_export.title:SetShadowOffset(1, -1) shooty_export.edit = CreateFrame("EditBox", "shooty_exportedit", shooty_export) shooty_export.edit:SetMultiLine(true) @@ -42,6 +48,12 @@ shooty_export.edit:SetScript("OnEscapePressed", function() shooty_export.edit:SetText("") shooty_export:Hide() end) +shooty_export.edit:SetScript("OnEditFocusGained", function() + shooty_export.edit:HighlightText() +end) +shooty_export.edit:SetScript("OnCursorChanged", function() + shooty_export.edit:HighlightText() +end) shooty_export.AddSelectText = function(txt) shooty_export.edit:SetText(txt) shooty_export.edit:HighlightText() @@ -52,6 +64,78 @@ shooty_export.scroll:SetPoint('BOTTOMRIGHT', shooty_export, 'BOTTOMRIGHT', -30, shooty_export.scroll:SetScrollChild(shooty_export.edit) table.insert(UISpecialFrames,"shooty_exportframe") +function sepgp_standings:Export() + shooty_export.action:Hide() + shooty_export.title:SetText(C:Gold("Ctrl-C to copy. Esc to close.")) + local t = {} + for i = 1, GetNumGuildMembers(1) do + local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i) + local ep = (sepgp:get_ep_v3(name,officernote) or 0) --DONE: update v3 + local gp = (sepgp:get_gp_v3(name,officernote) or sepgp.VARS.basegp) --DONE: update v3 + if ep > 0 then + table.insert(t,{name,ep,gp,ep/gp}) + end + end + table.sort(t, function(a,b) + return tonumber(a[4]) > tonumber(b[4]) + end) + shooty_export:Show() + local txt = "Name;EP;GP;PR\n" + for i,val in ipairs(t) do + txt = string.format("%s%s;%d;%d;%.4f\n",txt,val[1],val[2],val[3],val[4]) + end + shooty_export.AddSelectText(txt) +end + +function sepgp_standings:Import() + if not IsGuildLeader() then return end + shooty_export.action:Show() + shooty_export.title:SetText(C:Red("Ctrl-V to paste data. Esc to close.")) + shooty_export.AddSelectText([[Warning: +Import overwrites all existing EPGP values. + +Paste all the csv data here replacing this text, +then hit Import. +Results will print here when done.]]) + shooty_export:Show() +end + +function sepgp_standings.import() + if not IsGuildLeader() then return end + local text = shooty_export.edit:GetText() + local t = {} + local found + for line in string.gfind(text,"[^\r\n]+") do + local name,ep,gp,pr = sepgp:strsplit(";",line) + ep,gp,pr = tonumber(ep),tonumber(gp),tonumber(pr) + if (name) and (ep) and (gp) and (pr) then + t[name]={ep,gp} + found = true + end + end + if (found) then + local count = 0 + shooty_export.edit:SetText("") + for i=1,GetNumGuildMembers(1) do + local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i) + local name_epgp = t[name] + if (name_epgp) then + count = count + 1 + --sepgp:debugPrint(string.format("%s {%s:%s}",name,name_epgp[1],name_epgp[2])) -- Debug + sepgp:update_epgp_v3(name_epgp[1],name_epgp[2],i,name,officernote) + t[name]=nil + end + end + sepgp:defaultPrint(string.format("Imported %d members.",count)) + local report = string.format("Imported %d members.\n",count) + report = string.format("%s\nFailed to import:",report) + for name,epgp in pairs(t) do + report = string.format("%s%s {%s:%s}\n",report,name,t[1],t[2]) + end + shooty_export.AddSelectText(report) + end +end + function sepgp_standings:OnEnable() if not T:IsRegistered("sepgp_standings") then T:Register("sepgp_standings", @@ -85,6 +169,13 @@ function sepgp_standings:OnEnable() "tooltipText", "Export standings to csv.", "func", function() sepgp_standings:Export() end ) + if IsGuildLeader() then + D:AddLine( + "text", "Import", + "tooltipText", "Import standings from csv.", + "func", function() sepgp_standings:Import() end + ) + end end ) end @@ -101,27 +192,6 @@ function sepgp_standings:Refresh() T:Refresh("sepgp_standings") end -function sepgp_standings:Export() - local t = {} - for i = 1, GetNumGuildMembers(1) do - local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i) - local ep = (sepgp:get_ep_v3(name,officernote) or 0) --DONE: update v3 - local gp = (sepgp:get_gp_v3(name,officernote) or sepgp.VARS.basegp) --DONE: update v3 - if ep > 0 then - table.insert(t,{name,ep,gp,ep/gp}) - end - end - table.sort(t, function(a,b) - return tonumber(a[4]) > tonumber(b[4]) - end) - shooty_export:Show() - local txt = "Name;EP;GP;PR\n" - for i,val in ipairs(t) do - txt = string.format("%s%s;%d;%d;%.4f\n",txt,val[1],val[2],val[3],val[4]) - end - shooty_export.AddSelectText(txt) -end - function sepgp_standings:setHideScript() local detachedFrame, tablet for i=1,5 do @@ -212,11 +282,22 @@ function sepgp_standings:OnTooltipUpdate() local t = self:BuildStandingsTable() for i = 1, table.getn(t) do local name, class, ep, gp, pr = unpack(t[i]) + local text = C:Colorize(BC:GetHexColor(class), name) + local text2 = string.format("%.4g", ep) + local text3 = string.format("%.4g", gp) + local text4 = string.format("%.4g", pr) + if (sepgp._playerName) and sepgp._playerName == name then + text = string.format("(*)%s",text) + local pr_decay = sepgp:capcalc(ep,gp) + if pr_decay < 0 then + text4 = string.format("%s(|cffff0000%.4g|r)",text4,pr_decay) + end + end cat:AddLine( - "text", C:Colorize(BC:GetHexColor(class), name), - "text2", string.format("%.4g", ep), - "text3", string.format("%.4g", gp), - "text4", string.format("%.4g", pr) + "text", text, + "text2", text2, + "text3", text3, + "text4", text4 ) end end