diff --git a/.pkgmeta b/.pkgmeta
index fc9a586..620cb93 100755
--- a/.pkgmeta
+++ b/.pkgmeta
@@ -3,13 +3,15 @@ enable-nolib-creation: no
externals:
libs/LibInit:
- url: git://git.curseforge.net/wow/libinit/mainline.git/
+ url: git://git.curseforge.net/wow/libinit/mainline.git/LibInit
+ libs/Ace3:
+ url: svn://svn.wowace.com/wow/ace3/mainline/trunk
+ tag: latest
manual-changelog:
filename: CHANGELOG.txt
markup-type: creole
-
ignore:
- .buildpath
- .project
\ No newline at end of file
diff --git a/GarrisonCommander.lua b/GarrisonCommander.lua
index 4c52ce3..31fae58 100644
--- a/GarrisonCommander.lua
+++ b/GarrisonCommander.lua
@@ -1,13 +1,12 @@
local me, ns = ...
local addon=LibStub("LibInit"):NewAddon(me,'AceHook-3.0','AceTimer-3.0','AceEvent-3.0') --#Addon
+local AceGUI=LibStub("AceGUI-3.0")
+local D=LibStub("LibDeformat-3.0")
local C=addon:GetColorTable()
local L=addon:GetLocale()
-local print=function(...) addon:Print(...) end
-local trace=function(...) addon:_Trace(false,1,...) end
-local xprint=function(dbg,...) if (type(dbg)=="boolean") then if dbg then addon:Print('DBG',...) end end end--else addon:Print(dbg,...) end end
---xprint=function() end
-local debug=ns.debug or print
-local dump=ns.dump or print
+local print=addon:Wrap("Print")
+local trace=addon:Wrap("Trace")
+local xprint=function() end
local pairs=pairs
local select=select
local next=next
@@ -19,13 +18,12 @@ local type=type
local GetAddOnMetadata=GetAddOnMetadata
local CreateFrame=CreateFrame
local wipe=wipe
----TODO:
--- Colorare i seguaci in base ala disponbilita' (verdi disponibili, rossi in altre missioni. Magary gialli se working?)
--- Memorizzare la percentuale di successo delle missioni partire, per visualizzarla nel pannello in progress
--- Rifare il tooltip
--- Decidere come (se) usare lo spazio che rimane a destra delle icone
+local format=format
+local tostring=tostring
+local collectgarbage=collectgarbage
--@debug@
+if (LibDebug) then LibDebug() end
local function tcopy(obj, seen)
if type(obj) ~= 'table' then return obj end
if seen and seen[obj] then return seen[obj] end
@@ -39,6 +37,8 @@ end
-----------------------------------------------------------------
-- Recycling function from ACE3
----newcount, delcount,createdcount,cached = 0,0,0
+
+
local new, del, copy
do
local pool = setmetatable({},{__mode="k"})
@@ -145,6 +145,14 @@ local GARRISON_MISSION_PERCENT_CHANCE="%d%%"-- GARRISON_MISSION_PERCENT_CHANCE
local GARRISON_MISSION_SUCCESS=GARRISON_MISSION_SUCCESS -- "Success"
local GARRISON_MISSION_TOOLTIP_NUM_REQUIRED_FOLLOWERS=GARRISON_MISSION_TOOLTIP_NUM_REQUIRED_FOLLOWERS -- "%d Follower mission";
local GARRISON_PARTY_NOT_FULL_TOOLTIP=GARRISON_PARTY_NOT_FULL_TOOLTIP -- "You do not have enough followers on this mission."
+local GARRISON_MISSION_CHANCE=GARRISON_MISSION_CHANCE -- Chanche
+local GARRISON_FOLLOWER_BUSY_COLOR=GARRISON_FOLLOWER_BUSY_COLOR
+local GARRISON_FOLLOWER_INACTIVE_COLOR=GARRISON_FOLLOWER_INACTIVE_COLOR
+local GARRISON_CURRENCY=GARRISON_CURRENCY --824
+local GARRISON_FOLLOWER_MAX_UPGRADE_QUALITY=GARRISON_FOLLOWER_MAX_UPGRADE_QUALITY -- 4
+local GARRISON_FOLLOWER_MAX_LEVEL=GARRISON_FOLLOWER_MAX_LEVEL -- 100
+
+local LEVEL=LEVEL -- Level
local NOT_COLLECTED=NOT_COLLECTED -- not collected
local GMF=GarrisonMissionFrame
local GMFFollowerPage=GMF.FollowerTab
@@ -163,7 +171,8 @@ local GMFFollowersListScrollFrameScrollChild=GarrisonMissionFrameFollowersListSc
local GMFFollowersListScrollFrame=GarrisonMissionFrameFollowersListScrollFrame
local GMFTab1=GarrisonMissionFrameTab1
local GMFTab2=GarrisonMissionFrameTab2
-local GMFTab3=GarrisonMissionFrameTab3
+local GMFTab3=_G.GarrisonMissionFrameTab3
+local GarrisonFollowerTooltip=GarrisonFollowerTooltip
local GarrisonMissionFrameMissionsListScrollFrame=GarrisonMissionFrameMissionsListScrollFrame
local IGNORE_UNAIVALABLE_FOLLOWERS=IGNORE.. ' ' .. UNAVAILABLE .. ' ' .. GARRISON_FOLLOWERS
local IGNORE_UNAIVALABLE_FOLLOWERS_DETAIL=IGNORE.. ' ' .. GARRISON_FOLLOWER_INACTIVE .. ',' .. GARRISON_FOLLOWER_ON_MISSION ..',' .. GARRISON_FOLLOWER_WORKING.. ','.. GARRISON_FOLLOWER_EXHAUSTED .. ' ' .. GARRISON_FOLLOWERS
@@ -174,19 +183,41 @@ local ANYONE='('..SPELL_TARGET_TYPE1_DESC..')'
local UNKNOWN_CHANCE=GARRISON_MISSION_PERCENT_CHANCE:gsub('%%d%%%%',UNKNOWN)
IGNORE_UNAIVALABLE_FOLLOWERS=capitalize(IGNORE_UNAIVALABLE_FOLLOWERS)
IGNORE_UNAIVALABLE_FOLLOWERS_DETAIL=capitalize(IGNORE_UNAIVALABLE_FOLLOWERS_DETAIL)
-local GARRISON_DURATION_HOURS_MINUTES=GARRISON_DURATION_HOURS_MINUTES
-local GARRISON_DURATION_DAYS_HOURS=GARRISON_DURATION_DAYS_HOURS
+local UNKNOWN=UNKNOWN -- Unknown
+local TYPE=TYPE -- Type
+local ALL=ALL -- All
+local MAXMISSIONS=8
+local MINPERC=20
+local BUSY_MESSAGE_FORMAT=L["Only first %1$d missions with over %2$d%% chance of success are shown"]
+local BUSY_MESSAGE=format(BUSY_MESSAGE_FORMAT,MAXMISSIONS,MINPERC)
+
+local function splitFormat(base)
+ local i,s=base:find("|4.*:.*;")
+ local m0,m1=base:match("|4(.*):(.*);")
+ local G=base
+ local G1=G:sub(1,i-1)..m0..G:sub(s+1)
+ local G2=G:sub(1,i-1)..m1..G:sub(s+1)
+ return G1,G2
+end
+
+local GARRISON_DURATION_DAY,GARRISON_DURATION_DAYS=splitFormat(GARRISON_DURATION_DAYS) -- "%d |4day:days;";
+local GARRISON_DURATION_DAY_HOURS,GARRISON_DURATION_DAYS_HOURS=splitFormat(GARRISON_DURATION_DAYS_HOURS) -- "%d |4day:days; %d hr";
+local GARRISON_DURATION_HOURS=GARRISON_DURATION_HOURS -- "%d hr";
+local GARRISON_DURATION_HOURS_MINUTES=GARRISON_DURATION_HOURS_MINUTES -- "%d hr %d min";
+local GARRISON_DURATION_MINUTES=GARRISON_DURATION_MINUTES -- "%d min";
+local GARRISON_DURATION_SECONDS=GARRISON_DURATION_SECONDS -- "%d sec";
local AGE_HOURS="First seen " .. GARRISON_DURATION_HOURS_MINUTES .. " ago"
local AGE_DAYS="First seen " .. GARRISON_DURATION_DAYS_HOURS .. " ago"
-local UNKNOWN=UNKNOWN
-local TYPE=TYPE
+
+
-- Panel sizes
-local BIGSIZEW=1400
+local BIGSIZEW=1220
local BIGSIZEH=662
local SIZEW=950
local SIZEH=662
local SIZEV
-local GCSIZE=800
+local GCSIZE=700
+local FLSIZE=400
local BIGBUTTON=BIGSIZEW-GCSIZE
local SMALLBUTTON=BIGSIZEW-GCSIZE
local GCF
@@ -200,10 +231,10 @@ local GarrisonMissionList_UpdateMissions=GarrisonMissionList_UpdateMissions
local GarrisonMissionPage_ClearFollower=GarrisonMissionPage_ClearFollower
local GarrisonMissionPage_UpdateMissionForParty=GarrisonMissionPage_UpdateMissionForParty
local GarrisonMissionPage_SetFollower=GarrisonMissionPage_SetFollower
+local GarrisonMissionButton_SetRewards=GarrisonMissionButton_SetRewards
local GetItemInfo=GetItemInfo
local type=type
local ITEM_QUALITY_COLORS=ITEM_QUALITY_COLORS
-local deadly={r=C.Purple.r,g=C.Purple.g,b=C.Purple.b}
function addon:GetDifficultyColor(perc)
if(perc >90) then
return QuestDifficultyColors['standard']
@@ -220,28 +251,57 @@ end
if (LibDebug) then LibDebug() end
----- Local variables
--
-local t0={
- __index=function(t,k) rawset(t,k,{}) return t[k] end
-}
-
+-- Forces a table to countain other tables,
local t1={
- __index=function(t,k) rawset(t,k,setmetatable({},t0)) return t[k] end
+ __index=function(t,k) rawset(t,k,{}) return t[k] end
}
local t2={
__index=function(t,k) rawset(t,k,setmetatable({},t1)) return t[k] end
}
local masterplan
-local availableFollowers=0 -- Total numner of non in mission followers
local followersCache={}
local followersCacheIndex={}
local dirty=false
local cache
local dbcache
-local timers={}
-local counters=setmetatable({},t0)
+local n=setmetatable({},{
+ __index = function(t,k)
+ local name=addon:GetFollowerData(k,'fullname')
+ if (name) then rawset(t,k,name) return name else return k end
+ end
+})
+
+-- Counter system
+local function cleanicon(stringa)
+ return (stringa:lower():gsub("%.blp$",""))
+end
+local counters=setmetatable({},t2)
local counterThreatIndex=setmetatable({},t2)
local counterFollowerIndex=setmetatable({},t2)
-local onMission={}
+local function genIteratorByFollower(missionID,followerID,tbl)
+ do
+ local tt=counters[missionID]
+ local tx=counterFollowerIndex[missionID][followerID]
+ setmetatable(tbl,{
+ __index=function(t,k) return tt[tx[k]] end,
+ __call=function(t) return #tx end
+ }
+ )
+ return tbl
+ end
+end
+local function genIteratorByThreat(missionID,threat,tbl)
+ do
+ local tt=counters[missionID]
+ local tx=counterThreatIndex[missionID][threat]
+ setmetatable(tbl,{
+ __index=function(t,k) return tt[tx[k]] end,
+ __call=function(t) return #tx end
+ }
+ )
+ return tbl
+ end
+end
--- Parties storage
--
@@ -249,40 +309,21 @@ local onMission={}
local parties=setmetatable({},{
__index=function(t,k) rawset(t,k,{members={},perc=0,full=false}) return t[k] end
})
-
+local function inParty(missionID,followerID)
+ local members=parties[missionID].members
+ for i=1,#members do
+ return members[i]==followerID
+ end
+end
--- Follower Missions Info
--
local followerMissions=setmetatable({},{
__index=function(t,k) rawset(t,k,{}) return t[k] end
})
---- Counters Info per mission
---
-
-local counters=setmetatable({},{
- __index=function(t,k) rawset(t,k,{}) return t[k] end
-})
-
------------------------------------------------------
--- Coroutines data
--------------
-local coroutines={
- Timers={
- func=false,
- elapsed=60,
- interval=10,
- paused=false
- },
- Drawer={
- func=false,
- elapsed=0,
- interval=1,
- paused=false
- }
-}
--
-- Temporary party management
-local openParty,isInParty,pushFollower,removeFollower,closeParty,roomInParty,storeFollowers
+local openParty,isInParty,pushFollower,removeFollower,closeParty,roomInParty,storeFollowers,dumpParty
do
local ID,frames,members,maxFollowers=0,{},{},1
@@ -304,21 +345,32 @@ do
if (followerID==members[i]) then return true end
end
end
+
---@function [parent=#local] roomInParty
function roomInParty()
- return not members[maxFollowers]
+ return maxFollowers-#members
+ end
+
+ ---@function [parent=#local] dumpParty
+ function dumpParty()
+ for i=1,3 do
+ if (members[i]) then
+ print(i,addob:GetFollowerData(members[i],'fullname'))
+ end
+ end
end
+
---@function [parent=#local] pushFollower
function pushFollower(followerID)
- if (followerID:sub(1,2) ~= '0x') then error(followerID .. "is not an id") end
- if (roomInParty()) then
+ if (followerID:sub(1,2) ~= '0x') then trace(followerID .. "is not an id") end
+ if (roomInParty()>0) then
local rc,code=pcall (C_Garrison.AddFollowerToMission,ID,followerID)
if (rc and code) then
tinsert(members,followerID)
return true
--@debug@
else
- print("Error adding ", followerID,"to",ID,code)
+ trace("Unable to add", n[followerID],"to",ID,code)
--@end-debug@
end
end
@@ -330,7 +382,7 @@ do
tremove(members,i)
local rc,code=pcall(C_Garrison.RemoveFollowerFromMission,ID,followerID)
--@debug@
- if (not rc) then xprint("Error removing", members[i],"from",ID,code) end
+ if (not rc) then trace("Unable to remove", n[members[i]],"from",ID,code) end
--@end-debug@
return true end
end
@@ -352,7 +404,7 @@ do
if (members[i]) then
local rc,code=pcall(C_Garrison.RemoveFollowerFromMission,ID,members[i])
--@debug@
- if (not rc) then xprint("Error popping ", members[i]," from ",ID,code) end
+ if (not rc) then trace("Unable to pop", members[i]," from ",ID,code) end
--@end-debug@
else
@@ -361,28 +413,112 @@ do
end
for i=1,#frames do
frames[i]:RegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE")
+
end
wipe(frames)
wipe(members)
return perc
end
end
--- ProgressBar
+-- These local will became conf var
+-- locally upvalued, doing my best to not interfere with other sorting modules,
+-- First time i am called to verride it I save it, so I give other modules a chance to hook it, too
+-- Could even do a trick and secureHook it at the expense of a double sort...
+local origGarrison_SortMissions
-function addon:AddLine(icon,name,status,quality,...)
- local r2,g2,b2=C.Red()
- local q=ITEM_QUALITY_COLORS[quality or 1] or {}
- if (status==AVAILABLE) then
- r2,g2,b2=C.Green()
- elseif (status==GARRISON_FOLLOWER_WORKING) then
- r2,g2,b2=C.Orange()
+function addon.Garrison_SortMissions_Chance(missionsList)
+ local comparison
+ do
+ function comparison(mission1, mission2)
+ local p1=parties[mission1.missionID]
+ local p2=parties[mission2.missionID]
+ if (p2.full and not p1.full) then return false end
+ if (p1.full and not p2.full) then return true end
+ if (p1.perc==p2.perc) then
+ return strcmputf8i(mission1.name, mission2.name) < 0
+ else
+ return p1.perc > p2.perc
+ end
+ end
+ end
+ table.sort(missionsList, comparison);
+end
+function addon.Garrison_SortMissions_Followers(missionsList)
+ local comparison
+ do
+ function comparison(mission1, mission2)
+ local p1=mission1.numFollowers
+ local p2=mission2.numFollowers
+ if (p1==p2) then
+ return strcmputf8i(mission1.name, mission2.name) < 0
+ else
+ return p1 < p2
+ end
+ end
+ end
+ table.sort(missionsList, comparison);
+end
+
+function addon:OnInitialized()
+--@debug@
+ print("OnInitialized")
+ LoadAddOn("Blizzard_DebugTools")
+ self:DebugEvents()
+--@end-debug@
+ self:CreatePrivateDb()
+ self:SafeRegisterEvent("GARRISON_MISSION_STARTED")
+ self:SafeRegisterEvent("GARRISON_MISSION_BONUS_ROLL_COMPLETE")
+ self:SafeRegisterEvent("GARRISON_MISSION_NPC_CLOSED",function(...) GCF:Hide() end)
+ self:SafeHookScript("GarrisonMissionFrame","OnShow","SetUp",true)
+ self:AddToggle("MOVEPANEL",true,L["Unlock Garrison Panel"])
+ self:AddToggle("IGM",true,IGNORE_UNAIVALABLE_FOLLOWERS,IGNORE_UNAIVALABLE_FOLLOWERS_DETAIL)
+ self:AddToggle("IGP",true,L["Ignore epic quality level 100 followers"],L["Level 100 epic followers are not used for match making. Useful when you level"])
+ self:AddSelect("MSORT","Garrison_SortMissions_Original",
+ {
+ Garrison_SortMissions_Original=L["Original method"],
+ Garrison_SortMissions_Chance=L["Success Chance"],
+ Garrison_SortMissions_Followers=L["Number of followers"],
+ },
+ L["Sort missions by:"],L["Original sort restores original sorting method, whatever it was (If you have another addon sorting mission, it should kick in again)"])
+--self:AddSlider("RESTIMER",5,1,10,"Enable res timer","Shows a timer for battlefield resser",1)
+ self:AddSlider("MAXMISSIONS",5,1,8,L["Mission shown for follower"],nil,1)
+ self:AddSlider("MINPERC",50,0,100,L["Minimun chance success under which ignore missions"],nil,5)
+ self:Trigger("MSORT")
+ return true
+end
+function addon:ApplyIGM(value)
+ self:BuildMissionsCache(false,true)
+ GarrisonMissionList_UpdateMissions()
+end
+function addon:ApplyIGP(value)
+ self:BuildMissionsCache(false,true)
+ GarrisonMissionList_UpdateMissions()
+end
+
+function addon:ApplyMSORT(value)
+ if (not origGarrison_SortMissions) then
+ origGarrison_SortMissions=Garrison_SortMissions
+ end
+ local func=self[value]
+ if (type(func)=="function") then
+ Garrison_SortMissions=self[value]
+ else
+ Garrison_SortMissions=origGarrison_SortMissions
end
- --GameTooltip:AddDoubleLine(name, status or AVAILABLE,r,g,b,r2,g2,b2)
- --GameTooltip:AddTexture(icon)
- GameTooltip:AddDoubleLine(icon and "|T" .. tostring(icon) .. ":0|t " .. name or name, status,q.r,q.g,q.b,r2,g2,b2)
+ GarrisonMissionList_UpdateMissions()
+end
+function addon:ApplyMAXMISSIONS(value)
+ MAXMISSIONS=value
+ BUSY_MESSAGE=format(BUSY_MESSAGE_FORMAT,MAXMISSIONS,MINPERC)
+
+end
+function addon:ApplyMINPERC(value)
+ MINPERC=value
+ BUSY_MESSAGE=format(BUSY_MESSAGE_FORMAT,MAXMISSIONS,MINPERC)
end
+
function addon:RestoreTooltip()
local self = GMF.MissionTab.MissionList;
local scrollFrame = self.listScroll;
@@ -486,6 +622,7 @@ local function cmp(a,b)
return a.quality < b.quality
end
+
function addon:FillCounters(missionID,mission)
if (not mission) then mission=self:GetMissionData(missionID) end
local slots=mission.slots
@@ -502,7 +639,7 @@ function addon:FillCounters(missionID,mission)
-- l.counterName
-- l.icon
-- l.description
- tinsert(missioncounters,{mechanic=true,name=l.name,followerID=id,bias=bias,rank=rank,quality=quality,icon=l.icon})
+ tinsert(missioncounters,{k=cleanicon(l.icon),mechanic=true,name=l.name,followerID=id,bias=bias,rank=rank,quality=quality,icon=l.icon})
followerMissions[id][missionID]=1+ (tonumber(followerMissions[id][missionID]) or 0)
end
end
@@ -515,15 +652,15 @@ function addon:FillCounters(missionID,mission)
--l.traitID
--l.icon
followerMissions[id][missionID]=1+ (tonumber(followerMissions[id][missionID]) or 0)
- tinsert(missioncounters,{trait=true,name=l.icon,followerID=id,bias=bias,rank=rank,quality=quality,icon=l.icon})
+ tinsert(missioncounters,{k=cleanicon(l.icon),trait=true,name=l.traitID,followerID=id,bias=bias,rank=rank,quality=quality,icon=l.icon})
end
end
table.sort(missioncounters,cmp)
- local cf=counterFollowerIndex[missionID]
- local ct=counterThreatIndex[missionID]
+ local cf=wipe(counterFollowerIndex[missionID])
+ local ct=wipe(counterThreatIndex[missionID])
for i=1,#missioncounters do
tinsert(cf[missioncounters[i].followerID],i)
- tinsert(ct[missioncounters[i].icon],i)
+ tinsert(ct[missioncounters[i].k],i)
end
end
function addon:Check(missionID)
@@ -644,10 +781,14 @@ RareOverlay table
Summary table
HighlightTL table
--]]
+local dbg=false
local function best(fid1,fid2,counters)
if (not fid1) then return fid2 end
if (not fid2) then return fid1 end
local f1,f2=counters[fid1],counters[fid2]
+ if (dbg) then
+ print("Current",fid1,n[f1.followerID]," vs Candidate",fid2,n[f2.followerID])
+ end
if (isInParty(f1.followerID)) then return fid1 end
if (f2.bias<0) then return fid1 end
if (f2.bias>f1.bias) then return fid2 end
@@ -656,13 +797,86 @@ local function best(fid1,fid2,counters)
end
return fid1
end
+function addon:CompleteParty(missionID,mission,skipbusy)
+ local perc=select(4,G.GetPartyMissionInfo(missionID)) -- If percentage is already 100, I'll try and add the most useless character
+ local candidateMissions=10000
+ local candidateRank=10000
+ local candidateQuality=9999
+ if (dbg) then
+ print("Attemptin to fill party, so far:")
+ dumpParty()
+ end
+ for x=1,roomInParty() do
+ local candidate
+ local candidatePerc=perc
+ local totFollowers=#followersCache
+ for i=1,totFollowers do
+ local data=followersCache[i]
+ local followerID=data.followerID
+ if (not self:IsIgnored(followerID,missionID) and not isInParty(followerID) and self:GetFollowerStatusForMission(followerID,skipbusy)) then
+ local missions=#followerMissions[followerID]
+ local rank=data.rank
+ local quality=data.quality
+ repeat
+ if (perc<100) then
+ pushFollower(followerID)
+ local newperc=select(4,G.GetPartyMissionInfo(missionID))
+ removeFollower(followerID)
+ if (newperc > candidatePerc) then
+ candidatePerc=newperc
+ candidate=followerID
+ candidateMissions=missions
+ candidateRank=rank
+ candidateQuality=quality
+ break -- continue
+ elseif (newperc < candidatePerc) then
+ break --continue
+ end
+ end
+ -- This candidate is not improving success chance, minimize
+ if (i < totFollowers and data.maxed) then
+ break -- Pointless using a maxed follower if we have more follower to try
+ end
+ if (missions<candidateMissions) then
+ candidate=followerID
+ candidateMissions=missions
+ candidateRank=rank
+ candidateQuality=quality
+ elseif(missions==candidateMissions and rank<candidateRank) then
+ candidate=followerID
+ candidateMissions=missions
+ candidateRank=rank
+ candidateQuality=quality
+ elseif(missions==candidateMissions and rank==candidateRank and quality<candidateQuality) then
+ candidate=followerID
+ candidateMissions=missions
+ candidateRank=rank
+ candidateQuality=quality
+ elseif (not candidate) then
+ candidate=followerID
+ candidateMissions=missions
+ candidateRank=rank
+ candidateQuality=quality
+ end
+ until true -- A poor man continue implementation using break
+ end
+ end
+ if (candidate) then
+ pushFollower(candidate)
+ if (dbg) then
+ print("Added member to party")
+ dumpParty()
+ end
+ perc=select(4,G.GetPartyMissionInfo(missionID))
+ end
+ end
+end
function addon:MatchMaker(missionID,mission,party,skipbusy)
- if (not mission) then return end
+ if (not mission) then mission=self:GetMissionData(missionID) end
+ if (not party) then party=parties[missionID] end
+ if (not skipbusy) then skipbusy=self:GetBoolean("IGM") end
if (GMFRewardSplash:IsShown()) then return end
- local dbg=missionID==(tonumber(_G.MW) or 0)
- if (not skipbusy) then
- skipbusy=self:GetBoolean("IGM")
- end
+ dbg=missionID==(tonumber(_G.MW) or 0)
local ignoreMaxed=self:GetBoolean("IGP")
local slots=mission.slots
local missionCounters=counters[missionID]
@@ -670,373 +884,141 @@ function addon:MatchMaker(missionID,mission,party,skipbusy)
local skipbusy=addon:GetBoolean("IGM")
openParty(missionID,mission.numFollowers)
for i=1,#slots do
- local threat=slots[i].icon
+ local threat=cleanicon(slots[i].icon)
local candidates=ct[threat]
local choosen
for i=1,#candidates do
- if (addon:GetFollowerStatusForMission(missionCounters[candidates[i]].followerID,skipbusy)) then
- choosen=best(choosen,candidates[i],missionCounters)
+ local followerID=missionCounters[candidates[i]].followerID
+ if (self:IsIgnored(followerID,missionID)) then
+ if (dbg) then print("Skipped",n[followerID],"due to ignored" ) end
+ else
+ if (addon:GetFollowerStatusForMission(followerID,skipbusy)) then
+ if (ignoreMaxed and self:GetFollowerData(followerID,'maxed')) then
+ if (dbg) then print("Skipped",n[followerID],"due to level" ) end
+ else
+ choosen=best(choosen,candidates[i],missionCounters)
+ if (dbg) then print("Taken",n[missionCounters[choosen].followerID]) end
+ end
+ end
end
end
if (choosen) then
if (type(missionCounters[choosen]) ~="table") then
- error (format("%s %s %d %d",mission.name,threat,missionID,tonumber(choosen) or 0))
+ trace(format("%s %s %d %d",mission.name,threat,missionID,tonumber(choosen) or 0))
end
pushFollower(missionCounters[choosen].followerID)
end
- if (not roomInParty()) then
+ if (roomInParty()==0) then
break
end
end
+ self:CompleteParty(missionID,mission,skipbusy)
storeFollowers(party.members)
- party.full= not roomInParty()
+ party.full= roomInParty()==0
party.perc=closeParty()
end
-function addon:MatchMaker1(missionID,mission,party,skipbusy)
- if (not mission) then return end
- if (GMFRewardSplash:IsShown()) then return end
- local dbg=missionID==(tonumber(_G.MW) or 0)
- if (not skipbusy) then
- skipbusy=self:GetBoolean("IGM")
- end
- local ignoreMaxed=self:GetBoolean("IGP")
- local slots=mission.slots
- if (slots) then
- wipe(mission.countered)
- local countered=mission.countered
- openParty(missionID,mission.numFollowers)
- for i=1,#counters do
- local f=counters[i]
- local menace=f.name
- if (#countered[menace] == 0) then
- if (roomInParty() and self:GetFollowerStatusForMission(f.follower,skipbusy) and pushFollower(f.follower)) then
- tinsert(countered[menace],f.follower)
- end
- end
- end
- local perc=select(4,G.GetPartyMissionInfo(missionID)) -- If percentage is already 100, I'll try and add the most useless character
- local candidateMissions=10000
- local candidateRank=10000
- local candidateQuality=9999
- for x=1,3 do
- if (not roomInParty()) then break end
- local candidate
- local candidatePerc=perc
- for _,data in pairs(followersCache) do
- local followerID=data.followerID
- if (not isInParty(followerID) and self:GetFollowerStatusForMission(followerID,skipbusy)) then
- local missions=#followerMissions[followerID]
- local rank=data.rank
- local quality=data.quality
- xprint(dbg,"Verifying",self:GetFollowerData(followerID,'name'),missions,rank,quality)
- repeat
- if (mission.numFollowers==1 and mission.xp and quality>4) then break end -- Pointless using a maxed follower for an xp only mission
- if (perc<=100) then
- pushFollower(followerID)
- local newperc=select(4,G.GetPartyMissionInfo(missionID))
- removeFollower(followerID)
- if (newperc > candidatePerc) then
- candidatePerc=newperc
- candidate=followerID
- candidateMissions=missions
- candidateRank=rank
- candidateQuality=quality
- break -- continue
- elseif (newperc < candidatePerc) then
- break --continue
- end
- end
- if (missions<candidateMissions) then
- candidate=followerID
- candidateMissions=missions
- candidateRank=rank
- candidateQuality=quality
- elseif(missions==candidateMissions and rank<candidateRank) then
- candidate=followerID
- candidateMissions=missions
- candidateRank=rank
- candidateQuality=quality
- elseif(missions==candidateMissions and rank==candidateRank and quality<candidateQuality) then
- candidate=followerID
- candidateMissions=missions
- candidateRank=rank
- candidateQuality=quality
- end
- until true -- A poor man continue implementation using break
+function addon:IsIgnored(followerID,missionID)
+ if (dbcache.ignored[missionID][followerID]) then return true end
+ if (dbcache.totallyignored[followerID]) then return true end
+end
+function addon:GetCounterBias(missionID,threat)
+ local bias=-1
+ local who=""
+ local iter=genIteratorByThreat(missionID,cleanicon(tostring(threat)),new())
+ for i=1,iter() do
+ if (iter[i]) then
+ if (iter[i].bias > bias) then
+ if (inParty(missionID,iter[i].followerID)) then
+ bias=iter[i].bias
+ who=iter[i].name
end
end
- if (candidate) then
- pushFollower(candidate)
- perc=select(4,G.GetPartyMissionInfo(missionID))
- end
-
end
- storeFollowers(party.members)
- party.full= not roomInParty()
- party.perc=closeParty()
end
+ del(iter)
+ return bias,who
+end
+function addon:AddLine(name,status)
+ local r2,g2,b2=C.Red()
+ if (status==AVAILABLE) then
+ r2,g2,b2=C.Green()
+ elseif (status==GARRISON_FOLLOWER_WORKING) then
+ r2,g2,b2=C.Orange()
+ end
+ GameTooltip:AddDoubleLine(name, status,nil,nil,nil,r2,g2,b2)
end
-function addon:TooltipAdder(missionID)
+
+function addon:HookedGarrisonMissionButton_AddThreatsToTooltip(missionID)
local mission=self:GetMissionData(missionID)
local button=GetMouseFocus()
--@debug@
GameTooltip:AddLine("ID:" .. tostring(missionID))
if (not mission) then GameTooltip:AddLine("E dove minchia è finita??") return end
- _G.MISSION=mission
---@end-debug@
- local f=GarrisonMissionListTooltipThreatsFrame
- if (not f.Env) then
- f.Env=CreateFrame("Frame",nil,f,"GarrisonAbilityCounterTemplate")
- f.Env:SetWidth(20)
- f.Env:SetHeight(20)
- f.Env:SetPoint("LEFT",f)
- end
- local t=f.EnvIcon:GetTexture();
- f.EnvIcon:Hide()
- --f.Env.Icon:SetTexture("Interface\\ICONS\\Achievement_ZoneSilverpine_01")
- f.Env.Icon:SetTexture(t)
- f.Env.Icon:SetWidth(20)
- f.Env.Icon:SetHeight(20)
- if (type(mission.counterers[t])=="table") then
- if (#mission.counterers[t]>0) then
- f.Env.Border:SetVertexColor(0,1,0)
- else
- f.Env.Border:SetVertexColor(1,0,0)
- end
- f.Env.Icon:Show()
- f.Env.Border:Show()
- f:Raise()
- f.Env:Show()
- else
- f.Env:Hide()
- end
---[[
- if (not f.EnvIcon.Mark) then
- local ck=CreateFrame("CheckButton",nil,f.EnvIcon,"UICheckButtonTemplate")
- ck:SetPoint("CENTER")
- ck:SetChecked(true)
- ck:GetCheckedTexture():SetVertexColor(0,1,0)
- f.EnvIcon.Marck=ck
- ck:Show()
- end
---]]
- GameTooltip:AddDoubleLine(t,"Environment")
- for i=1,#f.Threats do
- local t=f.Threats[i]
- GameTooltip:AddDoubleLine(t.Icon:GetTexture(),getAbilityName(t.Icon:GetTexture()))
- end
- GameTooltip:AddLine("Countered")
- for k,v in pairs(mission.countered) do
- GameTooltip:AddLine(k,C.Green())
- for kk,vv in pairs(v) do
- GameTooltip:AddDoubleLine(kk,vv)
- end
- end
- if (button.fromFollowerPage) then
- GameTooltip:AddLine(L["Only first 7 missions with over 60% success chance are shown"],C.Orange())
- end
-end
-
-function addon:_TooltipAdder(missionID,skipTT)
---@debug@
- if (not skipTT) then GameTooltip:AddLine("ID:" .. tostring(missionID)) end
---@end-debug@
- self:MatchMaker(missionID)
- local perc=select(4,G.GetPartyMissionInfo(missionID))
- self:GetRunningMissionData()
- local q=self:GetDifficultyColor(perc)
- if (not skipTT) then GameTooltip:AddDoubleLine(GARRISON_MISSION_SUCCESS,format(GARRISON_MISSION_PERCENT_CHANCE,perc),nil,nil,nil,q.r,q.g,q.b) end
- local buffed=new()
- local traited=new()
- local buffs=new()
- local traits=new()
- local fellas=new()
- availableFollowers=0
- self:GetRunningMissionData()
- for id,d in pairs(G.GetBuffedFollowersForMission(missionID)) do
- buffed[id]=d
- end
- for id,d in pairs(G.GetFollowersTraitsForMission(missionID)) do
- for x,y in pairs(d) do
---@debug@
- self.db.global.traits[y.traitID]=y.icon
---@end-debug@
- if (y.traitID~=236) then --Ignore hearthstone traits
- traited[id]=d
- break
- end
- end
- end
- local followerList=GarrisonMissionFrameFollowers.followersList
-
- for j=1,#followerList do
- local index=followerList[j]
- local follower=followers[index]
- follower.rank=follower.level < 100 and follower.level or follower.iLevel
- if (not follower.isCollected) then break end
- if (not follower.status) then
- availableFollowers=availableFollowers+1
- end
- if (follower.status and self:GetBoolean('IGM')) then
- else
- local id=follower.followerID
- local b=buffed[id]
- local t=traited[id]
- local followerBias = G.GetFollowerBiasForMission(missionID,id);
- follower.bias=followerBias
- local formato=C("%3d","White")
- if (followerBias==-1) then
- formato=C("%3d","Red")
- elseif (followerBias < 0) then
- formato=C("%3d","Orange")
- end
- formato=formato.." %s"
---@debug@
- formato=formato .. " 0x+(0*8) " .. id:sub(11)
---@end-debug@
- if (b) then
- if (not buffs[id]) then
- buffs[id]={rank=follower.rank,simple=follower.name,name=format(formato,follower.rank,follower.name),quality=follower.quality,status=(follower.status or AVAILABLE)}
- end
- for _,ability in pairs(b) do
- buffs[id].name=buffs[id].name .. " |T" .. tostring(ability.icon) .. ":0|t"
- if (not follower.status) then
- local aname=ability.name
- if (not fellas[aname]) then
- fellas[aname]={}
- end
- fellas[aname]={id=follower.followerID,rank=follower.rank,level=follower.level,iLevel=follower.iLevel,name=follower.name}
- end
- end
- end
- if (t) then
- if (not traits[id]) then
- traits[id]={rank=follower.rank,simple=follower.name,name=format(formato,follower.rank,follower.name),quality=follower.quality,status=follower.status or AVAILABLE}
- end
- for _,ability in pairs(t) do
- traits[id].name=traits[id].name .. " |T" .. tostring(ability.icon) .. ":0|t"
- end
- end
- end
- end
- local added=new()
- local maxfollowers=G.GetMissionMaxFollowers(missionID)
- requested[missionID]=maxfollowers
- local partyshown=false
- local perc=0
- if (next(traits) or next(buffs) ) then
- if (not skipTT) then GameTooltip:AddLine(GARRISON_FOLLOWER_CAN_COUNTER) end
- for id,v in pairs(buffs) do
- local status=(v.status == GARRISON_FOLLOWER_ON_MISSION and (timers[id] or GARRISON_FOLLOWER_ON_MISSION)) or v.status
- if (not skipTT) then self:AddLine(nil,v.name,status,v.quality) end
- end
- for id,v in pairs(traits) do
- local status=(v.status == GARRISON_FOLLOWER_ON_MISSION and (timers[id] or GARRISON_FOLLOWER_ON_MISSION)) or v.status
- if (not skipTT) then self:AddLine(nil,v.name,status,v.quality) end
- end
- if (not skipTT) then GameTooltip:AddLine(PARTY,C.White()) end
- partyshown=true
- local enemies = select(8,G.GetMissionInfo(missionID))
- --local missionInfo=G.GetBasicMissionInfo(missionID)
---@debug@
- --DevTools_Dump(fellas)
--@end-debug@
- for _,enemy in pairs(enemies) do
- for i,mechanic in pairs(enemy.mechanics) do
- local menace=mechanic.name
- local res
- if (fellas[menace]) then
- local followerID=fellas[menace].id
- res=fellas[menace].name
- local rc,code=pcall(G.AddFollowerToMission,missionID,followerID)
- if (rc and code) then
- tinsert(added,followerID)
- end
- end
- if (not skipTT) then
- if (res) then
- GameTooltip:AddDoubleLine(menace,res,0,1,0)
- else
- GameTooltip:AddDoubleLine(menace,' ',1,0,0)
- end
- end
+ if (true) then
+ local f=GarrisonMissionListTooltipThreatsFrame
+ if (not f.Env) then
+ f.Env=CreateFrame("Frame",nil,f,"GarrisonAbilityCounterTemplate")
+ f.Env:SetWidth(20)
+ f.Env:SetHeight(20)
+ f.Env:SetPoint("LEFT",f)
+ end
+ local t=f.EnvIcon:GetTexture();
+ f.EnvIcon:Hide()
+ f.Env.Icon:SetTexture(t)
+ f.Env.Icon:SetWidth(20)
+ f.Env.Icon:SetHeight(20)
+ local bias,who=self:GetCounterBias(missionID,t)
+ local color=self:GetBiasColor(bias,nil,"Green")
+ local c=C[color]
+ f.Env.Border:SetVertexColor(c())
+ for i=1,#f.Threats do
+ local th=f.Threats[i]
+ local bias=self:GetCounterBias(missionID,th.Icon:GetTexture())
+ local color=self:GetBiasColor(bias,nil,"Green")
+ local c=C[color]
+ th.Border:SetVertexColor(c())
+ end
+ end
+ -- Adding All available followers
+ GameTooltip:AddLine(L["Other useful followers"])
+ local fullnames=new()
+ local biascolors=new()
+ local partystring=strjoin("|",tostringall(unpack(parties[missionID].members)))
+ for followerID,refs in pairs(counterFollowerIndex[missionID]) do
+ if (not partystring:find(followerID)) then
+ local fullname= self:GetFollowerData(followerID,'fullname')
+ for i=1,#refs do
+ fullname=fullname .." |T" .. tostring(counters[missionID][refs[i]].icon) ..":16|t"
end
- end
- perc=select(4,G.GetPartyMissionInfo(missionID))
- if (perc < 100 and #added < maxfollowers and next(traits)) then
- for id,v in pairs(traits) do
- local rc,code=pcall(G.AddFollowerToMission,missionID,id)
- if (rc and code) then
- tinsert(added,id)
- if (not skipTT) then GameTooltip:AddDoubleLine(ENVIRONMENT_SUBHEADER,v.simple,v.quality) end
- break
- end
- end
- perc=select(4,G.GetPartyMissionInfo(missionID))
+ tinsert(fullnames,fullname)
+ biascolors[fullname]={self:GetBiasColor(followerID,missionID,"White"),self:GetFollowerStatus(followerID,true)}
end
end
- -- And then fill the roster
- local partysize=#added
- if (partysize < maxfollowers ) then
- for j=1,#followerList do
- local index=followerList[j]
- local follower=followers[index]
- if (not follower.isCollected) then
- break
- end
- if (follower.status and self:GetBoolean('IGM')) then
- else
- local rc,code=pcall(G.AddFollowerToMission,missionID,follower.followerID)
- if (rc and code) then
- if (not partyshown) then
- if (not skipTT) then GameTooltip:AddLine(PARTY,1) end
- partyshown=true
- end
- tinsert(added,follower.followerID)
- if (not skipTT) then
- GameTooltip:AddDoubleLine(SPELL_TARGET_TYPE4_DESC,follower.name,C.Orange.r,C.Orange.g,C.Orange.b)--SPELL_TARGET_TYPE1_DESC)
- end
- if (#added >= maxfollowers) then break end
- else
---@debug@
- xprint("Failed adding",follower.name,follower.followerID,rc,code)
---@end-debug@
- end
- end
- end
- perc=select(4,G.GetPartyMissionInfo(missionID))
+ table.sort(fullnames)
+ for i=1,#fullnames do
+ local fullname=fullnames[i]
+ local info=biascolors[fullname]
+ self:AddLine(fullname,info[2],info[1])
end
+
+-- for i=1,#mission.slots do
+-- local slot=mission.slots[i]
+-- local indexes=counterThreatIndex[missionID][cleanicon(slot.icon)]
+-- local name=C(NONE,"Red")
+-- if (indexes and #indexes > 0) then
+-- local fid=counters[missionID][indexes[1]].followerID
+-- name=fullnames[fid]
+-- end
+-- GameTooltip:AddDoubleLine(slot.name==TYPE and ENVIRONMENT_SUBHEADER or slot.name,name,nil,nil,nil,C.Green())
+-- end
+ del(fullnames)
+ del(biascolors)
+ local perc=parties[missionID].perc
local q=self:GetDifficultyColor(perc)
- if (not partyshown) then
- if (not skipTT) then GameTooltip:AddDoubleLine(PARTY,ANYONE,C.White.r,C.White.g,C.White.b) end
- end
- if (not skipTT) then GameTooltip:AddDoubleLine(GARRISON_MISSION_SUCCESS,format(GARRISON_MISSION_PERCENT_CHANCE,perc),nil,nil,nil,q.r,q.g,q.b) end
- local b=GameTooltip:GetOwner()
- successes[missionID]=perc
- if (availableFollowers < maxfollowers) then
- if (not skipTT) then GameTooltip:AddLine(GARRISON_PARTY_NOT_FULL_TOOLTIP,C:Red()) end
- else
- end
- if (not skipTT) then self:AddPerc(GameTooltip:GetOwner()) end
- for _,id in pairs(added) do
- local rc,code=pcall(G.RemoveFollowerFromMission,missionID,id)
---@debug@
- if (not rc) then xprint("Add",rc,code) end
---@end-debug@
- end
- -- Add a signature
- --local r,g,b=C:Silver()
- --GameTooltip:AddDoubleLine("GarrisonCommander",self.version,r,g,b,r,g,b)
- del(added)
---@debug@
- --DevTools_Dump(fellas)
---@end-debug@
- del(buffed)
- del(traited)
- del(buffs)
- del(traits)
- del(fellas)
+ GameTooltip:AddDoubleLine(GARRISON_MISSION_SUCCESS,format(GARRISON_MISSION_PERCENT_CHANCE,perc),nil,nil,nil,q.r,q.g,q.b)
end
+
function addon:FillFollowersList()
if (GarrisonFollowerList_UpdateFollowers) then
GarrisonFollowerList_UpdateFollowers(GMF.FollowerList)
@@ -1052,157 +1034,144 @@ local function switch(flag)
end
end
end
-function addon:ApplyIGM(value)
- if (not GMF) then return end
- switch("IGM")
- dirty=true
- self:RefreshMissions("Checked")
-end
-function addon:ApplyIGP(value)
- if (not GMF) then return end
- switch("IGP")
- dirty=true
- self:RefreshMissions("Checked")
+function addon:RefreshMission(missionID)
+ if (self:IsAvailableMissionPage()) then
+ if (tonumber(missionID)) then
+ self:FillCounters(missionID)
+ self:MatchMaker(missionID)
+ end
+ GarrisonMissionList_UpdateMissions()
+ end
end
-function addon:GMF_OnDragStart(frame)
- if (not self:GetBoolean('MOVEPANEL')) then return end
- frame.IsSizingOrMoving=true
- if (IsShiftKeyDown()) then
- frame.IsSizing=true
- frame:StartSizing("BOTTOMRIGHT")
- frame:SetScript("OnUpdate",function(frame,elapsed)
- if (frame.timepassed and frame.timepassed >1) then
- self:RefreshMissions()
- else
- frame.timepassed=frame.timepassed or 0
- frame.timepassed=frame.timepassed +elapsed
+function addon:RefreshLayout()
+ for i=1,#GarrisonMissionFrameMissionsListScrollFrame.buttons do
+ local b=GarrisonMissionFrameMissionsListScrollFrame.buttons[i]
+ if (b.Party) then
+ for j=1,3 do
+ DevTools_Dump(b.Party[1])
end
- end)
- else
- frame.IsSizing=nil
- frame:StartMoving()
+ end
end
end
-function addon:GMF_OnDragStop(frame)
- frame:StopMovingOrSizing()
- frame:SetScript("OnUpdate",nil)
- if (frame.IsSizing) then
- BIGSIZEW=frame:GetWidth()
- SIZEV=frame:GetHeight()
- BIGBUTTON=min(BIGSIZEW*0.55,BIGSIZEW-GCSIZE)
- SMALLBUTTON=BIGBUTTON
- if (not self:IsFollowerList()) then
- HybridScrollFrame_CreateButtons(frame.MissionTab.MissionList.listScroll, "GarrisonMissionListButtonTemplate", 13, -8, nil, nil, nil, -4);
- GarrisonMissionList_Update();
- else
- HybridScrollFrame_CreateButtons(frame.FollowerList.listScroll, "GarrisonMissionFollowerButtonTemplate", 7, -7, nil, nil, nil, -6);
- end
- end
- frame.IsSizing=nil
- frame.IsSizingOrMoving=nil
-end
-function addon:ApplyMOVEPANEL(value)
- if (not GMF) then return end
- switch("MOVEPANEL")
- if (value) then
- xprint("GMF MOVABLE")
- --GMF:SetMovable(true)
- --GMF:SetResizable(true)
- --GMF:RegisterForDrag("LeftButton")
- --self:RawHookScript(GMF,"OnDragStart","GMF_OnDragStart")
- --self:RawHookScript(GMF,"OnDragStop","GMF_OnDragStop")
- else
- xprint("GMF UNMOVABLE")
- GMF:SetScript("OnDragStart",nil)
- GMF:SetScript("OnDragStop",nil)
- GMF:ClearAllPoints()
- GMF:SetPoint("CENTER",UIParent)
- GMF:SetMovable(false)
- end
-end
-
-function addon:RefreshMissions(keepdata)
- self:BuildMissionsCache()
- if (self:IsAvailableMissionPage()) then
- if (not keepdata) then
- wipe(counters)
- wipe(parties)
- end
- GarrisonMissionList_UpdateMissions()
- end
-end
-function addon:GenerateDrawerPeriodic()
- return function(self)
- if (true) then return end
- if (self:IsRewardPage()) then return end
- if (GMF.IsMovingOrSizing) then return end
- if (GMF:GetHeight()<600) then return end
- if (GMF:GetWidth()< BIGSIZEW or GMF:GetHeight() < SIZEV) then
- xprint("Periodic redraw")
- self:GrowPanel(true)
- end
- end
-end
-
-function addon:GenerateTimersPeriodic()
- return coroutine.wrap(
- function(self)
- repeat
- local t=new()
- G.GetInProgressMissions(t)
- wipe(timers)
- wipe(onMission)
- for index=1,#t do
- local mission=t[index]
- for i=1,mission.numFollowers do
- timers[mission.followers[i]]=mission.timeLeft
- onMission[mission.followers[i]]=mission.missionID
- end
- end
- coroutine.yield()
- until false
- end
- )
-end
-function addon:BuildMissionsCache()
+function addon:BuildMissionsCache(fc,mm)
--@debug@
local start=GetTime()
- xprint("Start")
- --for x=1,10 do -- stress test
+ print("Start Full Cache Rebuild")
--@end-debug@
local t=new()
G.GetAvailableMissions(t)
for index=1,#t do
local missionID=t[index].missionID
self:BuildMissionCache(missionID,t[index])
- self:MatchMaker(missionID,self:GetMissionData(missionID),parties[missionID],true)
+ if fc then self:FillCounters(missionID) end
+ if mm then self:MatchMaker(missionID) end
end
del(t)
--@debug@
- --end
- xprint("Done in",GetTime()-start)
+ print("Done in",GetTime()-start)
--@end-debug@
end
+--[[
+GARRISON_DURATION_DAYS = "%d |4day:days;"; changed to dual form
+GARRISON_DURATION_DAYS_HOURS = "%d |4day:days; %d hr"; changed to dual form
+GARRISON_DURATION_HOURS = "%d hr";
+GARRISON_DURATION_HOURS_MINUTES = "%d hr %d min";
+GARRISON_DURATION_MINUTES = "%d min";
+GARRISON_DURATION_SECONDS = "%d sec";
+--]]
+local function GarrisonTimeStringToSeconds(text)
+ local s = D.Deformat(text,GARRISON_DURATION_SECONDS)
+ if (s) then return s end
+ local m = D.Deformat(text,GARRISON_DURATION_MINUTES)
+ if m then return m end
+ local h,m= D.Deformat(text,GARRISON_DURATION_HOURS_MINUTES)
+ if (h) then return h*3600+m*60 end
+ local h= D.Deformat(text,GARRISON_DURATION_HOURS)
+ if (h) then return h*3600 end
+ local d,h=D:Deformat(GARRISON_DURATION_DAY_HOURS)
+ if (d) then return d*3600*24 + h*3600 end
+ local d,h=D:Deformat(GARRISON_DURATION_DAYS_HOURS)
+ if (d) then return d*3600*24 + h*3600 end
+ local d=D:Deformat(GARRISON_DURATION_DAYS)
+ if (d) then return d*3600*24 end
+ local d=D:Deformat(GARRISON_DURATION_DAY)
+ if (d) then return d*3600*24 end
+ return 3600*24
+
+end
+function addon:BuildRunningMissionsCache()
+ local t=new()
+ G.GetInProgressMissions(t)
+ for index=1,#t do
+ local mission=t[index]
+ local missionID=mission.missionID
+ local running =dbcache.running[missionID]
+ running.duration=mission.durationSeconds
+ running.timeLeft=mission.timeLeft
+ if ((tonumber(running.started) or 0)==0) then running.started = time() - GarrisonTimeStringToSeconds(mission.timeLeft) end
+ local mission=cache.missions[missionID]
+ running.followers={}
+ for i=1,mission.numFollowers do
+ running.followers[i]=mission.followers[i]
+ dbcache.runningIndex[mission.followers[i]]=missionID
+ end
+ end
+ del(t)
+end
+function addon:UpdateRunningMissionCache(missionId,destroy)
+end
+--[[
+{
+ missionID=0,
+ counters={}, calculated
+ countered={ calculated
+ ["*"]={}
+ },
+ counterers={ calculated
+ ["*"]={}
+ },
+ slots={ calculated
+ ["*"]=0
+ },
+ numFollowers=0, -> GetMissionMaxFollowers()
+ name="<newmission>", GetMissionName
+ basePerc=0, GetPartyMissionInfo
+ durationSeconds=0, GePartyMissionInfo()
+ rewards={},
+ level=0,
+ iLevel=0,
+ rank=0,
+ locPrefix=false
+}
+--]]
function addon:BuildMissionCache(id,data)
if (not dbcache.seen[id]) then
dbcache.seen[id]=time()
end
local mission=cache.missions[id]
if (mission.name=="<newmission>") then
-
- for k,v in pairs(mission) do
- if (data[k]) then mission[k]=data[k]end
+ if (not data) then
+ mission.name=G.GetMissionName(id)
+ mission.numFollowers=G.GetMissionMaxFollowers(id)
+ mission.durationSeconds=select(5,G.GetMissionTimers(id))
+ else
+ mission.name=data.name
+ mission.numFollowers=data.numFollowers
+ mission.durationSeconds=data.durationSeconds
end
mission.rank=mission.level < 100 and mission.level or mission.iLevel
mission.xp=true
mission.resources=false
- for k,v in pairs(data.rewards) do
+ for k,v in pairs(G.GetMissionRewardInfo(id)) do
if (not v.followerXP) then mission.xp=false end
- if (v.currencyID and v.currencyID==824) then mission.resource=false end
+ if (v.currencyID and v.currencyID==GARRISON_CURRENCY) then mission.resource=false end
end
- local _,xp,type,typeDesc,typeIcon,_,_,enemies=G.GetMissionInfo(id)
+ local _,xp,type,typeDesc,typeIcon,locPrefix,_,enemies=G.GetMissionInfo(id)
+ mission.locPrefix=locPrefix
if (not type) then
- xprint(true,"No type",id,data.name)
+--@debug@
+ print(true,"No type",id,data.name)
+--@end-debug@
else
self.db.global.types[type]={name=typeDesc,icon=typeIcon}
end
@@ -1220,8 +1189,6 @@ function addon:BuildMissionCache(id,data)
tinsert(slots,{name=TYPE,icon=typeIcon})
end
end
- self:FillCounters(id,mission)
- --self:MatchMaker(id,mission)
mission.basePerc=select(4,G.GetPartyMissionInfo(id))
end
function addon:SetDbDefaults(default)
@@ -1235,10 +1202,27 @@ function addon:CreatePrivateDb()
{
profile={
seen={},
+ ignored={
+ ["*"]={
+ }
+ },
+ totallyignored={
+ },
history={
['*']={
}
- } }
+ },
+ running={
+ ["*"]={
+ followers={},
+ started=0,
+ duration=0
+ }
+ },
+ runningIndex={
+ ["*"]=0
+ }
+ }
},
true)
self.private=self:RegisterDatabase(
@@ -1246,31 +1230,22 @@ function addon:CreatePrivateDb()
{
profile={
missions={
- ["*"]={
- missionID=0,
- counters={},
- countered={
- ["*"]={}
- },
- counterers={
- ["*"]={}
- },
- slots={
- ["*"]=0
- },
- numFollowers=0,
- name="<newmission>",
- basePerc=0,
- durationSeconds=0,
- rewards={},
- level=0,
- iLevel=0,
- rank=0,
- locPrefix=false
+ ["*"]={
+ counters={},
+ slots={},
+ missionID=0,
+ numFollowers=0,
+ name="<newmission>",
+ basePerc=0,
+ durationSeconds=0,
+ level=0,
+ iLevel=0,
+ rank=0,
+ locPrefix=false
+ }
}
}
}
- }
,
true)
dbcache=self.privatedb.profile
@@ -1283,44 +1258,6 @@ function addon:wipe(i)
DevTools_Dump(i)
privatedb:ResetDB()
end
-function addon:OnInitialized()
---@debug@
- LoadAddOn("Blizzard_DebugTools")
- self:DebugEvents()
---@end-debug@
- self:CreatePrivateDb()
- if (self.db.char.missionsCache) then
- self.db.char.missionsCache=nil
- for i,v in pairs(self.db.char.seen) do
- dbcache.seen[i]=v
- end
- self.db.char.seen=nil
- end
- self:RegisterEvent("GARRISON_MISSION_NPC_CLOSED",function(...) print(...) GCF:Hide() end)
- self:RegisterEvent("GARRISON_MISSION_NPC_OPENED",print)
- self:RegisterEvent("GARRISON_MISSION_STARTED")
- self:RegisterEvent("GARRISON_MISSION_BONUS_ROLL_COMPLETE")
- self:SafeHookScript("GarrisonMissionFrame","OnShow","SetUp",true)
- self:AddToggle("MOVEPANEL",true,L["Unlock Garrison Panel"])
- self:AddToggle("IGM",true,IGNORE_UNAIVALABLE_FOLLOWERS,IGNORE_UNAIVALABLE_FOLLOWERS_DETAIL)
- self:AddToggle("IGP",true,L["Ignore maxed followers for xp only one follower missions"])
- print("Booting movepanel",self:GetBoolean("MOVEPANEL"))
---@debug@
- --Only Used for development
- self:RegisterEvent("GARRISON_MISSION_LIST_UPDATE",print)
- self:RegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE",print) --This event is quite useless, fires too often
- self:RegisterEvent("GARRISON_FOLLOWER_XP_CHANGED",print)
- self:RegisterEvent("GARRISON_FOLLOWER_ADDED",print)
- self:RegisterEvent("GARRISON_FOLLOWER_REMOVED",print)
- self:RegisterEvent("GARRISON_MISSION_BONUS_ROLL_LOOT",print)
- self:RegisterEvent("GARRISON_MISSION_FINISHED",print)
- self:RegisterEvent("GARRISON_MISSION_COMPLETE_RESPONSE",print)
- self:RegisterEvent("GARRISON_MISSION_BONUS_ROLL_COMPLETE",print)
- self:RegisterEvent("GARRISON_UPDATE",print)
- self:RegisterEvent("GARRISON_USE_PARTY_GARRISON_CHANGED",print)
---@end-debug@
- return true
-end
function addon:WipeMission(missionID)
cache.missions[missionID]=nil
counters[missionID]=nil
@@ -1330,97 +1267,146 @@ function addon:WipeMission(missionID)
end
-function addon:GARRISON_MISSION_NPC_CLOSED(event,...)
+
+---
+--@param #string event GARRISON_MISSION_NPC_OPENED
+-- Fires after GarrisonMissionFrame OnShow. Pretty useless
+
+function addon:EventGARRISON_MISSION_NPC_OPENED(event,...)
+--@debug@
+ print(event,...)
+--@end-debug@
+ GCF:Show()
+end
+function addon:EventGARRISON_MISSION_NPC_CLOSED(event,...)
--@debug@
print(event,...)
--@end-debug@
GCF:Hide()
end
-function addon:GARRISON_MISSION_STARTED(event,missionID)
+---
+--@param #string event GARRISON_MISSION_STARTED
+--@param #number missionID Numeric mission id
+-- After this events fires also GARRISON_MISSION_LIST_UPDATE and GARRISON_FOLLOWER_LIST_UPDATE
+
+function addon:EventGARRISON_MISSION_STARTED(event,missionID,...)
--@debug@
- print(event,missionID)
+ print(event,missionID,...)
--@end-debug@
+-- running={
+-- ["*"]={
+-- followers={},
+-- started=0,
+-- duration=0
+-- }
+-- },
+ dbcache.running[missionID].started=time()
+ dbcache.running[missionID].duration=select(2,G.GetPartyMissionInfo(missionID))
+ wipe(dbcache.running[missionID].followers)
for i=1,3 do
local m=parties[missionID].members[i]
if (m) then
- onMission[m]=missionID
+ tinsert(dbcache.running.followers,m)
+ dbcache.runningIndex[m]=missionID
end
end
dbcache.seen[missionID]=nil
- wipe(counters)
- wipe(parties)
- self:RefreshMissions(false)
+ counters[missionID]=nil
+ parties[missionID]=nil
+ self:BuildMissionsCache(true,true)
+end
+---
+--@param #string event GARRISON_MISSION_FINISHED
+--@param #number missionID Numeric mission id
+-- Thsi is just a notification, nothing get really changed
+-- GetMissionINfo still returns data
+-- but GetPartyMissionInfo does no longer return followers.
+-- Also timeleft is false
+--
+
+function addon:EventGARRISON_MISSION_FINISHED(event,missionID,...)
+--@debug@
+ print(event,missionID,...)
+ DevTools_Dump(G.GetPartyMissionInfo(missionID))
+--@end-debug@
end
-function addon:GARRISON_MISSION_BONUS_ROLL_COMPLETE(event,missionID,completed,success)
+
+function addon:EventGARRISON_MISSION_BONUS_ROLL_COMPLETE(event,missionID,completed,success)
--@debug@
- print(event,missionID)
+ print(event,missionID,completed,success)
--@end-debug@
- dbcache.seen[missionID]=nil
- tinsert(dbcache.history[missionID],{completed=time(),result=100,success=success})
- wipe(parties)
- wipe(counters)
end
-function addon:GARRISON_MISSION_COMPLETE_RESPONSE(event,missionID,completed,success)
+---
+--@param #number missionID mission identifier
+--@param #boolean completed I suppose it always be true...
+--@oaram #boolean success Mission was succesfull
+--Mission complete Sequence is:
+--GARRISON_MISSION_COMPLETE_RESPONSE
+--GARRISON_MISSION_BONUS_ROLL_COMPLETE missionID true
+--GARRISON_FOLLOWER_XP_CHANGED (1 or more times
+--GARRISON_MISSION_NPC_OPENED ??
+--GARRISON_MISSION_BONUS_ROLL_COMPLETE missionID nil
+--
+function addon:EventGARRISON_MISSION_COMPLETE_RESPONSE(event,missionID,completed,success)
--@debug@
- print(event,missionID)
+ xprint(event,missionID)
--@end-debug@
+ dbcache.history[missionID][time()]={result=100,success=success}
+ dbcache.seen[missionID]=nil
+ dbcache.running[missionID]=nil
dbcache.seen[missionID]=nil
- tinsert(dbcache.history[missionID],{completed=time(),result=100,success=success})
- wipe(parties)
- wipe(counters)
+ counters[missionID]=nil
+ parties[missionID]=nil
end
function addon:OptionOnClick(checkbox)
self:SetBoolean(checkbox.flag,checkbox:GetChecked())
+ trace(checkbox.flag)
self:Trigger(checkbox.flag)
end
-function addon:Option(obj,rel,name,text)
- local b=CreateFrame("CheckButton",nil,obj,"UICheckButtonTemplate")
- b.text:SetText(text)
- b.flag=name
- self:HookScript(b,"OnCLick","OptionOnClick")
- obj[name]=b
- b:SetChecked(self:GetBoolean(name))
- switch(name,self:GetBoolean(name))
- b:SetPoint("LEFT",rel,"RIGHT",10,0)
- b:Show()
- return b.text
-end
-local elapsed=0
-local interval=0.05
+-----------------------------------------------------
+-- Coroutines data and clock management
+-----------------------------------------------------
+local coroutines={
+ Timers={
+ func=false,
+ elapsed=60,
+ interval=60,
+ paused=false
+ },
+}
+
local lastmin=0
-function addon:Clock(frame,ts)
- elapsed=elapsed+ts
- if (elapsed > interval ) then
- for k,d in pairs(coroutines) do
- local co=coroutines[k]
- if (not co.func) then
- co.func=self["Generate"..k.."Periodic"](self)
- if (type(co.func) ~="function") then
+-- Keeping it as a nice example of coroutine management.. but not using it anymore
+function addon:Clock()
+ collectgarbage("step")
--@debug@
- print("Periodic inesistente",k)
---@end-debug@
- co.func=function() end
- end
- end
- co.elapsed=co.elapsed+elapsed
- if not co.paused and co.elapsed > co.interval then
- co.elapsed=0
- co.paused=co.func(self)
+ for k,d in pairs(coroutines) do
+ local co=coroutines[k]
+ if (not co.func) then
+ co.func=self["Generate"..k.."Periodic"](self)
+ if (type(co.func) ~="function") then
+ co.func=function() end
end
end
- elapsed=0
+ co.elapsed=co.elapsed+1
+ if not co.paused and co.elapsed > co.interval then
+ co.elapsed=0
+ co.paused=co.func(self)
+ end
end
+--@end-debug@
+--@debug@
local h,m=GetGameTime()
if (m~=lastmin) then
lastmin=m
UpdateAddOnCPUUsage()
- print("MP",GetAddOnCPUUsage("MasterPlan"))
- print("GC",GetAddOnCPUUsage("GarrisonCommander"))
+ UpdateAddOnMemoryUsage()
+ print("GC Usage",GetAddOnCPUUsage("GarrisonCommander"),GetAddOnMemoryUsage("GarrisonCommander"))
end
+--@end-debug@
end
function addon:ActivateButton(button,OnClick,Tooltiptext,persistent)
- print("Activting")
button:SetScript("OnClick",function(...) self[OnClick](self,...) end )
if (Tooltiptext) then
button.tooltip=Tooltiptext
@@ -1439,7 +1425,6 @@ end
function addon:Shrink(button)
local f=button.Toggle
local name=f:GetName() or "Unnamed"
- print("Toggling",name)
if (f:GetHeight() > 200) then
f.savedHeight=f:GetHeight()
f:SetHeight(200)
@@ -1455,7 +1440,7 @@ function addon:ShowHelpWindow(button)
local r=AG:Create("Label")
r:SetFullHeight(true)
r:SetFullWidth(true)
- r:SetFontObject(GameFontNormalLarge2)
+ r:SetFontObject(GameFontNormal)
r:SetText([[
Garrison Commander enhancec standard Garrison UI by adding a Menu header and a secondary list of mission button to the right of the standard list.
Secondary button list:
@@ -1479,41 +1464,141 @@ those given by MasterPlan because MasterPlan clashes with GarrisonCommander.
]])
helpwindow:AddChild(r)
helpwindow:SetTitle("Garrison Commander Help")
+ helpwindow:SetPoint("TOPLEFT",button,"TOPRIGHT",0,0)
+ helpwindow:Show()
+ return
end
if (helpwindow:IsShown()) then
helpwindow:Hide()
else
- helpwindow:ClearAllPoints()
- helpwindow:SetPoint("CENTER")
helpwindow:Show()
end
end
function addon:Toggle(button)
local f=button.Toggle
local name=f:GetName() or "Unnamed"
- print("Toggling",name)
- if (f:IsShown()) then print("Hiding",name) f:Hide() else print("Showing",name) f:Show() end
+ if (f:IsShown()) then f:Hide() else f:Show() end
if (button.SetChecked) then
button:SetChecked(f:IsShown())
end
end
+-- Unused, experimenting with acegui
+local function GFC_Constructor()
+ local widget=setmetatable({},{__index=AceGUI:Create("SimpleGroup")})
+ function widget:DrawOn(frame,l,r)
+ self.frame:ClearAllPoints()
+ self.frame:SetPoint("TOPLEFT",frame,"TOPLEFT",l,0)
+ self.frame:SetPoint("BOTTOMRIGHT",frame,"TOPRIGHT",r,0)
+ end
+ function widget:OnRelease()
+ self.frame:ClearAllPoints()
+ end
+ if (false) then
+ AceGUI:RegisterWidgetType("GarrisonCommanderHeader",GFC_Constructor,1)
+ local layer=AceGUI:Create("GarrisonCommanderHeader")
+ layer:DrawOn(GCF)
+ layer:SetLayout("flow")
+ LibStub("AceConfigDialog-3.0"):Open(me,layer)
+ end
+ return widget
+end
+function addon:Select(obj,rel,name,text)
+ local b=CreateFrame("Frame","MSORT",obj,"GarrisonCommanderMenu")
+ b.Text:SetFormattedText("%s: %s",C("Sort: ","Yellow"),C("Not yet implemented","Red"))
+ b.menu={
+ {text="Not yet implemented",notCheckable=true,notClickable=true},
+ {text="Example",func=print,arg1="arg1",arg2="arg2"}
+ }
+ b:SetPoint("LEFT",rel,"RIGHT",10,0)
+ b:SetWidth(400)
+ b:SetHeight(20)
+ b:Show()
+ return b
+end
+function addon:Option(obj,rel,name,text)
+ local b=CreateFrame("CheckButton",nil,obj,"UICheckButtonTemplate")
+ b.text:SetText(text)
+ b.flag=name
+ b:SetScript("OnCLick",function(...) self:OptionOnClick(...) end)
+ obj[name]=b
+ b:SetChecked(self:GetBoolean(name))
+ switch(name,self:GetBoolean(name))
+ b:SetPoint("LEFT",rel,"RIGHT",10,0)
+ b:Show()
+ return b.text
+end
+function addon:Menu(obj,rel,name,text,table)
+end
+function addon:CreateOptionsLayer(...)
+ local o=AceGUI:Create("SimpleGroup") -- a transparent frame
+ o:SetLayout("Flow")
+ o:SetCallback("OnClose",function(widget) widget.frame:SetScale(1.0) widget:Release() end)
+ for i=1,select('#',...) do
+ local flag=select(i,...)
+ local info=self:GetVarInfo(flag)
+ if (info) then
+ local data={option=info}
+ local widget
+ if (info.type=="toggle") then
+ widget=AceGUI:Create("CheckBox")
+ local value=self:GetBoolean(flag)
+ widget:SetValue(value)
+ local color=value and "Green" or "Silver"
+ widget:SetLabel(C(info.name,color))
+ elseif(info.type=="select") then
+ widget=AceGUI:Create("Dropdown")
+ widget:SetValue(self:GetVar(flag))
+ widget:SetLabel(info.name)
+ widget:SetText(info.values[self:GetVar(flag)])
+ widget:SetList(info.values)
+ end
+ widget:SetCallback("OnValueChanged",function(widget,event,value)
+ if (type(value=='boolean')) then
+ local color=value and "Green" or "Silver"
+ widget:SetLabel(C(info.name,color))
+ end
+ self[info.set](self,data,value)
+ end)
+ widget:SetCallback("OnEnter",function(widget)
+ GameTooltip:SetOwner(widget.frame,"ANCHOR_CURSOR")
+ GameTooltip:AddLine(info.desc)
+ GameTooltip:Show()
+ end)
+ widget:SetCallback("OnLeave",function(widget)
+ GameTooltip:FadeOut()
+ end)
+ o:AddChildren(widget)
+ end
+ end
+ _G.TEST=o
+ local frame=setmetatable({},{__index=o})
+ function frame:Show() self.frame:Show() end
+ return frame
+end
function addon:Options()
- print("Loading options setters")
+ -- Main Garrison Commander Header
local base=CreateFrame("Frame",nil,UIParent,"GarrisonCommanderTitle")
GCF=base
GCF:SetWidth(BIGSIZEW)
GCF:SetPoint("TOP",UIParent,0,-60)
base:SetHeight(40)
base:EnableMouse(true)
- self:RawHookScript(base,"OnUpdate","Clock")
GCF:SetMovable(true)
GCF:RegisterForDrag("LeftButton")
- GCF:SetScript("OnDragStart",function(frame)frame:StartMoving() end)
+ GCF:SetScript("OnDragStart",function(frame)if (self:GetBoolean("MOVEPANEL")) then frame:StartMoving() end end)
GCF:SetScript("OnDragStop",function(frame) frame:StopMovingOrSizing() end)
+ -- Adding a signture
local rel=base.Signature
- rel=self:Option(base,rel,'IGM',L["Ignore busy followers"])
- rel=self:Option(base,rel,'IGP',L["Ignore maxed followers for xp only one follower missions"])
- rel=self:Option(base,rel,'MOVEPANEL',L["Unlock Panel"])
+ GCF.Menu=self:CreateOptionsLayer('IGM','IGP','MOVEPANEL','MSORT')
+ GCF.Menu:SetParent(GCF)
+ GCF.Menu.frame:SetScale(0.6)
+ GCF.Menu:SetPoint("TOPLEFT",base.Signature,"TOPRIGHT",10,10)
+ GCF.Menu:SetPoint("BOTTOMRIGHT",base,"BOTTOMRIGHT",-30,0)
+ GCF.Menu:Show()
+ --rel=self:Option(base,rel,'IGM',L["Ignore busy followers"])
+ --rel=self:Option(base,rel,'IGP',L["Try not to use epic quality level 100 followers"])
+ --rel=self:Option(base,rel,'MOVEPANEL',L["Unlock Panel"])
+ --rel=self:Select(base,rel,'MSORT',"Pippo")
--HelpButton
local h=CreateFrame("Button",nil,base,"UIPanelCloseButton")
h:SetFrameLevel(999)
@@ -1536,6 +1621,19 @@ function addon:Options()
self:ActivateButton(h,"Shrink",L["Click to toggle Garrison Mission Frame"])
GCF.gcHIDE=h
self:Trigger("MOVEPANEL")
+ -- Mission list on follower panels
+ local ml=CreateFrame("Frame","GCFMissions",GMFFollowers,"GarrisonCommanderFollowerMissionList")
+ ml:SetPoint("TOPLEFT",GMFFollowers,"TOPRIGHT")
+ ml:SetPoint("BOTTOMLEFT",GMFFollowers,"BOTTOMRIGHT")
+ --ml:SetWidth(450)
+ ml:Show()
+ GCFMissions=ml
+ local fs=GMFFollowers:CreateFontString(nil, "BACKGROUND", "GameFontNormalHugeBlack")
+ fs:SetPoint("TOPLEFT",GMFFollowers,"TOPRIGHT")
+ fs:SetText(AVAILABLE)
+ fs:SetWidth(250)
+ fs:Show()
+ GCFBusyStatus=fs
self.Options=function() end
end
@@ -1561,44 +1659,6 @@ end
function addon:IsMissionPage()
return GMF:IsShown() and GMFMissionPage:IsShown() and GMFFollowers:IsShown()
end
-function addon:SafeHookScript(frame,hook,method,postHook)
- local name="Unknown"
- if (type(frame)=="string") then
- name=frame
- frame=_G[frame]
- else
- if (frame and frame.GetName) then
- name=frame:GetName()
- end
- end
- if (frame) then
- if (method) then
- if (postHook) then
- self:SecureHookScript(frame,hook,method)
---@debug@
- print("PostHooked",name,hook)
---@end-debug@
- else
- self:HookScript(frame,hook,method)
---@debug@
- print("PreHooked",name,hook)
---@end-debug@
- end
- else
- if (postHook) then
- self:SecureHookScript(frame,hook,function(...) self:ScriptTrace(name,hook,...) end)
- print("DummyPostHooked:",name,hook)
- else
- self:HookScript(frame,hook,function(...) self:ScriptTrace(name,hook,...) end)
- print("DummyPreHooked:",name,hook)
- end
- end
---@debug@
- else
- print(C("Attempted hook for non existent:","red"),name,hook)
---@end-debug@
- end
-end
function addon:_AddPerc(b,...)
if (b and b.info and b.info.missionID and b.info.missionID ) then
if (GMF.MissionTab.MissionList.showInProgress) then
@@ -1668,14 +1728,32 @@ function addon:_AddPerc(b,...)
b.ProgressHidden=false
end
end
-function addon:GarrisonMissionFrame_HideCompleteMissions()
- self:GrowPanel(true)
- self:RefreshMissions("MissionCompleteClose")
+function addon:HookedGarrisonMissionFrame_HideCompleteMissions()
+ self:BuildMissionsCache(true,true)
+end
+function addon:HookedGarrisonFollowerTooltipTemplate_SetGarrisonFollower(...)
+ local h=GarrisonFollowerTooltip:GetHeight()
+ local fs=GarrisonFollowerTooltip.fs
+ if (not fs) then
+ fs=GarrisonFollowerTooltip:CreateFontString(nil, "BACKGROUND", "GameFontNormal")
+ GarrisonFollowerTooltip.fs=fs
+ fs:SetWidth(0)
+ fs:SetText(L["Click to see available missions"])
+ fs:SetTextColor(0,1,0)
+ fs:SetPoint("BOTTOMLEFT",GarrisonFollowerTooltip,"BOTTOMLEFT",5,5)
+ fs:SetPoint("BOTTOMRIGHT",GarrisonFollowerTooltip,"BOTTOMRIGHT",-5,5)
+ fs:SetHeight(15)
+ GarrisonFollowerTooltip:SetHeight(h+15)
+ end
+ fs:Show()
end
-function addon:GarrisonFollowerListButton_OnClick(frame,button)
- if (button=="LeftButton" and not GarrisonMissionFrame.FollowerTab.Model:IsShown()) then
+function addon:HookedGarrisonFollowerListButton_OnClick(frame,button)
+--@debug@
+ trace("Click",button,GarrisonMissionFrame.FollowerTab.Model:IsShown())
+--@end-debug@
+ if (button=="LeftButton" and GarrisonMissionFrame.FollowerTab.FollowerID ~= frame.info.followerID) then
if (frame.info.isCollected) then
- self:GarrisonFollowerPage_ShowFollower(frame.info,id)
+ self:HookedGarrisonFollowerPage_ShowFollower(frame.info,frame.info.followerID)
end
end
end
@@ -1691,13 +1769,14 @@ function addon:FillMissionButton(button)
else
button.Summary:SetFormattedText(PARENS_TEMPLATE, mission.duration);
end
- if ( button.Title:GetWidth() + button.Summary:GetWidth() + 8 < 275 - mission.numRewards * 65 ) then
+ local tw=button:GetWidth() -165
+ if ( button.Title:GetWidth() + button.Summary:GetWidth() + 8 < tw - mission.numRewards * 65 ) then
button.Title:SetPoint("LEFT", 165, 0);
button.Summary:ClearAllPoints();
button.Summary:SetPoint("BOTTOMLEFT", button.Title, "BOTTOMRIGHT", 8, 0);
else
button.Title:SetPoint("LEFT", 165, 10);
- button.Title:SetWidth(275 - mission.numRewards * 65);
+ button.Title:SetWidth(tw - mission.numRewards * 65);
button.Summary:ClearAllPoints();
button.Summary:SetPoint("TOPLEFT", button.Title, "BOTTOMLEFT", 0, -4);
end
@@ -1738,18 +1817,65 @@ function addon:FillMissionButton(button)
button.Overlay:Hide();
end
button.MissionType:SetAtlas(mission.typeAtlas);
- GarrisonMissionButton_SetRewards(button, mission.rewards, mission.numRewards);
+ self.ClonedGarrisonMissionButton_SetRewards(button, mission.rewards, mission.numRewards);
button:Show();
end
-function addon:GarrisonFollowerPage_ShowFollower(frame,followerID)
- local MAXMISSIONS=6
- local MINPERC=60
+-- Ripped bleeding from Blizzard code. In mini buttons I cant suffer MP staff
+function addon:ClonedGarrisonMissionButton_SetRewards(rewards, numRewards)
+ if (numRewards > 0) then
+ local index = 1;
+ for id, reward in pairs(rewards) do
+ if (not self.Rewards[index]) then
+ self.Rewards[index] = CreateFrame("Frame", nil, self, "GarrisonMissionListButtonRewardTemplate");
+ self.Rewards[index]:SetPoint("RIGHT", self.Rewards[index-1], "LEFT", 0, 0);
+ end
+ local Reward = self.Rewards[index];
+ Reward.Quantity:Hide();
+ Reward.itemID = nil;
+ Reward.currencyID = nil;
+ Reward.tooltip = nil;
+ if (reward.itemID) then
+ Reward.itemID = reward.itemID;
+ GarrisonMissionFrame_SetItemRewardDetails(Reward);
+ if ( reward.quantity > 1 ) then
+ Reward.Quantity:SetText(reward.quantity);
+ Reward.Quantity:Show();
+ end
+ else
+ Reward.Icon:SetTexture(reward.icon);
+ Reward.title = reward.title
+ if (reward.currencyID and reward.quantity) then
+ if (reward.currencyID == 0) then
+ Reward.tooltip = GetMoneyString(reward.quantity);
+ else
+ Reward.currencyID = reward.currencyID;
+ Reward.Quantity:SetText(reward.quantity);
+ Reward.Quantity:Show();
+ end
+ else
+ Reward.tooltip = reward.tooltip;
+ end
+ end
+ Reward:Show();
+ index = index + 1;
+ end
+ end
+
+ for i = (numRewards + 1), #self.Rewards do
+ self.Rewards[i]:Hide();
+ end
+end
+
+local Busystatusmessage
+function addon:HookedGarrisonFollowerPage_ShowFollower(frame,followerID)
local i=0
+ if (not self:IsFollowerList()) then return end
+ if (not GCFMissions.Missions) then GCFMissions.Missions={} end
+ if (not Busystatusmessage) then Busystatusmessage=C(BUSY_MESSAGE,"Red)") end
-- frame has every info you can need on a follower, but here I dont really need them, maybe just counters
--DevTools_Dump(table.Counters)
local followerName=self:GetFollowerData(followerID,'name')
- local dbg=followerName=="Qiana Moonshadow"
repeat -- a poor man goto
if (type(frame.followerID)=="number") then
GCFBusyStatus:SetText(NOT_COLLECTED)
@@ -1765,20 +1891,24 @@ function addon:GarrisonFollowerPage_ShowFollower(frame,followerID)
local m1,m2,m3,perc,numFollowers=nil,nil,nil,0,""
if (status ~= AVAILABLE and status ~= GARRISON_FOLLOWER_IN_PARTY) then
if (status==GARRISON_FOLLOWER_ON_MISSION) then
- local missionID=onMission[followerID]
+ local missionID=dbcache.runningIndex[followerID]
+ if (not missionID) then return end
list=GMF.MissionTab.MissionList.inProgressMissions
m1=followerID
perc=select(4,G.GetPartyMissionInfo(missionID))
for j=1,#list do
index[list[j].missionID]=j
end
+ numFollowers=#list[index[missionID]].followers
tinsert(partyIndex,-missionID)
- GCFBusyStatus:SetText("")
+ GCFBusyStatus:SetText(GARRISON_FOLLOWER_ON_MISSION)
else
GCFBusyStatus:SetText(self:GetFollowerStatus(followerID,false,true)) -- no time, colored
end
+ GCFBusyStatus:SetTextColor(C.Red())
+
else
- GCFBusyStatus:SetText("")
+ GCFBusyStatus:SetText(Busystatusmessage)
list=GMF.MissionTab.MissionList.availableMissions
for j=1,#list do
index[list[j].missionID]=j
@@ -1788,8 +1918,18 @@ function addon:GarrisonFollowerPage_ShowFollower(frame,followerID)
end
table.sort(partyIndex,function(a,b) return parties[a].perc > parties[b].perc end)
end
+ self:FillFollowerButton(GCFMissions.Header,followerID)
+ -- Scanning mission list
for z = 1,#partyIndex do
local missionID=partyIndex[z]
+ if not(tonumber(missionID)) then
+--@debug@
+ print("missionid not a number",missionID)
+ self:Dump("partyIndex table",partyIndex)
+--@end-debug@
+ perc=-1 --(lowering perc to ignore this mission
+ end
+
if (missionID>0) then
local p=parties[missionID]
m1,m2,m3,perc=p.members[1],p.members[2],p.members[3],tonumber(p.perc) or 0
@@ -1809,15 +1949,20 @@ function addon:GarrisonFollowerPage_ShowFollower(frame,followerID)
local panel=GCFMissions.Missions[i]
if (not panel) then
panel=CreateFrame("Button",nil,GCFMissions,"GarrisonCommanderMissionListButtonTemplate")
- panel:SetPoint("TOPLEFT",GCFMissions.Missions[i-1],"BOTTOMLEFT")
- panel:SetPoint("TOPRIGHT",GCFMissions.Missions[i-1],"BOTTOMRIGHT")
+ if (i==1) then
+ panel:SetPoint("TOPLEFT",GCFMissions.Header,"BOTTOMLEFT")
+ else
+ panel:SetPoint("TOPLEFT",GCFMissions.Missions[i-1],"BOTTOMLEFT")
+ panel:SetPoint("TOPRIGHT",GCFMissions.Missions[i-1],"BOTTOMRIGHT")
+ end
tinsert(GCFMissions.Missions,panel)
--Creo una riga nuova
+ panel:SetScale(0.6)
+ panel.fromFollowerPage=true
+ panel.LocBG:SetPoint("LEFT")
end
panel.info=mission
panel.id=index[missionID]
- panel.fromFollowerPage=true
- panel.LocBG:SetPoint("LEFT")
self:FillMissionButton(panel)
local q=self:GetDifficultyColor(perc)
panel.Percent:SetFormattedText(GARRISON_MISSION_PERCENT_CHANCE,perc)
@@ -1830,94 +1975,182 @@ function addon:GarrisonFollowerPage_ShowFollower(frame,followerID)
del(partyIndex)
del(index)
until true
+ if (i>0) then
+ GCFBusyStatus:SetPoint("TOPLEFT",GCFMissions.Missions[i],"BOTTOMLEFT",0,-5)
+ else
+ GCFBusyStatus:SetPoint("TOPLEFT",GCFMissions.Header,"BOTTOMLEFT",0,-5)
+ end
i=i+1
for x=i,#GCFMissions.Missions do GCFMissions.Missions[x]:Hide() end
end
+---
+--Initial one time setup
function addon:SetUp(...)
+--@debug@
+ print("Setup")
+--@end-debug@
SIZEV=GMF:GetHeight()
self:Options()
self:StartUp()
end
+---
+-- Additional setup
+-- This method is called every time garrison mission panel is open because
+-- when it closes, I remove most of used hooks
function addon:StartUp(...)
+--@debug@
+ print("Startup")
+--@end-debug@
self:Unhook(GMF,"OnShow")
self:PermanentEvents()
- GCF:Show()
- GMF:ClearAllPoints()
- GMF:SetPoint("TOPLEFT",GCF,"BOTTOMLEFT")
- GMF:SetPoint("TOPRIGHT",GCF,"BOTTOMRIGHT")
- GMFRewardSplash:ClearAllPoints()
- GMFRewardSplash:SetPoint("TOPLEFT",GCF,"BOTTOMLEFT")
- GMFRewardSplash:SetPoint("TOPRIGHT",GCF,"BOTTOMRIGHT")
- GMFRewardPage:ClearAllPoints()
- GMFRewardPage:SetPoint("TOPLEFT",GCF,"BOTTOMLEFT")
- GMFRewardPage:SetPoint("TOPRIGHT",GCF,"BOTTOMRIGHT")
- if (not GCFMissions) then
- local ml=CreateFrame("Frame","GCFMissions",GMFFollowers,"GarrisonCommanderFollowerMissionList")
- ml:SetPoint("TOPLEFT",GMFFollowers,"TOPRIGHT")
- ml:SetPoint("BOTTOMLEFT",GMFFollowers,"BOTTOMRIGHT")
- ml:SetWidth(450)
- ml:Show()
- GCFMissions=ml
- local fs=GMFFollowers:CreateFontString(nil, "BACKGROUND", "GameFontNormalHugeBlack")
- fs:SetPoint("TOPLEFT",GMFFollowers,"TOPRIGHT")
- fs:SetPoint("BOTTOMLEFT",GMFFollowers,"BOTTOMRIGHT")
- fs:SetText(AVAILABLE)
- fs:SetWidth(450)
- fs:Show()
- GCFBusyStatus=fs
- end
- self:GrowPanel(self:GetBoolean("BIGPANEL"))
- self:SecureHook("GarrisonMissionFrame_CheckCompleteMissions",function(...) print("GarrisonMissionFrame_CheckCompleteMissions",...) end)
- self:SecureHook("GarrisonMissionButton_AddThreatsToTooltip",function(id) self:TooltipAdder(id) end)
- self:SecureHook("GarrisonMissionButton_SetRewards","RenderButton")
- self:SecureHook("GarrisonFollowerListButton_OnClick")--,function(...) print("GarrisonFollowerListButton_OnClick",...) end)
- self:SecureHook("GarrisonFollowerPage_ShowFollower")--,function(...) print("GarrisonFollowerPage_ShowFollower",...) end)
- self:SecureHook("GarrisonMissionButton_OnClick")
- self:HookScript(GCF,"OnHide","CleanUp")
- -- Forcing refresh when needed without possibly disrupting Blizzard Logic
- self:SecureHook("GarrisonMissionFrame_HideCompleteMissions") -- Mission reward completed
- self:SafeHookScript(GMFMissions,"OnShow",function (f,...) print(f:GetName(),'OnShow') self:GrowPanel(true) end )
- self:SafeHookScript(GMFFollowers,"OnShow",function (f,...) print(f:GetName(),'OnShow') self:GrowPanel(false) end )
- self:SecureHook("GarrisonMissionPage_ShowMission","UpdateMissionPage")
- self:BuildMissionsCache()
+ self:GrowPanel()
+ self:SafeSecureHook("GarrisonMissionButton_OnClick","OnClick_GarrisonMissionButton")
+ self:SafeSecureHook("GarrisonMissionFrame_CheckCompleteMissions")
+ self:SafeSecureHook("GarrisonMissionButton_AddThreatsToTooltip")
+ self:SafeSecureHook("GarrisonMissionButton_SetRewards")
+ self:SafeSecureHook("GarrisonFollowerListButton_OnClick")--,function(...) xprint("GarrisonFollowerListButton_OnClick",...) end)
+ self:SafeSecureHook("GarrisonFollowerPage_ShowFollower")--,function(...) xprint("GarrisonFollowerPage_ShowFollower",...) end)
+ self:SafeSecureHook("GarrisonFollowerTooltipTemplate_SetGarrisonFollower")
+ self:SafeSecureHook("GarrisonMissionFrame_HideCompleteMissions") -- Mission reward completed
+ self:SafeSecureHook("GarrisonMissionPage_ShowMission")
+ self:SafeSecureHook("GarrisonMissionList_UpdateMissions")
+ self:SafeHookScript(GMFMissions,"OnShow")--,"GrowPanel")
+ self:SafeHookScript(GMFFollowers,"OnShow")--,"GrowPanel")
+ self:SafeHookScript(GCF,"OnHide","CleanUp",true)
+ self:ScheduleRepeatingTimer("Clock",1)
+ self:BuildMissionsCache(true,true)
+ self:BuildRunningMissionsCache()
GarrisonMissionList_UpdateMissions();
end
+-- probably not really needed, haven seen yet them firing out of garrison
function addon:PermanentEvents()
- self:RegisterEvent("GARRISON_MISSION_COMPLETE_RESPONSE")
- self:RegisterEvent("GARRISON_MISSION_STARTED")
- self:RegisterEvent("GARRISON_MISSION_BONUS_ROLL_COMPLETE")
- self:RegisterEvent("GARRISON_MISSION_NPC_CLOSED")
+ self:SafeRegisterEvent("GARRISON_MISSION_COMPLETE_RESPONSE")
+ self:SafeRegisterEvent("GARRISON_MISSION_STARTED")
+ self:SafeRegisterEvent("GARRISON_MISSION_BONUS_ROLL_COMPLETE")
+ self:SafeRegisterEvent("GARRISON_MISSION_NPC_CLOSED")
+ self:SafeRegisterEvent("GARRISON_FOLLOWER_XP_CHANGED")
+--@debug@
self:DebugEvents()
+--@end-debug@
end
function addon:DebugEvents()
- self:RegisterEvent("GARRISON_MISSION_LIST_UPDATE",print)
- self:RegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE",print) --This event is quite useless, fires too often
- self:RegisterEvent("GARRISON_FOLLOWER_XP_CHANGED",print)
- self:RegisterEvent("GARRISON_FOLLOWER_ADDED",print)
- self:RegisterEvent("GARRISON_FOLLOWER_REMOVED",print)
- self:RegisterEvent("GARRISON_MISSION_BONUS_ROLL_LOOT",print)
- self:RegisterEvent("GARRISON_MISSION_FINISHED",print)
- self:RegisterEvent("GARRISON_UPDATE",print)
- self:RegisterEvent("GARRISON_USE_PARTY_GARRISON_CHANGED",print)
- self:RegisterEvent("GARRISON_MISSION_NPC_OPENED",print)
+ self:SafeRegisterEvent("GARRISON_MISSION_LIST_UPDATE")
+ self:SafeRegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE") -- Should be used only when has true as parameter
+ self:SafeRegisterEvent("GARRISON_FOLLOWER_ADDED")
+ self:SafeRegisterEvent("GARRISON_FOLLOWER_REMOVED")
+ self:SafeRegisterEvent("GARRISON_MISSION_BONUS_ROLL_LOOT")
+ self:SafeRegisterEvent("GARRISON_MISSION_FINISHED")
+ self:SafeRegisterEvent("GARRISON_UPDATE")
+ self:SafeRegisterEvent("GARRISON_USE_PARTY_GARRISON_CHANGED")
+ self:SafeRegisterEvent("GARRISON_MISSION_NPC_OPENED")
+end
+function addon:checkMethod(method,hook)
+ if (type(self[method])=="function") then
+--@debug@
+ --print("Hooking ",hook,"to self:" .. method)
+--@end-debug@
+ return true
+--@debug@
+ else
+ --print("Hooking ",hook,"to print")
+--@end-debug@
+ end
end
-
-function addon:CleanUp()
- self:UnhookAll()
- self:HookScript(GMF,"OnSHow","StartUp",true)
- self:PermanentEvents() -- Reattaching permanent events
- collectgarbage("collect")
- print("Cleaning up")
+function addon:SafeRegisterEvent(event)
+ local method="Event"..event
+ if (self:checkMethod(method,event)) then
+ return self:RegisterEvent(event,method)
+--@debug@
+ else
+ return self:RegisterEvent(event,print)
+--@end-debug@
+ end
end
-function addon:GetFollowerData(key,subkey)
- local k=followersCacheIndex[key]
- if (not followersCache[1]) then
- followersCache=G.GetFollowers()
- for i,v in pairs(followersCache) do
- if (not v.isCollected) then
- followersCache[i]=nil
+function addon:SafeSecureHook(tobehooked,method)
+ method=method or "Hooked"..tobehooked
+ if (self:checkMethod(method,tobehooked)) then
+ return self:SecureHook(tobehooked,method)
+--@debug@
+ else
+ do
+ local hooked=tobehooked
+ return self:SecureHook(tobehooked,function(...) print(hooked,...) end)
+ end
+--@end-debug@
+ end
+end
+function addon:SafeHookScript(frame,hook,method,postHook)
+ local name="Unknown"
+ if (type(frame)=="string") then
+ name=frame
+ frame=_G[frame]
+ else
+ if (frame and frame.GetName) then
+ name=frame:GetName()
+ end
+ end
+ if (frame) then
+ if (method) then
+ if (postHook) then
+ self:SecureHookScript(frame,hook,method)
else
- v.rank=v.level==100 and v.iLevel or v.level
+ self:HookScript(frame,hook,method)
+ end
+ else
+ if (postHook) then
+ self:SecureHookScript(frame,hook,function(...) self:ScriptTrace(name,hook,...) end)
+ else
+ self:HookScript(frame,hook,function(...) self:ScriptTrace(name,hook,...) end)
+ end
+ end
+ end
+end
+
+function addon:CleanUp()
+ self:UnhookAll()
+ self:CancelAllTimers()
+ self:HookScript(GMF,"OnSHow","StartUp",true)
+ self:PermanentEvents() -- Reattaching permanent events
+ if (GarrisonFollowerTooltip.fs) then
+ GarrisonFollowerTooltip.fs:Hide()
+ end
+ collectgarbage("collect")
+--@debug@
+ print("Cleaning up")
+--@end-debug@
+end
+function addon:EventGARRISON_FOLLOWER_XP_CHANGED(event,followerID,iLevel,xp,level,quality)
+ local i=followersCacheIndex[followerID]
+ if (i) then
+ local follower=followersCache[i]
+ if follower and follower.checkID and follower.checkID==followerID then
+ follower.iLevel=iLevel
+ follower.xp=xp
+ follower.level=level
+ follower.quality=quality
+ follower.rank=follower.level==100 and follower.iLevel or follower.level
+ follower.coloredname=C(follower.name,tostring(follower.quality))
+ follower.fullname=format("%3d %s",follower.rank,follower.coloredname)
+ follower.maxed=follower.quality >= GARRISON_FOLLOWER_MAX_UPGRADE_QUALITY and follower.level >=GARRISON_FOLLOWER_MAX_LEVEL
+ return -- single updated
+ end
+ end
+ wipe(followersCache)
+ self:GetFollowerData(followerID) -- triggering a full cache refresh
+end
+
+function addon:GetFollowerData(key,subkey)
+ local k=followersCacheIndex[key]
+ if (not followersCache[1]) then
+ followersCache=G.GetFollowers()
+ for i,follower in pairs(followersCache) do
+ if (not follower.isCollected) then
+ followersCache[i]=nil
+ else
+ follower.rank=follower.level==100 and follower.iLevel or follower.level
+ follower.coloredname=C(follower.name,tostring(follower.quality))
+ follower.fullname=format("%3d %s",follower.rank,follower.coloredname)
+ follower.maxed=follower.quality >= GARRISON_FOLLOWER_MAX_UPGRADE_QUALITY and follower.level >=GARRISON_FOLLOWER_MAX_LEVEL
end
end
end
@@ -1934,11 +2167,7 @@ function addon:GetFollowerData(key,subkey)
end
if (k) then
if (subkey) then
- if (subkey=='rank') then
- return t[k].level==100 and t[k].iLevel or t[k].level
- else
- return t[k][subkey]
- end
+ return t[k][subkey]
else
return t[k]
end
@@ -1949,8 +2178,12 @@ end
function addon:GetMissionData(missionID,subkey)
local missionCache=cache.missions[missionID]
if (missionCache.name=="<newmission>") then
+--@debug@
print("Found a new mission",missionID,"Refreshing mission list")
- self:BuildMissionCache(missionID)
+--@end-debug@
+ self:BuildMissionsCache()
+ self:FillCounters(missionID,cache.missions[missionID])
+ self:MatchMaker(missionID,cache.missions[missionID],parties[missionID],self:GetBoolean("IGM"))
end
if (subkey) then
return missionCache[subkey]
@@ -1967,148 +2200,97 @@ end
function addon:GetFollowerStatus(followerID,withTime,colored)
local status=G.GetFollowerStatus(followerID)
if (status and status== GARRISON_FOLLOWER_ON_MISSION and withTime) then
- status=timers[followerID]
+ local running=dbcache.running[dbcache.runningIndex[followerID]]
+ status=SecondsToTime(time() - running.started + running.duration,true)
end
- if (status) then
+-- The only case a follower appears in party is after a refused mission due to refresh triggered before GARRISON_FOLLOWER_LIST_UPDATE
+ if (status and status~=GARRISON_FOLLOWER_IN_PARTY) then
return colored and C(status,"Red") or status
else
return colored and C(AVAILABLE,"Green") or AVAILABLE
end
end
-function addon:ClearFollowers()
- wipe(followers)
-end
-local AceGUI=LibStub("AceGUI-3.0")
-function addon:GetScroller(title)
- local scrollerWindow=AceGUI:Create("Frame")
- scrollerWindow:SetTitle(title)
- scrollerWindow:SetLayout("Fill")
- --local scrollcontainer = AceGUI:Create("SimpleGroup") -- "InlineGroup" is also good
- --scrollcontainer:SetFullWidth(true)
- --scrollcontainer:SetFullHeight(true) -- probably?
- --scrollcontainer:SetLayout("Fill") -- important!
- --scrollerWindow:AddChild(scrollcontainer)
- local scroll = AceGUI:Create("ScrollFrame")
- scroll:SetLayout("Flow") -- probably?
- scroll:SetFullWidth(true)
- scroll:SetFullHeight(true)
- scrollerWindow:AddChild(scroll)
- scrollerWindow:SetCallback("OnClose","Release")
- scrollerWindow:SetHeight(800)
- scrollerWindow:SetWidth(400)
- scrollerWindow:SetPoint("CENTER")
- scrollerWindow:Show()
- return scroll
-end
-function addon:AddLabel(obj,text,...)
- local l=AceGUI:Create("Label")
- l:SetText(text)
- l:SetColor(...)
- l:SetFullWidth(true)
- obj:AddChild(l)
-end
-function addon:cuttyPrint(scroll,level,k,v)
- if (type(level)=="table") then
- for k,v in pairs(level) do
- self:cuttyPrint(scroll,"",k,v)
- end
- return
- end
- if (type(v)=="table") then
- self:AddLabel(scroll,level..C(k,"Azure")..":" ..C("Table","Orange"))
- for kk,vv in pairs(v) do
- self:cuttyPrint(scroll,level .. " ",kk,vv)
- end
- else
- if (type(v)=="string" and v:sub(1,2)=='0x') then
- v=v.. " " ..tostring(self:GetFollowerData(v,'name'))
- end
- self:AddLabel(scroll,level..C(k,"White")..":" ..C(v,"Yellow"))
- end
-end
-function addon:DumpFollowerMissions(missionID)
- local scroll=self:GetScroller("FollowerMissions " .. self:GetMissionData(missionID,'name'))
- self:cuttyPrint(scroll,followerMissions.missions[missionID])
-end
-function addon:DumpMission(missionID)
- local scroll=self:GetScroller("MissionCache " .. self:GetMissionData(missionID,'name'))
- self:cuttyPrint(scroll,cache.missions[missionID])
-end
-function addon:DumpCounters(missionID)
- local scroll=self:GetScroller("Counters " .. self:GetMissionData(missionID,'name'))
- self:cuttyPrint(scroll,counters[missionID])
- self:cuttyPrint(scroll,"Lista per follower","","")
- self:cuttyPrint(scroll,counterFollowerIndex[missionID])
- self:cuttyPrint(scroll,"Lista per threat","","")
- self:cuttyPrint(scroll,counterThreatIndex[missionID])
-end
-function addon:DumpCounterers(missionID)
- local scroll=self:GetScroller("Counterers " .. self:GetMissionData(missionID,'name'))
- self:cuttyPrint(scroll,cache.missions[missionID].counterers)
-end
-function addon:DumpParty(missionID)
- local scroll=self:GetScroller("Party " .. self:GetMissionData(missionID,'name'))
- self:cuttyPrint(scroll,parties[missionID])
-end
-function addon:UpdateMissionPage(missionInfo)
+function addon:HookedGarrisonMissionPage_ShowMission(missionInfo)
+ if( IsShiftKeyDown()) then print("Shift key, ignoring mission prefill") return end
+ local missionID=missionInfo.missionID
--@debug@
- print("UpdateMissionPage for",missionInfo.missionID)
+ print("UpdateMissionPage for",missionID,missionInfo.name,missionInfo.numFollowers)
--@end-debug@
--DevTools_Dump(missionInfo)
--self:BuildMissionData(missionInfo.missionID.missionInfo)
- local mission=self:GetMissionData(missionInfo.missionID)
- local t=new()
- t.members=new()
- self:MatchMaker(mission.missionID,mission,t,true)
- local members=t.members
- for i=1,#members do
+ for i=1,3 do
GarrisonMissionPage_ClearFollower(GMFMissionPageFollowers[i])
end
- for i=1,#members do
- local info=self:GetFollowerData(members[i])
- print(members[i],info.name)
- GarrisonMissionPage_SetFollower(GMFMissionPageFollowers[i],info)
+ local party=parties[missionID]
+ if (party) then
+ local members=party.members
+ for i=1,missionInfo.numFollowers do
+ local followerID=members[i]
+ if (followerID) then
+ local info=self:GetFollowerData(followerID)
+--@debug@
+ print("Adding follower",info.name)
+--@end-debug@
+ GarrisonMissionPage_SetFollower(GMFMissionPageFollowers[i],info)
+ end
+ end
end
GarrisonMissionPage_UpdateMissionForParty()
- del(t.members)
- del(t)
end
local firstcall=true
-function addon:GrowPanel(enlarge)
- if (not GMFRewardSplash:IsShown()) then
- --GMF:SetWidth(BIGSIZEW)
- GMF:SetHeight(BIGSIZEH)
- --GMFMissions:SetWidth(890)
- --GMFMissions:ClearAllPoints()
- --GMFMissions:SetPoint("TOPLEFT",GMF,25,-64)
- GMFMissions:SetPoint("BOTTOMRIGHT",GMF,-25,35)
- GMFFollowers:SetPoint("BOTTOMLEFT",GMF,-35,65)
- --GMFMissionsListScrollFrame:SetWidth(500)
- GMFMissionsListScrollFrameScrollChild:ClearAllPoints()
- GMFMissionsListScrollFrameScrollChild:SetPoint("TOPLEFT",GMFMissionsListScrollFrame)
- GMFMissionsListScrollFrameScrollChild:SetPoint("BOTTOMRIGHT",GMFMissionsListScrollFrame)
- GMFFollowersListScrollFrameScrollChild:SetPoint("BOTTOMLEFT",GMFFollowersListScrollFrame,-35,35)
- end
-end
-function addon:GetBiasColor(followerID,missionID)
- local rc,followerBias = pcall(G.GetFollowerBiasForMission,missionID,followerID)
- if (not rc) then
- print(followerID,missionID,followerBias)
- return "White"
- end
- if (followerBias==-1) then
+
+---@function GrowPanel
+-- Enforce the new panel sizes
+--
+function addon:GrowPanel()
+ GCF:Show()
+ GMF:ClearAllPoints()
+ GMF:SetPoint("TOPLEFT",GCF,"BOTTOMLEFT")
+ GMF:SetPoint("TOPRIGHT",GCF,"BOTTOMRIGHT")
+ GMFRewardSplash:ClearAllPoints()
+ GMFRewardSplash:SetPoint("TOPLEFT",GCF,"BOTTOMLEFT")
+ GMFRewardSplash:SetPoint("TOPRIGHT",GCF,"BOTTOMRIGHT")
+ GMFRewardPage:ClearAllPoints()
+ GMFRewardPage:SetPoint("TOPLEFT",GCF,"BOTTOMLEFT")
+ GMFRewardPage:SetPoint("TOPRIGHT",GCF,"BOTTOMRIGHT")
+ GMF:SetHeight(BIGSIZEH)
+ GMFMissions:SetPoint("BOTTOMRIGHT",GMF,-25,35)
+ GMFFollowers:SetPoint("BOTTOMLEFT",GMF,-35,65)
+ GMFMissionsListScrollFrameScrollChild:ClearAllPoints()
+ GMFMissionsListScrollFrameScrollChild:SetPoint("TOPLEFT",GMFMissionsListScrollFrame)
+ GMFMissionsListScrollFrameScrollChild:SetPoint("BOTTOMRIGHT",GMFMissionsListScrollFrame)
+ GMFFollowersListScrollFrameScrollChild:SetPoint("BOTTOMLEFT",GMFFollowersListScrollFrame,-35,35)
+ GMF.MissionCompleteBackground:SetWidth(BIGSIZEW)
+end
+---@function
+-- Return bias color for follower and mission
+-- @param #number bias bias as returned by blizzard interface [optional]
+-- @param #string followerID
+-- @param #number missionID
+function addon:GetBiasColor(followerID,missionID,goodcolor)
+ goodcolor=goodcolor or "White"
+ local bias=followerID or 0
+ if (missionID) then
+ local rc,followerBias = pcall(G.GetFollowerBiasForMission,missionID,followerID)
+ if (not rc) then
+ return goodcolor
+ else
+ bias=followerBias
+ end
+ end
+ if not tonumber(bias) then return "Yellow" end
+ if (bias==-1) then
return "Red"
- elseif (followerBias < 0) then
+ elseif (bias < 0) then
return "Orange"
end
- return "White"
+ return goodcolor
end
function addon:FillFollowerButton(frame,followerID,missionID)
if (not frame) then return end
- local dbg=missionID==(tonumber(_G.MW) or 0)
for i=1,#frame.Threats do
- frame.Threats[i]:Hide()
+ if (frame.Threats[i]) then frame.Threats[i]:Hide() end
end
frame.NotFull:Hide()
if (not followerID) then
@@ -2119,18 +2301,18 @@ function addon:FillFollowerButton(frame,followerID,missionID)
frame.PortraitFrame.LevelBorder:SetAtlas("GarrMission_PortraitRing_LevelBorder");
frame.PortraitFrame.LevelBorder:SetWidth(58);
frame.PortraitFrame.Level:SetText("")
- frame:SetScript("OnEnter",nil)
+ --frame:SetScript("OnEnter",nil)
GarrisonFollowerPortrait_Set(frame.PortraitFrame.Portrait)
return
end
local info=G.GetFollowerInfo(followerID)
--local info=followers[ID]
frame.info=info
+ frame.missionID=missionID
frame.Name:Show();
frame.Name:SetText(info.name);
- local color=self:GetBiasColor(followerID,missionID)
+ local color=missionID and self:GetBiasColor(followerID,missionID,"White") or "Yellow"
frame.Name:SetTextColor(C[color]())
- xprint(dbg,G.GetFollowerStatus(followerID))
frame.Status:SetText(self:GetFollowerStatus(followerID,true,true))
frame.Status:Show()
if (frame.Class) then
@@ -2151,45 +2333,42 @@ function addon:FillFollowerButton(frame,followerID,missionID)
end
GarrisonMissionFrame_SetFollowerPortrait(frame.PortraitFrame, info, showItemLevel);
-- Counters icon
- local tohide=1
- if (not GMF.MissionTab.MissionList.showInProgress) then
- local mission=self:GetMissionData(missionID)
- local c=mission.counterers[followerID]
- for i=1,min(#c, 4) do
+ if (missionID and not GMF.MissionTab.MissionList.showInProgress) then
+ local tohide=1
+ local missionCounters=counters[missionID]
+ local index=counterFollowerIndex[missionID][followerID]
+ for i=1,#index do
+ local k=index[i]
local t=frame.Threats[i]
- local tx=self.db.global.abilities[c[i]]
- if (tx) then
- t.Icon:SetTexture(tx.icon)
- else
- t.Icon:SetTexture(c[i])
- end
+ local tx=missionCounters[k].icon
+ t.Icon:SetTexture(tx)
+ local color=self:GetBiasColor(missionCounters[k].bias,nil,"Green")
+ t.Border:SetVertexColor(C[color]())
t:Show()
tohide=i+1
end
- end
- for i=tohide,4 do frame.Threats[i]:Show() end
- frame:SetScript("OnEnter",GarrisonMissionPageFollowerFrame_OnEnter)
-end
-function addon:MissionButton_OnClick(frame,button)
- _G.MW=frame:GetParent().info.missionID
- print("Clicked",frame:GetParent():GetName(),button)
- if (button=="LeftButton") then
- self:RenderButton(frame:GetParent(),{},0)
+ else
+ frame.Status:Hide()
end
end
-- pseudo static
local scale=0.9
-local x1,y1,x2,y2=10,0,12*scale,0
-function addon:PrepareExtraButton(bg,limit)
- limit=limit or 3
- for numMembers=1,limit do
- local f=bg.Party[numMembers]
- if (not f) then
- f=CreateFrame("Button",nil,bg,"GarrisonCommanderMissionPageFollowerTemplate")
- f:SetPoint("LEFT",bg.Party[numMembers-1],"RIGHT",x2,y2)
- --f:SetFrameStrata("HIGH")
- tinsert(bg.Party,f)
- end
+function addon:BuildFollowersButtons(button,bg,limit)
+ if (bg.Party) then return end
+ bg.Party={}
+ for numMembers=1,3 do
+ local f=CreateFrame("Button",nil,bg,"GarrisonCommanderMissionPageFollowerTemplate")
+ if (numMembers==1) then
+ f:SetPoint("BOTTOMLEFT",bg.Percent,"BOTTOMRIGHT",10,0)
+ else
+ f:SetPoint("LEFT",bg.Party[numMembers-1],"RIGHT",10,0)
+ end
+ tinsert(bg.Party,f)
+ f:EnableMouse(true)
+ f:SetScript("OnEnter",GarrisonMissionPageFollowerFrame_OnEnter)
+ f:SetScript("OnLeave",GarrisonMissionPageFollowerFrame_OnLeave)
+ f:RegisterForClicks("AnyUp")
+ f:SetScript("OnClick",function(...) self:OnClick_PartyMember(...) end)
for numThreats=1,4 do
local threatFrame =f.Threats[numThreats];
if ( not threatFrame ) then
@@ -2200,42 +2379,144 @@ function addon:PrepareExtraButton(bg,limit)
threatFrame:Hide()
end
end
+ for i=1,3 do bg.Party[i]:SetScale(0.9) end
+ -- Making room for both GC and MP
+ if (button.Expire) then
+ button.Expire:ClearAllPoints()
+ button.Expire:SetPoint("TOPRIGHT")
+ end
+ if (button.Threats and button.Threats[1]) then
+ button.Threats[1]:ClearAllPoints()
+ button.Threats[1]:SetPoint("TOPLEFT",165,0)
+ end
+
+
+
end
function addon:BuildExtraButton(button)
local bg=CreateFrame("Button",nil,button,"GarrisonCommanderMissionButton")
- --button.LocBG:ClearAllPoints()
- --button.LocBG:SetPoint("RIGHT",200,0)
- button.Title:ClearAllPoints()
- button.Title:SetPoint("TOPLEFT",165,-5)
- button.Summary:ClearAllPoints()
- button.Summary:SetPoint("BOTTOMLEFT",165,5)
- button.LocBG:SetPoint("LEFT")
bg:SetPoint("TOPLEFT",button,"TOPRIGHT")
bg:SetPoint("RIGHT",GarrisonMissionFrameMissionsListScrollFrame,"RIGHT",-25,0)
bg.button=button
bg:SetScript("OnEnter",function(this) GarrisonMissionButton_OnEnter(this.button) end)
bg:SetScript("OnLeave",function() GameTooltip:FadeOut() end)
bg:RegisterForClicks("AnyUp")
- self:RawHookScript(bg,"OnClick","MissionButton_OnClick")
+ bg:SetScript("OnClick",function(...) self:OnClick_GCMissionButton(...) end)
button.gcPANEL=bg
- self:PrepareExtraButton(bg)
+ if (not bg.Party) then self:BuildFollowersButtons(button,bg,3) end
end
-function addon:GarrisonMissionButton_SetRewards(button,rewards,numrewards)
+--function addon:GarrisonMissionButton_SetRewards(button,rewards,numrewards)
+--end
+do
+ local menuFrame = CreateFrame("Frame", "GCFollowerDropDOwn", nil, "UIDropDownMenuTemplate")
+ local func=function(...) addon:IgnoreFollower(...) end
+ local func2=function(...) addon:UnignoreFollower(...) end
+ local menu= {
+ { text="Follower", notClickable=true,notCheckable=true,isTitle=true },
+ { text=L["Ignore for this mission"],checked=false, func=func, arg1=0, arg2="none"},
+-- { text=L["Ignore for all missions"],checked=false, func=func, arg1=0, arg2="none"},
+ { text=L["Consider again"], notClickable=true,notCheckable=true,isTitle=true },
+ }
+ function addon:OnClick_PartyMember(frame,button,down,...)
+ local followerID=frame.info and frame.info.followerID or nil
+ local missionID=frame.missionID
+ if (not followerID) then return end
+ if (button=="LeftButton") then
+ self:OpenFollowersTab()
+ GMF.selectedFollower=followerID
+ if (GMF.FollowerTab) then
+ GarrisonFollowerPage_ShowFollower(GMF.FollowerTab,followerID)
+ end
+ else
+ local ignore=self.privatedb.profile.ignored
+
+ menu[1].text=frame.info.name
+ menu[2].arg1=missionID
+ menu[2].arg2=followerID
+ --menu[3].arg2=followerID
+ local i=4
+ for k,r in pairs(dbcache.ignored[missionID]) do
+ if (r) then
+ local v=menu[i] or {}
+ v.text=self:GetFollowerData(k,'name')
+ v.func=func2
+ v.arg1=missionID
+ v.arg2=k
+ menu[i]=v
+ i=i+1
+ else
+ dbcache.ignored[missionID]=nil
+ end
+ end
+ if (i>4) then
+ i=i+1
+ menu[i]={text=ALL,func=func2,arg1=missionID,arg2='all'}
+ end
+ for x=#menu,i,-1 do tremove(menu) end
+ EasyMenu(menu,menuFrame,"cursor",0,0,"MENU",5)
+ end
+
+ end
+end
+function addon:IgnoreFollower(table,missionID,followerID,flag)
+ if (missionID==0) then
+ dbcache.totallyignored[followerID]=true
+ else
+ dbcache.ignored[missionID][followerID]=true
+ end
+ -- full ignore disabled for now
+ dbcache.totallyignored[followerID]=nil
+ self:RefreshMission(missionID)
+end
+function addon:UnignoreFollower(table,missionID,followerID,flag)
+ if (followerID=='all') then
+ wipe(dbcache.ignored[missionID])
+ else
+ dbcache.ignored[missionID][followerID]=nil
+ end
+ self:RefreshMission(missionID)
+end
+function addon:OpenFollowersTab()
+ GarrisonMissionFrame_SelectTab(2)
end
-function addon:GarrisonMissionButton_OnClick(tab,button)
- print("Interceptd",button,tab.fromFollowerPage)
+function addon:OpenMissionsTab()
+ GarrisonMissionFrame_SelectTab(1)
+end
+function addon:OnClick_GarrisonMissionButton(tab,button)
+ trace("Clicked")
if (tab.fromFollowerPage) then
GarrisonMissionFrame_SelectTab(1)
end
end
-function addon:RenderButton(button,rewards,numRewards)
---@debug@
+function addon:OnClick_GCMissionButton(frame,button)
+ if (button=="RightButton") then
+ self:HookedGarrisonMissionButton_SetRewards(frame:GetParent(),{},0)
+ _G.DBG=frame.button.info.missionID
+ else
+ frame.button:Click()
+ end
+end
+
+function addon:HookedGarrisonMissionButton_SetRewards(button,rewards,numRewards)
if (not button or not button.Title) then
+--@debug@
error(strconcat("Called on I dunno what ",tostring(button)," ", tostring(button:GetName())))
return
- end
--@end-debug@
- if (self:IsRewardPage()) then return end
+ end
+ --if (self:IsRewardPage()) then return end
+ local tw=button:GetWidth()-165
+ if ( button.Title:GetWidth() + button.Summary:GetWidth() + 8 < tw - numRewards * 65 ) then
+ button.Title:SetPoint("LEFT", 165, 0);
+ button.Summary:ClearAllPoints();
+ button.Summary:SetPoint("BOTTOMLEFT", button.Title, "BOTTOMRIGHT", 8, 0);
+ else
+ button.Title:SetPoint("LEFT", 165, 10);
+ button.Title:SetWidth(tw - numRewards * 65);
+ button.Summary:ClearAllPoints();
+ button.Summary:SetPoint("TOPLEFT", button.Title, "BOTTOMLEFT", 0, -4);
+ end
+ button.LocBG:SetPoint("LEFT")
if (numRewards > 0) then
local index=1
for id,reward in pairs(rewards) do
@@ -2270,16 +2551,10 @@ function addon:RenderButton(button,rewards,numRewards)
button:SetWidth(width)
if (not button.gcPANEL) then
self:BuildExtraButton(button)
- else
- -- Summary is a bit stubborn, it must be moved every time
- button.Summary:ClearAllPoints()
- button.Summary:SetPoint("BOTTOMLEFT",165,5)
end
local panel=button.gcPANEL
local missionInfo=button.info
local missionID=missionInfo.missionID
- local dbg=missionID==(tonumber(_G.MW) or 0)
- xprint(dbg,C("Rendering button for mission "..missionID,"Red"))
if (GMF.MissionTab.MissionList.showInProgress) then
if (not button.inProgressFresh) then
local perc=select(4,G.GetPartyMissionInfo(missionID))
@@ -2303,11 +2578,9 @@ function addon:RenderButton(button,rewards,numRewards)
button.inProgressFresh=false
local mission=self:GetMissionData(missionID)
local party=parties[missionID]
- xprint("Rendering mission",button.info.missionID)
if (#party.members==0) then
+ self:FillCounters(missionID,mission)
self:MatchMaker(missionID,mission,party)
- else
- xprint("Using old party",#party.members)
end
local perc=party.perc
local notFull=false
@@ -2354,8 +2627,8 @@ function addon:RenderButton(button,rewards,numRewards)
panel.Age:Show()
panel.Percent:Show()
end
-_G.GAC=addon
--@do-not-package@
+_G.GAC=addon
--[[
MasterPlan final button
GMFMissions.CompleteDialog.BorderFrame.CompleteAll
@@ -2560,4 +2833,141 @@ Dump: value=table returned by GetFollowerInfo for a collected follower
}
local location, xp, environment, environmentDesc, environmentTexture, locPrefix, isExhausting, enemies = G.GetMissionInfo(missionID)
--]]
+function addon:GetScroller(title)
+ local scrollerWindow=AceGUI:Create("Frame")
+ scrollerWindow:SetTitle(title)
+ scrollerWindow:SetLayout("Fill")
+ --local scrollcontainer = AceGUI:Create("SimpleGroup") -- "InlineGroup" is also good
+ --scrollcontainer:SetFullWidth(true)
+ --scrollcontainer:SetFullHeight(true) -- probably?
+ --scrollcontainer:SetLayout("Fill") -- important!
+ --scrollerWindow:AddChild(scrollcontainer)
+ local scroll = AceGUI:Create("ScrollFrame")
+ scroll:SetLayout("Flow") -- probably?
+ scroll:SetFullWidth(true)
+ scroll:SetFullHeight(true)
+ scrollerWindow:AddChild(scroll)
+ scrollerWindow:SetCallback("OnClose","Release")
+ scrollerWindow:SetHeight(800)
+ scrollerWindow:SetWidth(400)
+ scrollerWindow:SetPoint("CENTER")
+ scrollerWindow:Show()
+ return scroll
+end
+function addon:AddLabel(obj,text,...)
+ local l=AceGUI:Create("Label")
+ l:SetText(text)
+ l:SetColor(...)
+ l:SetFullWidth(true)
+ obj:AddChild(l)
+end
+function addon:cuttyPrint(scroll,level,k,v)
+ if (type(level)=="table") then
+ for k,v in pairs(level) do
+ self:cuttyPrint(scroll,"",k,v)
+ end
+ return
+ end
+ if (type(v)=="table") then
+ self:AddLabel(scroll,level..C(k,"Azure")..":" ..C("Table","Orange"))
+ for kk,vv in pairs(v) do
+ self:cuttyPrint(scroll,level .. " ",kk,vv)
+ end
+ else
+ if (type(v)=="string" and v:sub(1,2)=='0x') then
+ v=v.. " " ..tostring(self:GetFollowerData(v,'name'))
+ end
+ self:AddLabel(scroll,level..C(k,"White")..":" ..C(v,"Yellow"))
+ end
+end
+function addon:DumpFollowerMissions(missionID)
+ local scroll=self:GetScroller("FollowerMissions " .. self:GetMissionData(missionID,'name'))
+ self:cuttyPrint(scroll,followerMissions.missions[missionID])
+end
+function addon:DumpIfnored()
+ local scroll=self:GetScroller("Ignored")
+ self:cuttyPrint(scroll,self.privatedb.profile.ignored)
+end
+function addon:DumpMission(missionID)
+ local scroll=self:GetScroller("MissionCache " .. self:GetMissionData(missionID,'name'))
+ self:cuttyPrint(scroll,cache.missions[missionID])
+end
+---
+-- Debug function
+--@param missionID Identificativo missione
+function addon:DumpCounters(missionID)
+ local scroll=self:GetScroller("Counters " .. self:GetMissionData(missionID,'name'))
+ self:cuttyPrint(scroll,counters[missionID])
+ self:cuttyPrint(scroll,"Lista per follower","","")
+ self:cuttyPrint(scroll,counterFollowerIndex[missionID])
+ self:cuttyPrint(scroll,"Lista per threat","","")
+ self:cuttyPrint(scroll,counterThreatIndex[missionID])
+end
+function addon:Dump(title,data)
+ local scroll=self:GetScroller(title)
+ self:cuttyPrint(scroll,data)
+
+end
+function addon:DumpCounterers(missionID)
+ local scroll=self:GetScroller("Counterers " .. self:GetMissionData(missionID,'name'))
+ self:cuttyPrint(scroll,cache.missions[missionID].counterers)
+end
+function addon:DumpParty(missionID)
+ local scroll=self:GetScroller("Party " .. self:GetMissionData(missionID,'name'))
+ self:cuttyPrint(scroll,parties[missionID])
+end
+function addon:GenerateTimersPeriodic()
+ return coroutine.wrap(
+ function(self)
+ repeat
+ local t=new()
+ G.GetInProgressMissions(t)
+ for index=1,#t do
+ local mission=t[index]
+ for i=1,mission.numFollowers do
+ end
+ end
+ coroutine.yield()
+ until false
+ end
+ )
+end
+function addon:GMF_OnDragStart(frame)
+ if (not self:GetBoolean('MOVEPANEL')) then return end
+ frame.IsSizingOrMoving=true
+ if (IsShiftKeyDown()) then
+ frame.IsSizing=true
+ frame:StartSizing("BOTTOMRIGHT")
+ frame:SetScript("OnUpdate",function(frame,elapsed)
+ if (frame.timepassed and frame.timepassed >1) then
+ GarrisonMissionList_UpdateMissions()
+ else
+ frame.timepassed=frame.timepassed or 0
+ frame.timepassed=frame.timepassed +elapsed
+ end
+ end)
+ else
+ frame.IsSizing=nil
+ frame:StartMoving()
+ end
+end
+function addon:GMF_OnDragStop(frame)
+ frame:StopMovingOrSizing()
+ frame:SetScript("OnUpdate",nil)
+ if (frame.IsSizing) then
+ BIGSIZEW=frame:GetWidth()
+ SIZEV=frame:GetHeight()
+ BIGBUTTON=min(BIGSIZEW*0.55,BIGSIZEW-GCSIZE)
+ SMALLBUTTON=BIGBUTTON
+ if (not self:IsFollowerList()) then
+ HybridScrollFrame_CreateButtons(frame.MissionTab.MissionList.listScroll, "GarrisonMissionListButtonTemplate", 13, -8, nil, nil, nil, -4);
+ GarrisonMissionList_Update();
+ else
+ HybridScrollFrame_CreateButtons(frame.FollowerList.listScroll, "GarrisonMissionFollowerButtonTemplate", 7, -7, nil, nil, nil, -6);
+ end
+ end
+ frame.IsSizing=nil
+ frame.IsSizingOrMoving=nil
+end
+
--@end-do-not-package@
diff --git a/GarrisonCommander.xml b/GarrisonCommander.xml
index a9ddff1..ea01a57 100644
--- a/GarrisonCommander.xml
+++ b/GarrisonCommander.xml
@@ -52,7 +52,8 @@
</Texture>
</Layer>
<Layer level="BACKGROUND" textureSubLevel="3">
- <Texture parentKey="IconBG" atlas="Garr_MissionList-IconBG" useAtlasSize="true">
+ <Texture parentKey="IconBG" atlas="Garr_MissionList-IconBG">
+ <Size x="90" y="80"/>
<Anchors>
<Anchor point="TOPLEFT" y="-1"/>
</Anchors>
@@ -126,7 +127,7 @@
</Layer>
</Layers>
</Frame>
- <Frame name="GarrisonCommanderMissionPageFollowerTemplate" inherits="GarrisonMissionPageFollowerTemplate" virtual="true">
+ <Button name="GarrisonCommanderMissionPageFollowerTemplate" inherits="GarrisonMissionPageFollowerTemplate" virtual="true">
<Size x="170" y="58"/>
<Layers>
<Layer level="OVERLAY">
@@ -165,7 +166,7 @@
<OnLeave function="GarrisonMissionPageFollowerFrame_OnLeave"/>
<OnMouseUp />
</Scripts>
- </Frame>
+ </Button>
<Button name="GarrisonCommanderMissionButton" inherits="GarrisonCommanderBackground" virtual="true">
<Size x="600" y="80"/>
<Layers>
@@ -185,15 +186,9 @@
</FontString>
</Layer>
</Layers>
- <Frames>
- <Frame parentArray="Party" name="$parentFollower" inherits="GarrisonCommanderMissionPageFollowerTemplate">
- <Anchors>
- <Anchor point="BOTTOMLEFT" relativeKey="$parent.Percent" relativePoint="BOTTOMRIGHT" x="40" y="0"/>
- </Anchors>
- </Frame>
- </Frames>
</Button>
<Button name="GarrisonCommanderMissionListButtonTemplate" inherits="GarrisonMissionListButtonTemplate" virtual="true">
+ <Size x="450" y="80" />
<Layers>
<Layer level="OVERLAY" >
<FontString parentKey="NumMembers" inherits="GameFontHighlightSmall" justifyH="CENTER" justifyV="CENTER" maxLines="3" >
@@ -214,14 +209,148 @@
</Layers>
</Button>
<Frame name="GarrisonCommanderFollowerMissionList" virtual="true">
- <Size x="400" y="400" />
+ <Size x="250" y="400" />
<Frames>
- <Button parentArray="Missions" name="$parentMissions" inherits="GarrisonCommanderMissionListButtonTemplate" >
- <Size x="450" y="80" />
+ <Frame parentKey="Header" name="$parentHeader" inherits="GarrisonCommanderMissionPageFollowerTemplate">
<Anchors>
- <Anchor point="TOPLEFT" />
+ <Anchor point="TOPLEFT"/>
</Anchors>
+ </Frame>
+ </Frames>
+ </Frame>
+ <Frame name="GarrisonCommanderMenu" virtual="true">
+ <Size>
+ <AbsDimension x="40" y="32"/>
+ </Size>
+ <Layers>
+ <Layer level="ARTWORK">
+ <Texture parentKey="Left" name="$parentLeft" file="Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame">
+ <Size>
+ <AbsDimension x="25" y="64"/>
+ </Size>
+ <Anchors>
+ <Anchor point="TOPLEFT">
+ <Offset>
+ <AbsDimension x="0" y="17"/>
+ </Offset>
+ </Anchor>
+ </Anchors>
+ <TexCoords left="0" right="0.1953125" top="0" bottom="1"/>
+ </Texture>
+ <Texture parentKey="Middle" name="$parentMiddle" file="Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame">
+ <Size>
+ <AbsDimension x="200" y="64"/>
+ </Size>
+ <Anchors>
+ <Anchor point="LEFT" relativeTo="$parentLeft" relativePoint="RIGHT"/>
+ </Anchors>
+ <TexCoords left="0.1953125" right="0.8046875" top="0" bottom="1"/>
+ </Texture>
+ <Texture parentKey="Right" name="$parentRight" file="Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame">
+ <Size>
+ <AbsDimension x="25" y="64"/>
+ </Size>
+ <Anchors>
+ <Anchor point="LEFT" relativeTo="$parentMiddle" relativePoint="RIGHT"/>
+ </Anchors>
+ <TexCoords left="0.8046875" right="1" top="0" bottom="1"/>
+ </Texture>
+ <FontString parentKey="Text" name="$parentText" inherits="GameFontHighlightSmall" wordwrap="false" justifyH="RIGHT">
+ <Size>
+ <AbsDimension x="0" y="10"/>
+ </Size>
+ <Anchors>
+ <Anchor point="RIGHT" relativeTo="$parentRight">
+ <Offset>
+ <AbsDimension x="-43" y="2"/>
+ </Offset>
+ </Anchor>
+ </Anchors>
+ </FontString>
+ </Layer>
+ <Layer level="OVERLAY">
+ <Texture name="$parentIcon" hidden="true">
+ <Size>
+ <AbsDimension x="16" y="16"/>
+ </Size>
+ <Anchors>
+ <Anchor point="LEFT">
+ <Offset x="30" y="2"/>
+ </Anchor>
+ </Anchors>
+ </Texture>
+ </Layer>
+ </Layers>
+ <Frames>
+ <Button parentKey="Button" name="$parentButton" motionScriptsWhileDisabled="true" >
+ <Size>
+ <AbsDimension x="24" y="24"/>
+ </Size>
+ <Anchors>
+ <Anchor point="TOPRIGHT" relativeTo="$parentRight">
+ <Offset>
+ <AbsDimension x="-16" y="-18"/>
+ </Offset>
+ </Anchor>
+ </Anchors>
+ <Scripts>
+ <OnEnter>
+ local parent = self:GetParent();
+ local myscript = parent:GetScript("OnEnter");
+ if(myscript ~= nil) then
+ myscript(parent);
+ end
+ </OnEnter>
+ <OnLeave>
+ local parent = self:GetParent();
+ local myscript = parent:GetScript("OnLeave");
+ if(myscript ~= nil) then
+ myscript(parent);
+ end
+ </OnLeave>
+ <OnClick>
+ EasyMenu(self:GetParent().menu, self:GetParent(), "cursor", 0, 0, "MENU", 4)
+ </OnClick>
+ </Scripts>
+ <NormalTexture name="$parentNormalTexture" file="Interface\ChatFrame\UI-ChatIcon-ScrollDown-Up">
+ <Size>
+ <AbsDimension x="24" y="24"/>
+ </Size>
+ <Anchors>
+ <Anchor point="RIGHT"/>
+ </Anchors>
+ </NormalTexture>
+ <PushedTexture name="$parentPushedTexture" file="Interface\ChatFrame\UI-ChatIcon-ScrollDown-Down">
+ <Size>
+ <AbsDimension x="24" y="24"/>
+ </Size>
+ <Anchors>
+ <Anchor point="RIGHT"/>
+ </Anchors>
+ </PushedTexture>
+ <DisabledTexture name="$parentDisabledTexture" file="Interface\ChatFrame\UI-ChatIcon-ScrollDown-Disabled">
+ <Size>
+ <AbsDimension x="24" y="24"/>
+ </Size>
+ <Anchors>
+ <Anchor point="RIGHT"/>
+ </Anchors>
+ </DisabledTexture>
+ <HighlightTexture name="$parentHighlightTexture" file="Interface\Buttons\UI-Common-MouseHilight" alphaMode="ADD">
+ <Size>
+ <AbsDimension x="24" y="24"/>
+ </Size>
+ <Anchors>
+ <Anchor point="RIGHT"/>
+ </Anchors>
+ </HighlightTexture>
</Button>
</Frames>
+ <Scripts>
+ <OnHide>
+ CloseDropDownMenus();
+ </OnHide>
+ </Scripts>
</Frame>
+
</Ui>
\ No newline at end of file
diff --git a/RelNotes.lua b/RelNotes.lua
index 226f352..c4dfa47 100644
--- a/RelNotes.lua
+++ b/RelNotes.lua
@@ -1,6 +1,5 @@
local me,ns=...
local hlp=LibStub("LibInit"):GetAddon(me)
-if (not hlp) then return end
local L=hlp:GetLocale()
function hlp:loadHelp()
self:HF_Title(me,"RELNOTES")
diff --git a/embeds.xml b/embeds.xml
index e2c177d..99cc796 100644
--- a/embeds.xml
+++ b/embeds.xml
@@ -1,3 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
+ <Include file="libs\LibDeformat-3.0\lib.xml"/>
<Include file="libs\LibInit\LibInit.xml"/>
</Ui>
diff --git a/libs/LibDeformat-3.0/LibDeformat-3.0.lua b/libs/LibDeformat-3.0/LibDeformat-3.0.lua
new file mode 100644
index 0000000..6580517
--- /dev/null
+++ b/libs/LibDeformat-3.0/LibDeformat-3.0.lua
@@ -0,0 +1,272 @@
+--[[
+Name: LibDeformat-3.0
+Author(s): ckknight (ckknight@gmail.com)
+Website: http://www.wowace.com/projects/libdeformat-3-0/
+Description: A library to convert a post-formatted string back to its original arguments given its format string.
+License: MIT
+]]
+
+local LibDeformat = LibStub:NewLibrary("LibDeformat-3.0", 1)
+
+if not LibDeformat then
+ return
+end
+
+-- this function does nothing and returns nothing
+local function do_nothing()
+end
+
+-- a dictionary of format to match entity
+local FORMAT_SEQUENCES = {
+ ["s"] = ".+",
+ ["c"] = ".",
+ ["%d*d"] = "%%-?%%d+",
+ ["[fg]"] = "%%-?%%d+%%.?%%d*",
+ ["%%%.%d[fg]"] = "%%-?%%d+%%.?%%d*",
+}
+
+-- a set of format sequences that are string-based, i.e. not numbers.
+local STRING_BASED_SEQUENCES = {
+ ["s"] = true,
+ ["c"] = true,
+}
+
+local cache = setmetatable({}, {__mode='k'})
+-- generate the deformat function for the pattern, or fetch from the cache.
+local function get_deformat_function(pattern)
+ local func = cache[pattern]
+ if func then
+ return func
+ end
+
+ -- escape the pattern, so that string.match can use it properly
+ local unpattern = '^' .. pattern:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") .. '$'
+
+ -- a dictionary of index-to-boolean representing whether the index is a number rather than a string.
+ local number_indexes = {}
+
+ -- (if the pattern is a numbered format,) a dictionary of index-to-real index.
+ local index_translation = nil
+
+ -- the highest found index, also the number of indexes found.
+ local highest_index
+ if not pattern:find("%%1%$") then
+ -- not a numbered format
+
+ local i = 0
+ while true do
+ i = i + 1
+ local first_index
+ local first_sequence
+ for sequence in pairs(FORMAT_SEQUENCES) do
+ local index = unpattern:find("%%%%" .. sequence)
+ if index and (not first_index or index < first_index) then
+ first_index = index
+ first_sequence = sequence
+ end
+ end
+ if not first_index then
+ break
+ end
+ unpattern = unpattern:gsub("%%%%" .. first_sequence, "(" .. FORMAT_SEQUENCES[first_sequence] .. ")", 1)
+ number_indexes[i] = not STRING_BASED_SEQUENCES[first_sequence]
+ end
+
+ highest_index = i - 1
+ else
+ -- a numbered format
+
+ local i = 0
+ while true do
+ i = i + 1
+ local found_sequence
+ for sequence in pairs(FORMAT_SEQUENCES) do
+ if unpattern:find("%%%%" .. i .. "%%%$" .. sequence) then
+ found_sequence = sequence
+ break
+ end
+ end
+ if not found_sequence then
+ break
+ end
+ unpattern = unpattern:gsub("%%%%" .. i .. "%%%$" .. found_sequence, "(" .. FORMAT_SEQUENCES[found_sequence] .. ")", 1)
+ number_indexes[i] = not STRING_BASED_SEQUENCES[found_sequence]
+ end
+ highest_index = i - 1
+
+ i = 0
+ index_translation = {}
+ pattern:gsub("%%(%d)%$", function(w)
+ i = i + 1
+ index_translation[i] = tonumber(w)
+ end)
+ end
+
+ if highest_index == 0 then
+ cache[pattern] = do_nothing
+ else
+ --[=[
+ -- resultant function looks something like this:
+ local unpattern = ...
+ return function(text)
+ local a1, a2 = text:match(unpattern)
+ if not a1 then
+ return nil, nil
+ end
+ return a1+0, a2
+ end
+
+ -- or if it were a numbered pattern,
+ local unpattern = ...
+ return function(text)
+ local a2, a1 = text:match(unpattern)
+ if not a1 then
+ return nil, nil
+ end
+ return a1+0, a2
+ end
+ ]=]
+
+ local t = {}
+ t[#t+1] = [=[
+ return function(text)
+ local ]=]
+
+ for i = 1, highest_index do
+ if i ~= 1 then
+ t[#t+1] = ", "
+ end
+ t[#t+1] = "a"
+ if not index_translation then
+ t[#t+1] = i
+ else
+ t[#t+1] = index_translation[i]
+ end
+ end
+
+ t[#t+1] = [=[ = text:match(]=]
+ t[#t+1] = ("%q"):format(unpattern)
+ t[#t+1] = [=[)
+ if not a1 then
+ return ]=]
+
+ for i = 1, highest_index do
+ if i ~= 1 then
+ t[#t+1] = ", "
+ end
+ t[#t+1] = "nil"
+ end
+
+ t[#t+1] = "\n"
+ t[#t+1] = [=[
+ end
+ ]=]
+
+ t[#t+1] = "return "
+ for i = 1, highest_index do
+ if i ~= 1 then
+ t[#t+1] = ", "
+ end
+ t[#t+1] = "a"
+ t[#t+1] = i
+ if number_indexes[i] then
+ t[#t+1] = "+0"
+ end
+ end
+ t[#t+1] = "\n"
+ t[#t+1] = [=[
+ end
+ ]=]
+
+ t = table.concat(t, "")
+
+ -- print(t)
+
+ cache[pattern] = assert(loadstring(t))()
+ end
+
+ return cache[pattern]
+end
+
+--- Return the arguments of the given format string as found in the text.
+-- @param text The resultant formatted text.
+-- @param pattern The pattern used to create said text.
+-- @return a tuple of values, either strings or numbers, based on the pattern.
+-- @usage LibDeformat.Deformat("Hello, friend", "Hello, %s") == "friend"
+-- @usage LibDeformat.Deformat("Hello, friend", "Hello, %1$s") == "friend"
+-- @usage LibDeformat.Deformat("Cost: $100", "Cost: $%d") == 100
+-- @usage LibDeformat.Deformat("Cost: $100", "Cost: $%1$d") == 100
+-- @usage LibDeformat.Deformat("Alpha, Bravo", "%s, %s") => "Alpha", "Bravo"
+-- @usage LibDeformat.Deformat("Alpha, Bravo", "%1$s, %2$s") => "Alpha", "Bravo"
+-- @usage LibDeformat.Deformat("Alpha, Bravo", "%2$s, %1$s") => "Bravo", "Alpha"
+-- @usage LibDeformat.Deformat("Hello, friend", "Cost: $%d") == nil
+-- @usage LibDeformat("Hello, friend", "Hello, %s") == "friend"
+function LibDeformat.Deformat(text, pattern)
+ if type(text) ~= "string" then
+ error(("Argument #1 to `Deformat' must be a string, got %s (%s)."):format(type(text), text), 2)
+ elseif type(pattern) ~= "string" then
+ error(("Argument #2 to `Deformat' must be a string, got %s (%s)."):format(type(pattern), pattern), 2)
+ end
+
+ return get_deformat_function(pattern)(text)
+end
+
+--[===[@debug@
+function LibDeformat.Test()
+ local function tuple(success, ...)
+ if success then
+ return true, { n = select('#', ...), ... }
+ else
+ return false, ...
+ end
+ end
+
+ local function check(text, pattern, ...)
+ local success, results = tuple(pcall(LibDeformat.Deformat, text, pattern))
+ if not success then
+ return false, results
+ end
+
+ if select('#', ...) ~= results.n then
+ return false, ("Differing number of return values. Expected: %d. Actual: %d."):format(select('#', ...), results.n)
+ end
+
+ for i = 1, results.n do
+ local expected = select(i, ...)
+ local actual = results[i]
+ if type(expected) ~= type(actual) then
+ return false, ("Return #%d differs by type. Expected: %s (%s). Actual: %s (%s)"):format(type(expected), expected, type(actual), actual)
+ elseif expected ~= actual then
+ return false, ("Return #%d differs. Expected: %s. Actual: %s"):format(expected, actual)
+ end
+ end
+
+ return true
+ end
+
+ local function test(text, pattern, ...)
+ local success, problem = check(text, pattern, ...)
+ if not success then
+ print(("Problem with (%q, %q): %s"):format(text, pattern, problem or ""))
+ end
+ end
+
+ test("Hello, friend", "Hello, %s", "friend")
+ test("Hello, friend", "Hello, %1$s", "friend")
+ test("Cost: $100", "Cost: $%d", 100)
+ test("Cost: $100", "Cost: $%1$d", 100)
+ test("Alpha, Bravo", "%s, %s", "Alpha", "Bravo")
+ test("Alpha, Bravo", "%1$s, %2$s", "Alpha", "Bravo")
+ test("Alpha, Bravo", "%2$s, %1$s", "Bravo", "Alpha")
+ test("Alpha, Bravo, Charlie, Delta, Echo", "%s, %s, %s, %s, %s", "Alpha", "Bravo", "Charlie", "Delta", "Echo")
+ test("Alpha, Bravo, Charlie, Delta, Echo", "%1$s, %2$s, %3$s, %4$s, %5$s", "Alpha", "Bravo", "Charlie", "Delta", "Echo")
+ test("Alpha, Bravo, Charlie, Delta, Echo", "%5$s, %4$s, %3$s, %2$s, %1$s", "Echo", "Delta", "Charlie", "Bravo", "Alpha")
+ test("Alpha, Bravo, Charlie, Delta, Echo", "%2$s, %3$s, %4$s, %5$s, %1$s", "Echo", "Alpha", "Bravo", "Charlie", "Delta")
+ test("Alpha, Bravo, Charlie, Delta, Echo", "%3$s, %4$s, %5$s, %1$s, %2$s", "Delta", "Echo", "Alpha", "Bravo", "Charlie")
+ test("Alpha, Bravo, Charlie, Delta", "%s, %s, %s, %s, %s", nil, nil, nil, nil, nil)
+ test("Hello, friend", "Cost: $%d", nil)
+ print("LibDeformat-3.0: Tests completed.")
+end
+--@end-debug@]===]
+
+setmetatable(LibDeformat, { __call = function(self, ...) return self.Deformat(...) end })
\ No newline at end of file
diff --git a/libs/LibDeformat-3.0/lib.xml b/libs/LibDeformat-3.0/lib.xml
new file mode 100644
index 0000000..cf6abae
--- /dev/null
+++ b/libs/LibDeformat-3.0/lib.xml
@@ -0,0 +1,4 @@
+<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
+..\FrameXML\UI.xsd">
+ <Script file="LibDeformat-3.0.lua" />
+</Ui>
\ No newline at end of file