diff --git a/BuildingPage.lua b/BuildingPage.lua index 06df884..3b6049b 100644 --- a/BuildingPage.lua +++ b/BuildingPage.lua @@ -60,7 +60,6 @@ function module:AddFollowerToPlot(plot) if (addon:GetToggle("HF")) then return frame:Hide() end - ns.xprint(plot.followerTooltip,plot.plotID) if plot.followerTooltip then local followerName, level, quality, displayID, followerID, garrFollowerID, status, portraitIconID = G.GetFollowerInfoForBuilding(plot.plotID) if followerName then diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 943b007..2f4c2f9 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -3,4 +3,5 @@ Fix: Using a full upgrade token on follower was warning about lost points Fix: Possible soloution for a couple of very rare lua errors Feature: Clicking on data broker opens missions report (same as clicking on minimap icon) -Feature: In follower rectuiting page, information about which follower have traits and counter are show in dropdown \ No newline at end of file +Feature: In follower rectuiting page, information about which follower have traits and counter are show in dropdown +Feature: Broker now reports status of producing lot. \ No newline at end of file diff --git a/GarrisonCommander-Broker/GarrisonCommander-Broker.toc b/GarrisonCommander-Broker/GarrisonCommander-Broker.toc index f49f988..6f17d36 100644 --- a/GarrisonCommander-Broker/GarrisonCommander-Broker.toc +++ b/GarrisonCommander-Broker/GarrisonCommander-Broker.toc @@ -4,7 +4,7 @@ ## Notes-itIT: Data-Broker per GarrisonCommander ## Notes-frFR: Data-Broker pour GarrisonCommander ## Author: Alar of Daggerspine -## Version: @project-version@ @project-abbreviated-hash@ +## Version: @project-version@ ## X-Version: 2.3.5 ## X-Revision: @project-abbreviated-hash@ ## eMail: alar@aspide.it diff --git a/GarrisonCommander-Broker/embeds.xml b/GarrisonCommander-Broker/embeds.xml index d99d5dc..635e36d 100644 --- a/GarrisonCommander-Broker/embeds.xml +++ b/GarrisonCommander-Broker/embeds.xml @@ -7,4 +7,5 @@ <Include file="..\GarrisonCommander\libs\Ace3\AceTimer-3.0\AceTimer-3.0.xml"/> <Include file="..\GarrisonCommander\libs\Ace3\AceLocale-3.0\AceLocale-3.0.xml"/> <Include file="..\GarrisonCommander\libs\Ace3\AceDB-3.0\AceDB-3.0.xml"/> + <Include file="..\GarrisonCommander\libs\LibInit\LibInit.xml"/> </Ui> diff --git a/GarrisonCommander-Broker/ldb.lua b/GarrisonCommander-Broker/ldb.lua index cae7bfd..7a48f62 100644 --- a/GarrisonCommander-Broker/ldb.lua +++ b/GarrisonCommander-Broker/ldb.lua @@ -7,8 +7,11 @@ if (not LibStub:GetLibrary("LibDataBroker-1.1",true)) then end if (LibDebug) then LibDebug() end local L=LibStub("AceLocale-3.0"):GetLocale(me,true) -local addon=LibStub("AceAddon-3.0"):NewAddon(me,"AceTimer-3.0","AceEvent-3.0") -local dataobj +--local addon=LibStub("AceAddon-3.0"):NewAddon(me,"AceTimer-3.0","AceEvent-3.0","AceConsole-3.0") --#addon +local addon=LibStub("LibInit"):NewAddon(me,"AceTimer-3.0","AceEvent-3.0","AceConsole-3.0") --#addon +local C=addon:GetColorTable() +local dataobj --#Missions +local farmobj --#Farms local SecondsToTime=SecondsToTime local type=type local strsplit=strsplit @@ -16,12 +19,41 @@ local tonumber=tonumber local tremove=tremove local time=time local tinsert=tinsert +local tContains=tContains local G=C_Garrison -local NONE=NONE -local DONE=DONE local format=format local table=table local math=math +local GetQuestResetTime=GetQuestResetTime +local CalendarGetDate=CalendarGetDate +local CalendarGetAbsMonth=CalendarGetAbsMonth +local GameTooltip=GameTooltip +local pairs=pairs +local select=select +local READY=READY +local NEXT=NEXT +local NONE=C(NONE,"Red") +local DONE=C(DONE,"Green") +local NEED=C(NEED,"Red") +local dbversion=2 + +local spellids={ + [158754]='herb', + [158745]='mine', + [170599]='mine', + [170691]='herb', +} +local buildids={ + mine={61,62,63}, + herb={29,136,137} +} +local names={ + mine="Lunar Fall", + herb="Herb Garden" +} +local today=0 +local yesterday=0 +local lastreset=0 function addon:ldbCleanup() local now=time() for i=1,#self.db.realm.missions do @@ -37,26 +69,9 @@ function addon:ldbCleanup() end end function addon:ldbUpdate() - local now=time() - local completed=0 - local ready=NONE - local prox=NONE - for i=1,#self.db.realm.missions do - local t,missionID,pc=strsplit('.',self.db.realm.missions[i]) - t=tonumber(t) or 0 - if t>now then - local duration=t-now - local duration=duration < 60 and duration or math.floor(duration/60)*60 - prox=format("|cff20ff20%s|r in %s",pc,SecondsToTime(duration),completed) - break; - else - if ready==NONE then - ready=format("|cff20ff20%s|r",pc) - end - end - completed=completed+1 - end - dataobj.text=format("%s: %s (Tot: |cff00ff00%d|r) %s: %s",READY,ready,completed,NEXT,prox) + self:CheckDailyReset() + dataobj:Update() + farmobj:Update() end function addon:GARRISON_MISSION_STARTED(event,missionID) local duration=select(2,G.GetPartyMissionInfo(missionID)) or 0 @@ -65,20 +80,168 @@ function addon:GARRISON_MISSION_STARTED(event,missionID) table.sort(self.db.realm.missions) self:ldbUpdate() end -function addon:OnInitialize() +function addon:CheckEvents() + if (G.IsOnGarrisonMap()) then + self:RegisterEvent("UNIT_SPELLCAST_START") + --self:RegisterEvent("ITEM_PUSH") + else + self:UnregisterEvent("UNIT_SPELLCAST_START") + --self:UnregisterEvent("ITEM_PUSH") + end +end +function addon:ZONE_CHANGED_NEW_AREA() + self:ScheduleTimer("CheckEvents",1) + self:ScheduleTimer("DiscoverFarms",1) + +end +function addon:UNIT_SPELLCAST_START(event,unit,name,rank,lineID,spellID) + if (unit=='player') then + if spellids[spellID] then + name=names[spellids[spellID]] + if not self.db.realm.farms[ns.me][name] then + self.db.realm.farms[ns.me][name]=true + farmobj:Update() + end + end + end +end +function addon:ITEM_PUSH(event,bag,icon) + --@debug@ + print(event,bag,icon) + --@end-debug@ +end +function addon:CalculateModifiedDate() + local weekday, month, day, year = CalendarGetDate() + today=format("%04d%02d%02d",year,month,day) + if month==1 and day==1 then + local m, y, numdays, firstday = CalendarGetAbsMonth( 12, year-1 ) + yesterday=format("%04d%02d%02d",y,m,numdays) + elseif day==1 then + local m, y, numdays, firstday = CalendarGetAbsMonth( month-1, year) + yesterday=format("%04d%02d%02d",y,m,numdays) + else + yesterday=format("%04d%02d%02d",year,month,day-1) + end + if (GetQuestResetTime()<3600*3) then + today=yesterday + end +end +function addon:CheckDailyReset() + if lastreset < GetQuestResetTime() then + lastreset =GetQuestResetTime() + self:CleanFarms() + end + +end +function addon:CleanFarms() + for p,j in pairs(self.db.realm.farms) do + for s,_ in pairs(j) do + j[s]=false + end + end +end +function addon:CountMissing() + local tot=0 + local missing=0 + for p,j in pairs(self.db.realm.farms) do + for s,_ in pairs(j) do + tot=tot+1 + if not j[s] then missing=missing+1 end + end + end + return missing,tot +end +function addon:DiscoverFarms() + local shipmentIndex = 1; + local buildings = C_Garrison.GetBuildings(); + for i = 1, #buildings do + local buildingID = buildings[i].buildingID; + if ( buildingID) then + local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID = C_Garrison.GetLandingPageShipmentInfo(buildingID); + if (tContains(buildids.mine,buildingID)) then + names.mine=name + if not self.db.realm.farms[ns.me][name] then + self.db.realm.farms[ns.me][name]=false + end + end + if (tContains(buildids.herb,buildingID)) then + names.herb=name + if not self.db.realm.farms[ns.me][name] then + self.db.realm.farms[ns.me][name]=false + end + end + + end + end +end +function addon:SetDbDefaults(default) + default.realm={ + missions={}, + farms={["**"]={}}, + lastday="0", + dbversion=1 + } +end +function addon:OnInitialized() + lastreset=GetQuestResetTime() ns.me=GetUnitName("player",false) self:RegisterEvent("GARRISON_MISSION_STARTED") self:RegisterEvent("GARRISON_MISSION_NPC_OPENED","ldbCleanup") + self:RegisterEvent("ZONE_CHANGED_NEW_AREA") + if dbversion>self.db.realm.dbversion then + self.db:ResetDB() + self.db.realm.dbversion=dbversion + end + self:CalculateModifiedDate() + if self.db.realm.lastday<today then addon:CleanFarms() end + self.db.realm.lastday=today self:ScheduleRepeatingTimer("ldbUpdate",1) - self.db=LibStub("AceDB-3.0"):New("dbGACB",{realm={missions={}}}) + self:ScheduleTimer("ZONE_CHANGED_NEW_AREA",1) end -dataobj=LibStub:GetLibrary("LibDataBroker-1.1"):NewDataObject(me, { +dataobj=LibStub:GetLibrary("LibDataBroker-1.1"):NewDataObject("GC-Missions", { type = "data source", - label = "Missions ", + label = "GC Missions ", text=NONE, category = "Interface", icon = "Interface\\ICONS\\ACHIEVEMENT_GUILDPERK_WORKINGOVERTIME" }) +farmobj=LibStub:GetLibrary("LibDataBroker-1.1"):NewDataObject("GC-Farms", { + type = "data source", + label = "GC Farms ", + text=L["Harvesting status"], + category = "Interface", + icon = "Interface\\Icons\\Trade_Engineering" +}) +function farmobj:Update() + local n,t=addon:CountMissing() + if (t>0) then + local c1=C.Green.c + local c2=C.Green.c + if n>t/2 then + c1=C.Red.c + elseif n>0 then + c1=C.Orange.c + end + farmobj.text=format("%s |cff%s%d|r/|cff%s%d|r",L["Harvest"],c1,t-n,c2,t) + else + farmobj.text=NONE + end +end +function farmobj:OnTooltipShow() + self:AddDoubleLine(L["Time to next reset"],SecondsToTime(GetQuestResetTime())) + for k,v in pairs(addon.db.realm.farms) do + if (k==ns.me) then + self:AddLine(k,C.Green()) + else + self:AddLine(k,C.Orange()) + end + for s,d in pairs(v) do + self:AddDoubleLine(s,d and DONE or NEED) + end + end + self:AddLine(me,C.Silver()) +end + function dataobj:OnTooltipShow() self:AddLine(L["Mission awaiting"]) local db=addon.db.realm.missions @@ -87,17 +250,18 @@ function dataobj:OnTooltipShow() if db[i] then local t,missionID,pc=strsplit('.',db[i]) t=tonumber(t) or 0 - local name=C_Garrison.GetMissionName(missionID) + local name=G.GetMissionName(missionID) if (name) then + local msg=format("|cff%s%s|r: %s",pc==ns.me and C.Green.c or C.Orange.c,pc,name) if t > now then - self:AddDoubleLine(format("|cffff9900%s|r: %s",pc,name),SecondsToTime(t-now),nil,nil,nil,0,1,0) + self:AddDoubleLine(msg,SecondsToTime(t-now),nil,nil,nil,C.Red()) else - self:AddDoubleLine(format("|cffff9900%s|r: %s",pc,name),DONE,nil,nil,nil,1,0,0) + self:AddDoubleLine(msg,DONE) end end end end - self:AddLine(me,0,1,0) + self:AddLine(me,C.Silver()) end function dataobj:OnEnter() @@ -112,12 +276,46 @@ end function dataobj:OnLeave() GameTooltip:Hide() end +function farmobj:OnEnter() + GameTooltip:SetOwner(self, "ANCHOR_NONE") + GameTooltip:SetPoint("TOPLEFT", self, "BOTTOMLEFT") + GameTooltip:ClearLines() + farmobj.OnTooltipShow(GameTooltip) + GameTooltip:Show() +end +farmobj.OnLeave=dataobj.OnLeave + function dataobj:OnClick(button) if (button=="LeftButton") then GarrisonLandingPage_Toggle() end end +function dataobj:Update() + local now=time() + local completed=0 + local ready=NONE + local prox=NONE + for i=1,#addon.db.realm.missions do + local t,missionID,pc=strsplit('.',addon.db.realm.missions[i]) + t=tonumber(t) or 0 + if t>now then + local duration=t-now + local duration=duration < 60 and duration or math.floor(duration/60)*60 + prox=format("|cff20ff20%s|r in %s",pc,SecondsToTime(duration),completed) + break; + else + if ready==NONE then + ready=format("|cff20ff20%s|r",pc) + end + end + completed=completed+1 + end + self.text=format("%s: %s (Tot: |cff00ff00%d|r) %s: %s",READY,ready,completed,NEXT,prox) +end --@debug@ -_G.GACDB=addon +function addon:Dump() + DevTools_Dump(self.db.realm) +end +_G.GACB=addon --@end-debug@ diff --git a/GarrisonCommander.lua b/GarrisonCommander.lua index c0cffd0..b3be823 100644 --- a/GarrisonCommander.lua +++ b/GarrisonCommander.lua @@ -9,11 +9,6 @@ local xprint=ns.xprint local _G=_G local pp=print local HD=false -local print=ns.print -local pairs=pairs -local select=select -local next=next -local tinsert=tinsert local tremove=tremove local setmetatable=setmetatable local getmetatable=getmetatable @@ -34,7 +29,7 @@ local pin=false local baseHeight local minHeight --@debug@ -if LibDebug() then LibDebug() end +if LibDebug then LibDebug() end --@end-debug@ ns.bigscreen=true -- Blizzard functions override support @@ -233,20 +228,7 @@ end local counters=setmetatable({},t2) local counterThreatIndex=setmetatable({},t2) local counterFollowerIndex=setmetatable({},t2) ---- Quick backdrop --- -local backdrop = { - bgFile="Interface\\TutorialFrame\\TutorialFrameBackground", - edgeFile="Interface\\Tooltips\\UI-Tooltip-Border", - tile=true, - tileSize=16, - edgeSize=16, - insets={bottom=7,left=7,right=7,top=7} -} -local function addBackdrop(f,color) - f:SetBackdrop(backdrop) - f:SetBackdropBorderColor(C[color or 'Yellow']()) -end + --generic table scan @@ -1056,278 +1038,6 @@ function addon:Toggle(button) button:SetChecked(f:IsShown()) end end --- Unused, experimenting with acegui -function addon:GenerateMissionsWidgets() - self:GenerateMissionContainer() - self:GenerateMissionButton() -end -do -local generated -function addon:GenerateContainer() - if generated then return end - generated=true - do - local Type="GCGUIContainer" - local Version=1 - local m={} - function m:Close() - self.frame.CloseButton:Click() - end - function m:OnAcquire() - self.frame:EnableMouse(true) - self:SetTitleColor(C.Yellow()) - self.frame:SetFrameStrata("HIGH") - self.frame:SetFrameLevel(999) - end - function m:SetContentWidth(x) - self.content:SetWidth(x) - end - local function Constructor() - local frame=CreateFrame("Frame",nil,nil,"GarrisonUITemplate") - for _,f in pairs({frame:GetRegions()}) do - if (f:GetObjectType()=="Texture" and f:GetAtlas()=="Garr_WoodFrameCorner") then f:Hide() end - end - local widget={frame=frame,missions={}} - widget.type=Type - widget.SetTitle=function(self,...) self.frame.TitleText:SetText(...) end - widget.SetTitleColor=function(self,...) self.frame.TitleText:SetTextColor(...) end - for k,v in pairs(m) do widget[k]=v end - frame:SetScript("OnHide",function(self) self.obj:Fire('OnClose') end) - frame.obj=widget - --Container Support - local content = CreateFrame("Frame",nil,frame) - widget.content = content - --addBackdrop(content,'Green') - content.obj = widget - content:SetPoint("TOPLEFT",25,-25) - content:SetPoint("BOTTOMRIGHT",-25,25) - AceGUI:RegisterAsContainer(widget) - return widget - end - AceGUI:RegisterWidgetType(Type,Constructor,Version) - end -end -end -function addon:GenerateMissionContainer() - do - local Type="GMCLayer" - local Version=1 - local function OnRelease(self) - wipe(self.childs) - end - local m={} - function m:OnAcquire() - self.frame:SetParent(UIParent) - self.frame:SetFrameStrata("HIGH") - self.frame:SetHeight(50) - self.frame:SetWidth(100) - self.frame:Show() - self.frame:SetPoint("LEFT") - end - function m:Show() - return self.frame:Show() - end - function m:Hide() - self.frame:Hide() - self:Release() - end - function m:SetScript(...) - return self.frame:SetScript(...) - end - function m:SetParent(...) - return self.frame:SetParent(...) - end - function m:PushChild(child,index) - self.childs[index]=child - self.scroll:AddChild(child) - end - function m:RemoveChild(index) - local child=self.childs[index] - if (child) then - self.childs[index]=nil - child:Hide() - self:DoLayout() - end - end - function m:ClearChildren() - wipe(self.childs) - self:AddScroll() - end - function m:AddScroll() - if (self.scroll) then - self:ReleaseChildren() - self.scroll=nil - end - self.scroll=AceGUI:Create("ScrollFrame") - local scroll=self.scroll - self:AddChild(scroll) - scroll:SetLayout("List") -- probably? - scroll:SetFullWidth(true) - scroll:SetFullHeight(true) - scroll:SetPoint("TOPLEFT",self.title,"BOTTOMLEFT",0,0) - scroll:SetPoint("TOPRIGHT",self.title,"BOTTOMRIGHT",0,0) - scroll:SetPoint("BOTTOM",self.content,"BOTTOM",0,0) - end - local function Constructor() - local frame=CreateFrame("Frame") - local title=frame:CreateFontString(nil, "BACKGROUND", "GameFontNormalHugeBlack") - title:SetJustifyH("CENTER") - title:SetJustifyV("CENTER") - title:SetPoint("TOPLEFT") - title:SetPoint("TOPRIGHT") - title:SetHeight(0) - title:SetWidth(0) - addBackdrop(frame) - local widget={childs={}} - widget.title=title - widget.type=Type - widget.SetTitle=function(self,...) self.title:SetText(...) end - widget.SetTitleColor=function(self,...) self.title:SetTextColor(...) end - widget.SetFormattedTitle=function(self,...) self.title:SetFormattedText(...) end - widget.SetTitleWidth=function(self,...) self.title:SetWidth(...) end - widget.SetTitleHeight=function(self,...) self.title:SetHeight(...) end - widget.frame=frame - frame.obj=widget - for k,v in pairs(m) do widget[k]=v end - frame:SetScript("OnHide",function(self) self.obj:Fire('OnClose') end) - --Container Support - local content = CreateFrame("Frame",nil,frame) - widget.content = content - content.obj = self - content:SetPoint("TOPLEFT",title,"BOTTOMLEFT") - content:SetPoint("BOTTOMRIGHT") - AceGUI:RegisterAsContainer(widget) - return widget - end - AceGUI:RegisterWidgetType(Type,Constructor,Version) - end -end - -function addon:GenerateMissionButton() - do - local Type1="GMCMissionButton" - local Type2="GMCSlimMissionButton" - local Version=1 - local unique=0 - local m={} - function m:OnAcquire() - local frame=self.frame - frame.info=nil - frame:SetHeight(self.type==Type1 and 80 or 80) - frame:SetAlpha(1) - frame:Enable() - for i=1,#self.scripts do - frame:SetScript(self.scripts[i],nil) - end - for i=1,#frame.Rewards do - frame.Rewards[i].Icon:SetDesaturated(false) - end - wipe(self.scripts) - return self.frame:SetScale(1.0) - end - function m:Show() - return self.frame:Show() - end - function m:SetHeight(h) - return self.frame:SetHeight(h) - end - function m:Hide() - self.frame:SetHeight(1) - self.frame:SetAlpha(0) - return self.frame:Disable() - end - function m:SetScript(name,method) - tinsert(self.scripts,name) - return self.frame:SetScript(name,method) - end - function m:SetScale(s) - return self.frame:SetScale(s) - end - function m:SetMission(mission,party) - self.frame.info=mission - self.frame.fromFollowerPage=true - self.frame:EnableMouse(true) - self.frame.party=party - if self.type==Type1 then - addon:DrawSingleButton(false,self.frame,false,false) - self.frame:SetScript("OnEnter",GarrisonMissionButton_OnEnter) - self.frame:SetScript("OnLeave",ns.OnLeave) - else - addon:DrawSingleSlimButton(false,self.frame,false,false) - self.frame:SetScript("OnEnter",nil) - self.frame:SetScript("OnLeave",nil) - end - if self.type==Type2 then - self.frame.Percent:SetFormattedText("%d%%",party.perc) - self.frame.Percent:SetTextColor(addon:GetDifficultyColors(party.perc)) - _G.AX=self.frame - end - end - - local function Constructor() - unique=unique+1 - local frame=CreateFrame("Button",nil,nil,"GarrisonMissionListButtonTemplate") --"GarrisonCommanderMissionListButtonTemplate") - frame.Title:SetFontObject("QuestFont_Shadow_Small") - frame.Summary:SetFontObject("QuestFont_Shadow_Small") - frame:SetScript("OnEnter",nil) - frame:SetScript("OnLeave",nil) - frame:SetScript("OnClick",function(self,button) return self.obj:Fire("OnClick",self,button) end) - frame.LocBG:SetPoint("LEFT") - frame.MissionType:SetPoint("TOPLEFT",5,-2) - --[[ - frame.members={} - for i=1,3 do - local f=CreateFrame("Button",nil,frame,"GarrisonCommanderMissionPageFollowerTemplateSmall" ) - frame.members[i]=f - f:SetPoint("BOTTOMRIGHT",-65 -65 *i,5) - f:SetScale(0.8) - end - --]] - local widget={} - setmetatable(widget,{__index=frame}) - widget.frame=frame - widget.scripts={} - frame.obj=widget - for k,v in pairs(m) do widget[k]=v end - return widget - end - local function Constructor1() - local widget=Constructor() - widget.type=Type1 - return AceGUI:RegisterAsWidget(widget) - end - local function Constructor2() - local widget=Constructor() - local frame=widget.frame - widget.type=Type2 - local indicators=CreateFrame("Frame",nil,frame,"GarrisonCommanderIndicators") - indicators.Percent:SetJustifyH("LEFT") - indicators.Percent:SetJustifyV("CENTER") - indicators:SetPoint("LEFT",70,0) - indicators.Age:Hide() - frame.Indicators=indicators - frame.Percent=indicators.Percent - frame.Failure=frame:CreateFontString() - frame.Success=frame:CreateFontString() - frame.Failure:SetFontObject("GameFontRedLarge") - frame.Success:SetFontObject("GameFontGreenLarge") - frame.Failure:SetText(FAILED) - frame.Success:SetText(SUCCESS) - frame.Failure:Hide() - frame.Success:Hide() - frame.Title:SetPoint("TOPLEFT",frame.Indicators,"TOPRIGHT",0,0) - frame.Success:SetPoint("BOTTOMLEFT",frame.Indicators,"BOTTOMRIGHT",0,10) - frame.Failure:SetPoint("BOTTOMLEFT",frame.Indicators,"BOTTOMRIGHT",0,10) - - --widget.frame.MissionType:Hide() - --widget.frame.IconBG:Hide() - return AceGUI:RegisterAsWidget(widget) - end - AceGUI:RegisterWidgetType(Type1,Constructor1,Version) - AceGUI:RegisterWidgetType(Type2,Constructor2,Version) - - end -end function addon:CreateOptionsLayer(...) local o=AceGUI:Create("SimpleGroup") -- a transparent frame @@ -1804,7 +1514,6 @@ function addon:SetUp(...) self:CheckMP() self:CheckGMM() self:Options() - self:GenerateMissionsWidgets() GMC=self:GMCBuildPanel(ns.bigscreen) local tabMC=CreateFrame("CheckButton",nil,GMF,"SpellBookSkillLineTabTemplate") GMF.tabMC=tabMC @@ -1844,6 +1553,9 @@ function addon:SetUp(...) --collectgarbage("step",10) --/Interface/FriendsFrame/UI-Toast-FriendOnlineIcon end +function addon:MissionComplete() + return self:GetModule("MissionCompletion"):MissionComplete() +end function addon:AddMenu() local menu,size=self:CreateOptionsLayer(MP and 'CKMP' or nil,'BIGSCREEN','MOVEPANEL','IGM','IGP','NOFILL','MSORT') --self:AddOptionToOptionsLayer(GCF.Menu,'MSORT') @@ -2020,6 +1732,19 @@ function addon:SafeHookScript(frame,hook,method,postHook) end end end +local converter=CreateFrame("Frame"):CreateTexture() +function addon:GetFollowerTexture(followerID) + local rc,iconID=pcall(self.GetFollowerData,self,followerID,"portraitIconID") + if rc then + if iconID then + converter:SetToFileData(iconID) + return converter:GetTexture() + end + return "Interface\\Garrison\\Portraits\\FollowerPortrait_NoPortrait" + else + return "Interface\\Garrison\\Portraits\\FollowerPortrait_NoPortrait" + end +end function addon:CleanUp() wipe(ns.CompletedMissions) @@ -2032,7 +1757,7 @@ function addon:CleanUp() GarrisonFollowerTooltip.fs:Hide() end GMFMissions.CompleteDialog:Hide() - self:CloseReport() + self:GetModule("MissionCompletion"):CloseReport() --collectgarbage("collect") end function addon:EventGARRISON_FOLLOWER_XP_CHANGED(event,followerID,iLevel,xp,level,quality) diff --git a/GarrisonCommander.toc b/GarrisonCommander.toc index 798a2ff..3462cce 100644 --- a/GarrisonCommander.toc +++ b/GarrisonCommander.toc @@ -26,6 +26,8 @@ embeds.xml localization.lua wowhead.lua Init.lua +Widgets.lua +GarrisonCommander.xml MissionCache.lua FollowerCache.lua PartyCache.lua @@ -34,6 +36,5 @@ MissionCompletion.lua FollowerPage.lua MatchMaker.lua FollowerRecruiting.lua -GarrisonCommander.xml BuildingPage.lua RelNotes.lua diff --git a/Init.lua b/Init.lua index 2c3184b..09e7015 100644 --- a/Init.lua +++ b/Init.lua @@ -27,6 +27,7 @@ ns.AceGUI=LibStub("AceGUI-3.0") ns.D=LibStub("LibDeformat-3.0") ns.C=ns.addon:GetColorTable() ns.L=ns.addon:GetLocale() +ns.G=C_Garrison ns.print=ns.addon:Wrap("Print") ns.dprint=ns.print ns.trace=ns.addon:Wrap("Trace") diff --git a/MissionCompletion.lua b/MissionCompletion.lua index b5246a0..cee6bf6 100644 --- a/MissionCompletion.lua +++ b/MissionCompletion.lua @@ -21,400 +21,245 @@ local strsplit=strsplit local generated local salvages={ 114120,114119,114116} -local converter=CreateFrame("Frame"):CreateTexture() -function addon:GetFollowerTexture(followerID) - local rc,iconID=pcall(addon.GetFollowerData,addon,followerID,"portraitIconID") - if rc then - if iconID then - converter:SetToFileData(iconID) - return converter:GetTexture() - end - return "Interface\\Garrison\\Portraits\\FollowerPortrait_NoPortrait" - else - return "Interface\\Garrison\\Portraits\\FollowerPortrait_NoPortrait" - end -end -function addon:GenerateMissionCompleteList(title) - if not generated then - generated=true - self:GenerateContainer() - do - local Type="GCMCList" - local Version=1 - local m={} --#Widget - function m:ScrollDown() - local obj=self.scroll - if (#self.missions >1 and obj.scrollbar and obj.scrollbar:IsShown()) then - obj:SetScroll(80) - obj.scrollbar.ScrollDownButton:Click() - end - end - function m:OnAcquire() - wipe(self.missions) - end - function m:Show() - self.frame:Show() - end - function m:Hide() - self.frame:Hide() - self:Release() - end - function m:AddButton(text,action) - local obj=self.scroll - local b=AceGUI:Create("Button") - b:SetFullWidth(true) - b:SetText(text) - b:SetCallback("OnClick",action) - obj:AddChild(b) - end - function m:AddMissionButton(mission) - local obj=self.scroll - local b=AceGUI:Create("GMCSlimMissionButton") - b:SetMission(mission,addon:GetParty(mission.missionID)) - b:SetScale(0.7) - b:SetFullWidth(true) - self.missions[mission.missionID]=b - obj:AddChild(b) - end - function m:AddMissionResult(missionID,success) - local mission=self.missions[missionID] - if mission then - local frame=mission.frame - if success then - frame.Success:Show() - frame.Failure:Hide() - for i=1,#frame.Rewards do - frame.Rewards[i].Icon:SetDesaturated(false) - end - else - frame.Success:Hide() - frame.Failure:Show() - for i=1,#frame.Rewards do - frame.Rewards[i].Icon:SetDesaturated(true) - frame.Rewards[i].Quantity:Hide() - end - end - end - end - function m:AddRow(data,...) - local obj=self.scroll - local l=AceGUI:Create("InteractiveLabel") - l:SetFontObject(GameFontNormalSmall) - l:SetText(data) - l:SetColor(...) - l:SetFullWidth(true) - obj:AddChild(l) - - end - function m:AddFollower(followerID,xp,levelup) - local follower=addon:GetFollowerData(followerID) - if follower.maxed and not levelup then - return self:AddIconText(addon:GetFollowerTexture(followerID), - format("%s is already at maximum xp",addon:GetFollowerData(followerID,'fullname'))) - end - local quality=G.GetFollowerQuality(followerID) or follower.quality - local level=G.GetFollowerLevel(followerID) or follower.level - if levelup then - PlaySound("UI_Garrison_CommandTable_Follower_LevelUp"); - end - return self:AddIconText(addon:GetFollowerTexture(followerID), - format("%s gained %d xp%s%s",addon:GetFollowerData(followerID,'fullname',true),xp, - levelup and " |cffffed1a*** Level Up ***|r ." or ".", - format(" %d to go.",addon:GetFollowerData(followerID,'levelXP')-addon:GetFollowerData(followerID,'xp')))) - end - function m:AddIconText(icon,text,qt) - local obj=self.scroll - local l=AceGUI:Create("Label") - l:SetFontObject(GameFontNormalSmall) - if (qt) then - l:SetText(format("%s x %s",text,qt)) - else - l:SetText(text) - end - l:SetImage(icon) - l:SetImageSize(24,24) - l:SetFullWidth(true) - obj:AddChild(l) - if (obj.scrollbar and obj.scrollbar:IsShown()) then - obj:SetScroll(80) - obj.scrollbar.ScrollDownButton:Click() - end - return l - end - function m:AddItem(itemID,qt) - local obj=self.scroll - local _,itemlink,itemquality,_,_,_,_,_,_,itemtexture=GetItemInfo(itemID) - if not itemlink then - self:AddIconText(itemtexture,itemID,qt) - else - self:AddIconText(itemtexture,itemlink,qt) - end - end - local function Constructor() - local widget=AceGUI:Create("GCGUIContainer") - widget:SetLayout("Fill") - widget.missions={} - local scroll = AceGUI:Create("ScrollFrame") - scroll:SetLayout("List") -- probably? - scroll:SetFullWidth(true) - scroll:SetFullHeight(true) - widget:AddChild(scroll) - for k,v in pairs(m) do widget[k]=v end - widget:Show() - widget.scroll=scroll - return widget - end - AceGUI:RegisterWidgetType(Type,Constructor,Version) - end - end +local module=addon:NewSubClass('MissionCompletion') --#Module +function module:GenerateMissionCompleteList(title) local w=AceGUI:Create("GCMCList") w:SetTitle(title) w:SetCallback("OnClose", function(self) self:Release() ns.missionautocompleting=nil end) return w end - ---TODO: Portare la stampa dei risultati in fondo, e togliere il delay fra le missioni -do - local missions={} - local states={} - local currentMission - local rewards={ - items={}, - followerBase={}, - followerXP=setmetatable({},{__index=function() return 0 end}), - currencies=setmetatable({},{__index=function(t,k) rawset(t,k,{icon="",qt=0}) return t[k] end}), - } - local scroller - local report - local timer - local function startTimer(delay,event) - delay=delay or 0.2 - event=event or "LOOP" - addon:ScheduleTimer("MissionAutoComplete",delay,event) - --@alpha@ - addon:Dprint("Timer rearmed for",event,delay) - --@end-alpha@ - end - local function stopTimer() +local missions={} +local states={} +local currentMission +local rewards={ + items={}, + followerBase={}, + followerXP=setmetatable({},{__index=function() return 0 end}), + currencies=setmetatable({},{__index=function(t,k) rawset(t,k,{icon="",qt=0}) return t[k] end}), +} +local scroller +local report +local timer +local function stopTimer() + if (timer) then + module:CancelTimer(timer) timer=nil end - function addon:MissionsCleanup() - stopTimer() - self:MissionEvents(false) - GMF.MissionTab.MissionList.CompleteDialog:Hide() - GMF.MissionComplete:Hide() - GMF.MissionCompleteBackground:Hide() - GMF.MissionComplete.currentIndex = nil - GMF.MissionTab:Show() - GarrisonMissionList_UpdateMissions() - -- Re-enable "view" button - GMFMissions.CompleteDialog.BorderFrame.ViewButton:SetEnabled(true) - ns.missionautocompleting=nil - GarrisonMissionFrame_SelectTab(1) - GarrisonMissionFrame_CheckCompleteMissions() - end - function addon:MissionEvents(start) - self:UnregisterEvent("GARRISON_MISSION_BONUS_ROLL_COMPLETE") - self:UnregisterEvent("GARRISON_MISSION_BONUS_ROLL_LOOT") - self:UnregisterEvent("GARRISON_MISSION_COMPLETE_RESPONSE") - self:UnregisterEvent("GARRISON_FOLLOWER_XP_CHANGED") - if start then - self:RegisterEvent("GARRISON_MISSION_BONUS_ROLL_LOOT","MissionAutoComplete") - self:RegisterEvent("GARRISON_MISSION_BONUS_ROLL_COMPLETE","MissionAutoComplete") - self:RegisterEvent("GARRISON_MISSION_COMPLETE_RESPONSE","MissionAutoComplete") - self:RegisterEvent("GARRISON_FOLLOWER_XP_CHANGED","MissionAutoComplete") - else - self:SafeRegisterEvent("GARRISON_MISSION_BONUS_ROLL_LOOT") - self:SafeRegisterEvent("GARRISON_MISSION_BONUS_ROLL_COMPLETE") - self:SafeRegisterEvent("GARRISON_MISSION_COMPLETE_RESPONSE") - self:SafeRegisterEvent("GARRISON_FOLLOWER_XP_CHANGED") - end - end - function addon:CloseReport() - if report then pcall(report.Close,report) end - end - function addon:MissionComplete(this,button) - GMFMissions.CompleteDialog.BorderFrame.ViewButton:SetEnabled(false) -- Disabling standard Blizzard Completion - missions=G.GetCompleteMissions() - if (missions and #missions > 0) then - ns.missionautocompleting=true - report=self:GenerateMissionCompleteList("Missions' results") - --report:SetPoint("TOPLEFT",GMFMissions.CompleteDialog.BorderFrame) - --report:SetPoint("BOTTOMRIGHT",GMFMissions.CompleteDialog.BorderFrame) - report:SetParent(GMF) - report:SetPoint("TOP",GMF) - report:SetPoint("BOTTOM",GMF) - report:SetWidth(500) - report:SetCallback("OnClose",function() return addon:MissionsCleanup() end) - wipe(rewards.followerBase) - wipe(rewards.followerXP) - wipe(rewards.currencies) - wipe(rewards.items) - for i=1,#missions do - for k,v in pairs(missions[i].followers) do - rewards.followerBase[v]=self:GetFollowerData(v,'qLevel') - end - local m=missions[i] - local _ - _,_,_,m.successChance,_,_,m.xpBonus,m.resourceMultiplier,m.goldMultiplier=G.GetPartyMissionInfo(m.missionID) +end +local function startTimer(delay,event,...) + delay=delay or 0.2 + event=event or "LOOP" + stopTimer() + timer=module:ScheduleRepeatingTimer("MissionAutoComplete",delay,event,...) + --@alpha@ + addon:Dprint("Timer rearmed for",event,delay) + --@end-alpha@ +end +function module:MissionsCleanup() + stopTimer() + GMF.MissionTab.MissionList.CompleteDialog:Hide() + GMF.MissionComplete:Hide() + GMF.MissionCompleteBackground:Hide() + GMF.MissionComplete.currentIndex = nil + GMF.MissionTab:Show() + GarrisonMissionList_UpdateMissions() + -- Re-enable "view" button + GMFMissions.CompleteDialog.BorderFrame.ViewButton:SetEnabled(true) + ns.missionautocompleting=nil + GarrisonMissionFrame_SelectTab(1) + GarrisonMissionFrame_CheckCompleteMissions() +end +function module:OnInitialized(start) + self:RegisterEvent("GARRISON_MISSION_BONUS_ROLL_LOOT","MissionAutoComplete") + self:RegisterEvent("GARRISON_MISSION_BONUS_ROLL_COMPLETE","MissionAutoComplete") + self:RegisterEvent("GARRISON_MISSION_COMPLETE_RESPONSE","MissionAutoComplete") + self:RegisterEvent("GARRISON_FOLLOWER_XP_CHANGED","MissionAutoComplete") +end +function module:CloseReport() + if report then pcall(report.Close,report) end +end +function module:MissionComplete(this,button) + GMFMissions.CompleteDialog.BorderFrame.ViewButton:SetEnabled(false) -- Disabling standard Blizzard Completion + missions=G.GetCompleteMissions() + if (missions and #missions > 0) then + ns.missionautocompleting=true + report=self:GenerateMissionCompleteList("Missions' results") + --report:SetPoint("TOPLEFT",GMFMissions.CompleteDialog.BorderFrame) + --report:SetPoint("BOTTOMRIGHT",GMFMissions.CompleteDialog.BorderFrame) + report:SetParent(GMF) + report:SetPoint("TOP",GMF) + report:SetPoint("BOTTOM",GMF) + report:SetWidth(500) + report:SetCallback("OnClose",function() return module:MissionsCleanup() end) + wipe(rewards.followerBase) + wipe(rewards.followerXP) + wipe(rewards.currencies) + wipe(rewards.items) + for i=1,#missions do + for k,v in pairs(missions[i].followers) do + rewards.followerBase[v]=self:GetFollowerData(v,'qLevel') end - currentMission=tremove(missions) - ns.CompletedMissions[currentMission.missionID]=currentMission - self:MissionAutoComplete("LOOP") - self:MissionEvents(true) + local m=missions[i] + local _ + _,_,_,m.successChance,_,_,m.xpBonus,m.resourceMultiplier,m.goldMultiplier=G.GetPartyMissionInfo(m.missionID) end + currentMission=tremove(missions) + ns.CompletedMissions[currentMission.missionID]=currentMission + self:MissionAutoComplete("INIT") end - function addon:MissionAutoComplete(event,ID,arg1,arg2,arg3,arg4) +end +function module:MissionAutoComplete(event,ID,arg1,arg2,arg3,arg4) -- C_Garrison.MarkMissionComplete Mark mission as complete and prepare it for bonus roll, da chiamare solo in caso di successo -- C_Garrison.MissionBonusRoll - --@alpha@ - self:Dprint("evt",event,ID,arg1,arg2,arg3) - --@end-alpha@ - if event=="LOOT" then - return addon:MissionsPrintResults() - end +--@alpha@ + self:Dprint("evt",event,ID,arg1 or'',arg2 or '',arg3 or '') +--@end-alpha@ + if event=="LOOT" then + return self:MissionsPrintResults() + end - if (event =="LOOP" ) then - ID=currentMission and currentMission.missionID or "none" - arg1=currentMission and currentMission.state or "none" + if (event =="LOOP" or event=="INIT") then + ID=currentMission and currentMission.missionID or "none" + arg1=currentMission and currentMission.state or "none" + end + -- GARRISON_FOLLOWER_XP_CHANGED: followerID, xpGained, actualXp, newLevel, quality + if (event=="GARRISON_FOLLOWER_XP_CHANGED") then + if (arg1 > 0) then + --report:AddFollower(ID,arg1,arg2) + rewards.followerXP[ID]=rewards.followerXP[ID]+tonumber(arg1) or 0 end - -- GARRISON_FOLLOWER_XP_CHANGED: followerID, xpGained, actualXp, newLevel, quality - if (event=="GARRISON_FOLLOWER_XP_CHANGED") then - if (arg1 > 0) then - --report:AddFollower(ID,arg1,arg2) - rewards.followerXP[ID]=rewards.followerXP[ID]+tonumber(arg1) or 0 - end - return - -- GARRISON_MISSION_BONUS_ROLL_LOOT: itemID - elseif (event=="GARRISON_MISSION_BONUS_ROLL_LOOT") then - if (currentMission) then - rewards.items[format("%d:%s",currentMission.missionID,ID)]=1 - else - rewards.items[format("%d:%s",0,ID)]=1 - end - return - -- GARRISON_MISSION_COMPLETE_RESPONSE: missionID, requestCompleted, succeeded - elseif (event=="GARRISON_MISSION_COMPLETE_RESPONSE") then - if (not arg1) then - -- We need to call server again + return + -- GARRISON_MISSION_BONUS_ROLL_LOOT: itemID + elseif (event=="GARRISON_MISSION_BONUS_ROLL_LOOT") then + if (currentMission) then + rewards.items[format("%d:%s",currentMission.missionID,ID)]=1 + else + rewards.items[format("%d:%s",0,ID)]=1 + end + return + -- GARRISON_MISSION_COMPLETE_RESPONSE: missionID, requestCompleted, succeeded + elseif (event=="GARRISON_MISSION_COMPLETE_RESPONSE") then + if (not arg1) then + -- We need to call server again + currentMission.state=0 + elseif (arg2) then -- success, we need to roll + currentMission.state=1 + else -- failure, just print results + currentMission.state=2 + end + startTimer(0.1) + return + -- GARRISON_MISSION_BONUS_ROLL_COMPLETE: missionID, requestCompleted; happens after C_Garrison.MissionBonusRoll + elseif (event=="GARRISON_MISSION_BONUS_ROLL_COMPLETE") then + if (not arg1) then + -- We need to call server again + currentMission.state=1 + else + currentMission.state=3 + end + startTimer(0.1) + return + else -- event == LOOP + if (currentMission) then + local step=currentMission.state or -1 + if (step<1) then + step=0 currentMission.state=0 - elseif (arg2) then -- success, we need to roll - currentMission.state=1 - else -- failure, just print results - currentMission.state=2 - end - startTimer(0.1) - return - -- GARRISON_MISSION_BONUS_ROLL_COMPLETE: missionID, requestCompleted; happens after C_Garrison.MissionBonusRoll - elseif (event=="GARRISON_MISSION_BONUS_ROLL_COMPLETE") then - if (not arg1) then - -- We need to call server again - currentMission.state=1 - else - currentMission.state=3 + currentMission.goldMultiplier=currentMission.goldMultiplier or 1 + currentMission.xp=select(2,G.GetMissionInfo(currentMission.missionID)) + report:AddMissionButton(currentMission) end - startTimer(0.1) - return - else -- event == LOOP - if (currentMission) then - local step=currentMission.state or -1 - if (step<1) then - step=0 - currentMission.state=0 - currentMission.goldMultiplier=currentMission.goldMultiplier or 1 - currentMission.xp=select(2,G.GetMissionInfo(currentMission.missionID)) - report:AddMissionButton(currentMission) + if (step==0) then + --@alpha@ + self:Dprint("Fired mission complete for",currentMission.missionID) + --@end-alpha@ + G.MarkMissionComplete(currentMission.missionID) + startTimer(2) + elseif (step==1) then + --@alpha@ + self:Dprint("Fired bonus roll complete for",currentMission.missionID) + --@end-alpha@ + G.MissionBonusRoll(currentMission.missionID) + startTimer(2) + elseif (step>=2) then + self:GetMissionResults(step==3) + self:RefreshFollowerStatus() + currentMission=tremove(missions) + if currentMission then + ns.CompletedMissions[currentMission.missionID]=currentMission end - if (step==0) then - --@alpha@ - self:Dprint("Fired mission complete for",currentMission.missionID) - --@end-alpha@ - G.MarkMissionComplete(currentMission.missionID) - elseif (step==1) then - --@alpha@ - self:Dprint("Fired bonus roll complete for",currentMission.missionID) - --@end-alpha@ - G.MissionBonusRoll(currentMission.missionID) - elseif (step>=2) then - self:GetMissionResults(step==3) - self:RefreshFollowerStatus() - currentMission=tremove(missions) - if currentMission then - ns.CompletedMissions[currentMission.missionID]=currentMission - end - startTimer() - return - end - currentMission.state=step - else - report:AddButton(L["Building Final report"],function() addon:MissionsPrintResult() end) - startTimer(1,"LOOT") + startTimer() + return end - end - end - function addon:GetMissionResults(success) - stopTimer() - if (success) then - report:AddMissionResult(currentMission.missionID,true) - PlaySound("UI_Garrison_Mission_Complete_Mission_Success") + currentMission.state=step else - report:AddMissionResult(currentMission.missionID,false) - PlaySound("UI_Garrison_Mission_Complete_Encounter_Fail") + report:AddButton(L["Building Final report"],function() addon:MissionsPrintResult() end) + startTimer(1,"LOOT") end - if success then - local resourceMultiplier=currentMission.resourceMultiplier or 1 - local goldMultiplier=currentMission.goldMultiplier or 1 - for k,v in pairs(currentMission.rewards) do - v.quantity=v.quantity or 0 - if v.currencyID then - rewards.currencies[v.currencyID].icon=v.icon - if v.currencyID == 0 then - rewards.currencies[v.currencyID].qt=rewards.currencies[v.currencyID].qt+v.quantity * goldMultiplier - elseif v.currencyID == GARRISON_CURRENCY then - rewards.currencies[v.currencyID].qt=rewards.currencies[v.currencyID].qt+v.quantity * resourceMultiplier - else - rewards.currencies[v.currencyID].qt=rewards.currencies[v.currencyID].qt+v.quantity - end - elseif v.itemID then - GetItemInfo(v.itemID) -- Triggering the cache - rewards.items[format("%d:%s",currentMission.missionID,v.itemID)]=1 + end +end +function module:GetMissionResults(success) + stopTimer() + if (success) then + report:AddMissionResult(currentMission.missionID,true) + PlaySound("UI_Garrison_Mission_Complete_Mission_Success") + else + report:AddMissionResult(currentMission.missionID,false) + PlaySound("UI_Garrison_Mission_Complete_Encounter_Fail") + end + if success then + local resourceMultiplier=currentMission.resourceMultiplier or 1 + local goldMultiplier=currentMission.goldMultiplier or 1 + for k,v in pairs(currentMission.rewards) do + v.quantity=v.quantity or 0 + if v.currencyID then + rewards.currencies[v.currencyID].icon=v.icon + if v.currencyID == 0 then + rewards.currencies[v.currencyID].qt=rewards.currencies[v.currencyID].qt+v.quantity * goldMultiplier + elseif v.currencyID == GARRISON_CURRENCY then + rewards.currencies[v.currencyID].qt=rewards.currencies[v.currencyID].qt+v.quantity * resourceMultiplier + else + rewards.currencies[v.currencyID].qt=rewards.currencies[v.currencyID].qt+v.quantity end + elseif v.itemID then + GetItemInfo(v.itemID) -- Triggering the cache + rewards.items[format("%d:%s",currentMission.missionID,v.itemID)]=1 end end end - function addon:MissionsPrintResults(success) - stopTimer() - self:FollowerCacheInit() +end +function module:MissionsPrintResults(success) + stopTimer() + self:FollowerCacheInit() --@debug@ - --self:Dump("Ended Mission",rewards) + --self:Dump("Ended Mission",rewards) --@end-debug@ - for k,v in pairs(rewards.currencies) do - if k == 0 then - -- Money reward - report:AddIconText(v.icon,GetMoneyString(v.qt)) - elseif k == GARRISON_CURRENCY then - -- Garrison currency reward - report:AddIconText(v.icon,GetCurrencyLink(k),v.qt) - else - -- Other currency reward - report:AddIconText(v.icon,GetCurrencyLink(k),v.qt) - end - end - local items=new() - for k,v in pairs(rewards.items) do - local missionid,itemid=strsplit(":",k) - if (not items[itemid]) then - items[itemid]=1 - else - items[itemid]=items[itemid]+1 - end - end - for itemid,qt in pairs(items) do - report:AddItem(itemid,qt) + for k,v in pairs(rewards.currencies) do + if k == 0 then + -- Money reward + report:AddIconText(v.icon,GetMoneyString(v.qt)) + elseif k == GARRISON_CURRENCY then + -- Garrison currency reward + report:AddIconText(v.icon,GetCurrencyLink(k),v.qt) + else + -- Other currency reward + report:AddIconText(v.icon,GetCurrencyLink(k),v.qt) end - del(items) - for k,v in pairs(rewards.followerXP) do - report:AddFollower(k,v,self:GetFollowerData(k,'qLevel') > rewards.followerBase[k]) + end + local items=new() + for k,v in pairs(rewards.items) do + local missionid,itemid=strsplit(":",k) + if (not items[itemid]) then + items[itemid]=1 + else + items[itemid]=items[itemid]+1 end end + for itemid,qt in pairs(items) do + report:AddItem(itemid,qt) + end + del(items) + for k,v in pairs(rewards.followerXP) do + report:AddFollower(k,v,self:GetFollowerData(k,'qLevel') > rewards.followerBase[k]) + end end diff --git a/Widgets.lua b/Widgets.lua new file mode 100644 index 0000000..e0b1135 --- /dev/null +++ b/Widgets.lua @@ -0,0 +1,428 @@ +local me, ns = ... +local _G=_G +local pp=print +local addon=ns.addon +local AceGUI=LibStub("AceGUI-3.0") +local C=ns.C +local G=ns.G +local L=ns.L +local module=addon:NewSubModule("Widgets") --#module +--- Quick backdrop +-- +local backdrop = { + bgFile="Interface\\TutorialFrame\\TutorialFrameBackground", + edgeFile="Interface\\Tooltips\\UI-Tooltip-Border", + tile=true, + tileSize=16, + edgeSize=16, + insets={bottom=7,left=7,right=7,top=7} +} +local function addBackdrop(f,color) + f:SetBackdrop(backdrop) + f:SetBackdropBorderColor(C[color or 'Yellow']()) +end +local function GMCList() + local Type="GCMCList" + local Version=1 + local m={} --#GCMList + function m:ScrollDown() + local obj=self.scroll + if (#self.missions >1 and obj.scrollbar and obj.scrollbar:IsShown()) then + obj:SetScroll(80) + obj.scrollbar.ScrollDownButton:Click() + end + end + function m:OnAcquire() + wipe(self.missions) + end + function m:Show() + self.frame:Show() + end + function m:Hide() + self.frame:Hide() + self:Release() + end + function m:AddButton(text,action) + local obj=self.scroll + local b=AceGUI:Create("Button") + b:SetFullWidth(true) + b:SetText(text) + b:SetCallback("OnClick",action) + obj:AddChild(b) + end + function m:AddMissionButton(mission) + local obj=self.scroll + local b=AceGUI:Create("GMCSlimMissionButton") + b:SetMission(mission,addon:GetParty(mission.missionID)) + b:SetScale(0.7) + b:SetFullWidth(true) + self.missions[mission.missionID]=b + obj:AddChild(b) + b.frame.Spinner:Show() + b.frame.Spinner.Anim:Play() + + end + function m:AddMissionResult(missionID,success) + local mission=self.missions[missionID] + if mission then + local frame=mission.frame + frame.Spinner.Anim:Stop() + frame.Spinner:Hide() + if success then + frame.Success:Show() + frame.Failure:Hide() + for i=1,#frame.Rewards do + frame.Rewards[i].Icon:SetDesaturated(false) + end + else + frame.Success:Hide() + frame.Failure:Show() + for i=1,#frame.Rewards do + frame.Rewards[i].Icon:SetDesaturated(true) + frame.Rewards[i].Quantity:Hide() + end + end + end + end + function m:AddRow(data,...) + local obj=self.scroll + local l=AceGUI:Create("InteractiveLabel") + l:SetFontObject(GameFontNormalSmall) + l:SetText(data) + l:SetColor(...) + l:SetFullWidth(true) + obj:AddChild(l) + + end + function m:AddFollower(followerID,xp,levelup) + local follower=addon:GetFollowerData(followerID) + if follower.maxed and not levelup then + return self:AddIconText(addon:GetFollowerTexture(followerID), + format("%s is already at maximum xp",addon:GetFollowerData(followerID,'fullname'))) + end + local quality=G.GetFollowerQuality(followerID) or follower.quality + local level=G.GetFollowerLevel(followerID) or follower.level + if levelup then + PlaySound("UI_Garrison_CommandTable_Follower_LevelUp"); + end + return self:AddIconText(addon:GetFollowerTexture(followerID), + format("%s gained %d xp%s%s",addon:GetFollowerData(followerID,'fullname',true),xp, + levelup and " |cffffed1a*** Level Up ***|r ." or ".", + format(" %d to go.",addon:GetFollowerData(followerID,'levelXP')-addon:GetFollowerData(followerID,'xp')))) + end + function m:AddIconText(icon,text,qt) + local obj=self.scroll + local l=AceGUI:Create("Label") + l:SetFontObject(GameFontNormalSmall) + if (qt) then + l:SetText(format("%s x %s",text,qt)) + else + l:SetText(text) + end + l:SetImage(icon) + l:SetImageSize(24,24) + l:SetFullWidth(true) + obj:AddChild(l) + if (obj.scrollbar and obj.scrollbar:IsShown()) then + obj:SetScroll(80) + obj.scrollbar.ScrollDownButton:Click() + end + return l + end + function m:AddItem(itemID,qt) + local obj=self.scroll + local _,itemlink,itemquality,_,_,_,_,_,_,itemtexture=GetItemInfo(itemID) + if not itemlink then + self:AddIconText(itemtexture,itemID,qt) + else + self:AddIconText(itemtexture,itemlink,qt) + end + end + local function Constructor() + local widget=AceGUI:Create("GMCGUIContainer") + widget:SetLayout("Fill") + widget.missions={} + local scroll = AceGUI:Create("ScrollFrame") + scroll:SetLayout("List") -- probably? + scroll:SetFullWidth(true) + scroll:SetFullHeight(true) + widget:AddChild(scroll) + for k,v in pairs(m) do widget[k]=v end + widget:Show() + widget.scroll=scroll + return widget + end + AceGUI:RegisterWidgetType(Type,Constructor,Version) +end +local function GMCGUIContainer() + local Type="GMCGUIContainer" + local Version=1 + local m={} --#GMCGUIContainer + function m:Close() + self.frame.CloseButton:Click() + end + function m:OnAcquire() + self.frame:EnableMouse(true) + self:SetTitleColor(C.Yellow()) + self.frame:SetFrameStrata("HIGH") + self.frame:SetFrameLevel(999) + end + function m:SetContentWidth(x) + self.content:SetWidth(x) + end + ---@function [parent=#GMCGUIContainer] + local function Constructor() + local frame=CreateFrame("Frame",nil,nil,"GarrisonUITemplate") + for _,f in pairs({frame:GetRegions()}) do + if (f:GetObjectType()=="Texture" and f:GetAtlas()=="Garr_WoodFrameCorner") then f:Hide() end + end + local widget={frame=frame,missions={}} + widget.type=Type + widget.SetTitle=function(self,...) self.frame.TitleText:SetText(...) end + widget.SetTitleColor=function(self,...) self.frame.TitleText:SetTextColor(...) end + for k,v in pairs(m) do widget[k]=v end + frame:SetScript("OnHide",function(self) self.obj:Fire('OnClose') end) + frame.obj=widget + --Container Support + local content = CreateFrame("Frame",nil,frame) + widget.content = content + --addBackdrop(content,'Green') + content.obj = widget + content:SetPoint("TOPLEFT",25,-25) + content:SetPoint("BOTTOMRIGHT",-25,25) + AceGUI:RegisterAsContainer(widget) + return widget + end + AceGUI:RegisterWidgetType(Type,Constructor,Version) +end +local function GMCLayer() + local Type="GMCLayer" + local Version=1 + local function OnRelease(self) + wipe(self.childs) + end + local m={} --#GMCLayer + function m:OnAcquire() + self.frame:SetParent(UIParent) + self.frame:SetFrameStrata("HIGH") + self.frame:SetHeight(50) + self.frame:SetWidth(100) + self.frame:Show() + self.frame:SetPoint("LEFT") + end + function m:Show() + return self.frame:Show() + end + function m:Hide() + self.frame:Hide() + self:Release() + end + function m:SetScript(...) + return self.frame:SetScript(...) + end + function m:SetParent(...) + return self.frame:SetParent(...) + end + function m:PushChild(child,index) + self.childs[index]=child + self.scroll:AddChild(child) + end + function m:RemoveChild(index) + local child=self.childs[index] + if (child) then + self.childs[index]=nil + child:Hide() + self:DoLayout() + end + end + function m:ClearChildren() + wipe(self.childs) + self:AddScroll() + end + function m:AddScroll() + if (self.scroll) then + self:ReleaseChildren() + self.scroll=nil + end + self.scroll=AceGUI:Create("ScrollFrame") + local scroll=self.scroll + self:AddChild(scroll) + scroll:SetLayout("List") -- probably? + scroll:SetFullWidth(true) + scroll:SetFullHeight(true) + scroll:SetPoint("TOPLEFT",self.title,"BOTTOMLEFT",0,0) + scroll:SetPoint("TOPRIGHT",self.title,"BOTTOMRIGHT",0,0) + scroll:SetPoint("BOTTOM",self.content,"BOTTOM",0,0) + end + ---@function [parent=#GMCLayer] + local function Constructor() + local frame=CreateFrame("Frame") + local title=frame:CreateFontString(nil, "BACKGROUND", "GameFontNormalHugeBlack") + title:SetJustifyH("CENTER") + title:SetJustifyV("CENTER") + title:SetPoint("TOPLEFT") + title:SetPoint("TOPRIGHT") + title:SetHeight(0) + title:SetWidth(0) + addBackdrop(frame) + local widget={childs={}} + widget.title=title + widget.type=Type + widget.SetTitle=function(self,...) self.title:SetText(...) end + widget.SetTitleColor=function(self,...) self.title:SetTextColor(...) end + widget.SetFormattedTitle=function(self,...) self.title:SetFormattedText(...) end + widget.SetTitleWidth=function(self,...) self.title:SetWidth(...) end + widget.SetTitleHeight=function(self,...) self.title:SetHeight(...) end + widget.frame=frame + frame.obj=widget + for k,v in pairs(m) do widget[k]=v end + frame:SetScript("OnHide",function(self) self.obj:Fire('OnClose') end) + --Container Support + local content = CreateFrame("Frame",nil,frame) + widget.content = content + content.obj = self + content:SetPoint("TOPLEFT",title,"BOTTOMLEFT") + content:SetPoint("BOTTOMRIGHT") + AceGUI:RegisterAsContainer(widget) + return widget + end + AceGUI:RegisterWidgetType(Type,Constructor,Version) +end + +local function GMCMissionButton() + do + local Type1="GMCMissionButton" + local Type2="GMCSlimMissionButton" + local Version=1 + local unique=0 + local m={} --#GMCMissionButton + function m:OnAcquire() + local frame=self.frame + frame.info=nil + frame:SetHeight(self.type==Type1 and 80 or 80) + frame:SetAlpha(1) + frame:Enable() + for i=1,#self.scripts do + frame:SetScript(self.scripts[i],nil) + end + for i=1,#frame.Rewards do + frame.Rewards[i].Icon:SetDesaturated(false) + end + wipe(self.scripts) + return self.frame:SetScale(1.0) + end + function m:Show() + return self.frame:Show() + end + function m:SetHeight(h) + return self.frame:SetHeight(h) + end + function m:Hide() + self.frame:SetHeight(1) + self.frame:SetAlpha(0) + return self.frame:Disable() + end + function m:SetScript(name,method) + tinsert(self.scripts,name) + return self.frame:SetScript(name,method) + end + function m:SetScale(s) + return self.frame:SetScale(s) + end + function m:SetMission(mission,party) + self.frame.info=mission + self.frame.fromFollowerPage=true + self.frame:EnableMouse(true) + self.frame.party=party + if self.type==Type1 then + addon:DrawSingleButton(false,self.frame,false,false) + self.frame:SetScript("OnEnter",GarrisonMissionButton_OnEnter) + self.frame:SetScript("OnLeave",ns.OnLeave) + else + addon:DrawSingleSlimButton(false,self.frame,false,false) + self.frame:SetScript("OnEnter",nil) + self.frame:SetScript("OnLeave",nil) + end + if self.type==Type2 then + self.frame.Percent:SetFormattedText("%d%%",party.perc) + self.frame.Percent:SetTextColor(addon:GetDifficultyColors(party.perc)) + _G.AX=self.frame + end + end + + local function Constructor() + unique=unique+1 + local frame=CreateFrame("Button",nil,nil,"GarrisonMissionListButtonTemplate") --"GarrisonCommanderMissionListButtonTemplate") + frame.Title:SetFontObject("QuestFont_Shadow_Small") + frame.Summary:SetFontObject("QuestFont_Shadow_Small") + frame:SetScript("OnEnter",nil) + frame:SetScript("OnLeave",nil) + frame:SetScript("OnClick",function(self,button) return self.obj:Fire("OnClick",self,button) end) + frame.LocBG:SetPoint("LEFT") + frame.MissionType:SetPoint("TOPLEFT",5,-2) + --[[ + frame.members={} + for i=1,3 do + local f=CreateFrame("Button",nil,frame,"GarrisonCommanderMissionPageFollowerTemplateSmall" ) + frame.members[i]=f + f:SetPoint("BOTTOMRIGHT",-65 -65 *i,5) + f:SetScale(0.8) + end + --]] + local widget={} + setmetatable(widget,{__index=frame}) + widget.frame=frame + widget.scripts={} + frame.obj=widget + for k,v in pairs(m) do widget[k]=v end + return widget + end + ---@function [parent=#GMCMissionButton] + local function Constructor1() + local widget=Constructor() + widget.type=Type1 + return AceGUI:RegisterAsWidget(widget) + end + ---@function [parent=#GMCMissionButton] + local function Constructor2() + local widget=Constructor() + local frame=widget.frame + widget.type=Type2 + local indicators=CreateFrame("Frame",nil,frame,"GarrisonCommanderIndicators") + indicators.Percent:SetJustifyH("LEFT") + indicators.Percent:SetJustifyV("CENTER") + indicators:SetPoint("LEFT",70,0) + indicators.Age:Hide() + local spinner=CreateFrame("Frame",nil,frame,"LoadingSpinnerTemplate") + frame.Spinner=spinner + frame.Indicators=indicators + frame.Percent=indicators.Percent + frame.Failure=frame:CreateFontString() + frame.Success=frame:CreateFontString() + frame.Failure:SetFontObject("GameFontRedLarge") + frame.Success:SetFontObject("GameFontGreenLarge") + frame.Failure:SetText(FAILED) + frame.Success:SetText(SUCCESS) + frame.Failure:Hide() + frame.Success:Hide() + frame.Title:SetPoint("TOPLEFT",frame.Indicators,"TOPRIGHT",0,0) + frame.Success:SetPoint("BOTTOMLEFT",frame.Indicators,"BOTTOMRIGHT",0,10) + frame.Failure:SetPoint("BOTTOMLEFT",frame.Indicators,"BOTTOMRIGHT",0,10) + frame.Spinner:SetPoint("BOTTOMLEFT",frame.Indicators,"BOTTOMRIGHT",0,-2) + + --widget.frame.MissionType:Hide() + --widget.frame.IconBG:Hide() + return AceGUI:RegisterAsWidget(widget) + end + AceGUI:RegisterWidgetType(Type1,Constructor1,Version) + AceGUI:RegisterWidgetType(Type2,Constructor2,Version) + + end +end +function module:OnInitialized() + print("Module widget called") + GMCGUIContainer() + GMCLayer() + GMCMissionButton() + GMCList() +end