Quantcast

public alpha

Alar of Daggerspine [01-12-15 - 02:25]
public alpha

Signed-off-by: Alar of Daggerspine <alar@aspide.it>
Filename
GarrisonCommander.lua
doc.txt
wowhead.lua
diff --git a/GarrisonCommander.lua b/GarrisonCommander.lua
index d8afc16..525703e 100644
--- a/GarrisonCommander.lua
+++ b/GarrisonCommander.lua
@@ -37,13 +37,12 @@ local bigscreen=true
 local GMM=false
 local MP=false
 local MPGoodGuy=false
-local MPPage
+local MPSwitch
 local dbg=false
 local trc=false
 local pin=false
 local baseHeight
 local minHeight
-
 if (LibDebug) then LibDebug() end
 local function tcopy(obj, seen)
 	if type(obj) ~= 'table' then return obj end
@@ -125,6 +124,7 @@ local GARRISON_FOLLOWER_MAX_UPGRADE_QUALITY=GARRISON_FOLLOWER_MAX_UPGRADE_QUALIT
 local GARRISON_FOLLOWER_MAX_LEVEL=GARRISON_FOLLOWER_MAX_LEVEL -- 100

 local LEVEL=LEVEL -- Level
+local MISSING=ADDON_MISSING
 local NOT_COLLECTED=NOT_COLLECTED -- not collected
 local GMF=GarrisonMissionFrame
 local GMFFollowerPage=GMF.FollowerTab
@@ -548,8 +548,10 @@ end
 function addon:OnInitialized()
 --@debug@
 	xprint("OnInitialized")
-	self:DebugEvents()
 --@end-debug@
+--@alpha@
+	self:Popup(L["You are using an Alpha version of Garrison Commander. Please post bugs on Curse if you find them"],10)
+--@end-alpha@
 	for _,b in ipairs(GMFMissionsListScrollFrame.buttons) do
 		local scale=0.8
 		local f,h,s=b.Title:GetFont()
@@ -570,7 +572,7 @@ function addon:OnInitialized()
 	self:AddLabel("Mission Panel")
 	self:AddToggle("IGM",true,IGNORE_UNAIVALABLE_FOLLOWERS,IGNORE_UNAIVALABLE_FOLLOWERS_DETAIL)
 	self:AddToggle("IGP",true,L['Ignore "maxed"'],L["Level 100 epic followers are not used for xp only missions."])
-	self:AddToggle("NOFILL",false,L["Do not prefill mission page"],L["Disables automatic population of mission page screen. You can also press control while clicking to disable it for a single mission"])
+	self:AddToggle("NOFILL",false,L["No mission prefill"],L["Disables automatic population of mission page screen. You can also press control while clicking to disable it for a single mission"])
 	self:AddSelect("MSORT","Garrison_SortMissions_Original",
 	{
 		Garrison_SortMissions_Original=L["Original method"],
@@ -601,26 +603,15 @@ function addon:CheckMP()
 			MPGoodGuy=true
 			return
 		end
-		MP=true
-		self:AddToggle("CKMP",true,L["Use GC Interface"],L["Switches between Garrison Commander and Master Plan mission interface. This also allow you to see Garrison Mission Manager buttons.\n If doesnt work, tell me, and I will try to discover which new way of hiding GC and GMM had MP found....."])
-		if (GarrisonMissionFrameTab3) then -- Active Missions
-			GarrisonMissionFrameTab3:HookScript("OnClick",function(this)
-			GarrisonMissionList_SetTab(GarrisonMissionFrameMissionsTab2)
-			MPPage=3
-			end)
-		end
-		if (GarrisonMissionFrameTab1) then --Available Missions
-			GarrisonMissionFrameTab1:HookScript("OnClick",function(this)
-			GarrisonMissionList_SetTab(GarrisonMissionFrameMissionsTab1)
-			MPPage=1
-			end)
-		end
-		if (GarrisonMissionFrameTab2) then -- Followers list
-			GarrisonMissionFrameTab2:HookScript("OnClick",function(this)
-			GarrisonMissionFrame_SelectTab(2)
-			MPPage=2
-			end)
+		if GetAddOnMetadata("MasterPlan","Version")>="0.23" then
+			-- New compatible version
+			self:AddToggle("CKMP",true,L["Use GC Interface"],L["Switches between Garrison Commander and Master Plan mission interface. Tested with MP >0.23"])
+			MPGoodGuy=true
+			MPSwitch=true
 		end
+		MP=true
+		MPSwitch=true
+		self:AddToggle("CKMP",true,L["Use GC Interface"],L["Switches between Garrison Commander and Master Plan mission interface. Tested with MP >0.20"])
 	end
 end
 function addon:CheckGMM()
@@ -635,6 +626,13 @@ function addon:ApplyIGM(value)
 end
 function addon:ApplyCKMP(value)
 	self:Clock()
+	if (MasterPlanMissionList) then
+		if (value) then
+			MasterPlanMissionList:Hide()
+		else
+			MasterPlanMissionList:Show()
+		end
+	end
 	self:RefreshMission()
 end
 function addon:ApplyDBG(value)
@@ -1152,13 +1150,10 @@ function addon:SetThreatColor(obj,missionID)
 end

 function addon:HookedGarrisonMissionButton_AddThreatsToTooltip(missionID)
+	if (GMC:IsShown()) then return end
 	self:RenderTooltip(missionID)
 end
 function addon:RenderTooltip(missionID)
---@debug@
-	GameTooltip:AddLine("ID:" .. tostring(missionID))
---@end-debug@
-	if (GMC:IsShown()) then return end
 	local mission=self:GetMissionData(missionID)
 	if (not mission) then
 --@debug@
@@ -1426,7 +1421,9 @@ function addon:BuildMissionCache(id,data)
 			xprint("No type",id,data.name)
 --@end-debug@
 		else
-			self.db.global.types[type]={name=type,description=typeDesc,icon=typeIcon}
+			if (not self.db.global.types[type]) then
+				self.db.global.types[type]={name=type,description=typeDesc,icon=typeIcon}
+			end
 		end
 		mission.slots={}
 		local slots=mission.slots
@@ -1441,8 +1438,10 @@ function addon:BuildMissionCache(id,data)
 		if (type) then
 			tinsert(slots,{name=TYPE,key=type,icon=typeIcon})
 		end
+		--collectgarbace("step",100)
 	end
 	mission.basePerc=select(4,G.GetPartyMissionInfo(id))
+
 end
 function addon:SetDbDefaults(default)
 	default.global=default.global or {}
@@ -1669,12 +1668,11 @@ local dbgFrame
 local lastCPU=0
 local startTime=GetTime()
 -- Keeping it as a nice example of coroutine management.. but not using it anymore
-local InProgress
 function addon:Clock()
 	if (GMFMissions.showInProgress)	 then
-		--collectgarbage("step",200)
+		collectgarbage("step",200)
 	else
-		--collectgarbage("step",100)
+		collectgarbage("step",100)
 	end
 --@debug@
 	if (not dbgFrame) then
@@ -1692,8 +1690,10 @@ function addon:Clock()
 	if (m~=lastmin) then
 		lastmin=m
 	end
-	UpdateAddOnCPUUsage()
-	UpdateAddOnMemoryUsage()
+	if (trc) then
+		UpdateAddOnCPUUsage()
+		UpdateAddOnMemoryUsage()
+	end
 	local cpu=GetAddOnCPUUsage("GarrisonCommander")
 	dbgFrame.Text:SetText(format("GC Cpu %3.2f/%2.2f/%2.2f Mem %4.3fMB ",
 		cpu,
@@ -1703,7 +1703,7 @@ function addon:Clock()
 	lastCPU=cpu
 --@end-debug@
 	dbcache.lastseen=time()
-	if (not MP) then return end
+	if (not MP or MPGoodGuy) then return  end
 	MPShown=not self:GetBoolean("CKMP")
 	local children={GMFMissions:GetChildren()}
 	for i=1,#children do
@@ -1721,7 +1721,7 @@ function addon:Clock()
 		GarrisonMissionFrameMissionsListScrollFrame:Hide()
 	else
 		GarrisonMissionFrameMissionsListScrollFrame:Show()
-		GarrisonMissionFrameMissionsListScrollFrame:SetParent(GarrisonMissionFrameMissions)
+		GarrisonMissionFrameMissionsListScrollFrame:SetParent(GMFMissions)
 	end
 --@debug@
 	for k,d in pairs(coroutines) do
@@ -1766,10 +1766,10 @@ end
 function addon:ShowMissionControl()
 	if (not GMC:IsShown()) then
 		GarrisonMissionFrame_SelectTab(999)
-		GarrisonMissionFrame.FollowerTab:Hide()
-		GarrisonMissionFrame.FollowerList:Hide()
-		GarrisonMissionFrame.MissionTab:Hide()
-		GarrisonMissionFrame.TitleText:SetText("Garrison Commander Mission Control")
+		GMF.FollowerTab:Hide()
+		GMF.FollowerList:Hide()
+		GMF.MissionTab:Hide()
+		GMF.TitleText:SetText("Garrison Commander Mission Control")
 		GMC:Show()
 		GMC.startButton:Click()
 		GMC.tabMC:SetChecked(true)
@@ -2133,14 +2133,15 @@ function addon:CreateOptionsLayer(...)
 	local o=AceGUI:Create("SimpleGroup") -- a transparent frame
 	o:SetLayout("Flow")
 	o:SetCallback("OnClose",function(widget) widget:Release() end)
+	local totsize=0
 	for i=1,select('#',...) do
-		self:AddOptionToOptionsLayer(o,select(i,...))
+		totsize=totsize+self:AddOptionToOptionsLayer(o,select(i,...))
 	end
-	return o
+	return o,totsize
 end
 function addon:AddOptionToOptionsLayer(o,flag,maxsize)
-	maxsize=tonumber(maxsize) or 150
-	if (not flag) then return end
+	maxsize=tonumber(maxsize) or 140
+	if (not flag) then return 0 end
 	local info=self:GetVarInfo(flag)
 	if (info) then
 		local data={option=info}
@@ -2188,11 +2189,21 @@ function addon:AddOptionToOptionsLayer(o,flag,maxsize)
 		end)
 		o:AddChildren(widget)
 	end
+	return maxsize
 end

 function addon:Options()
 	-- Main Garrison Commander Header
 	GCF=CreateFrame("Frame","GCF",UIParent,"GarrisonCommanderTitle")
+--@alpha@
+	local fs=GCF:CreateFontString(nil, "BACKGROUND", "WorldMapTextFont")
+	fs:SetAllPoints()
+	fs:SetJustifyH("CENTER")
+	fs:SetJustifyV("CENTER")
+	fs:SetText("A l p h a   V e r s i o n")
+	fs:SetTextColor(C.Silver())
+	fs:SetAlpha(0.6)
+--@end-alpha@
 	-- Removing wood corner. I do it here to not derive an xml frame. This shoud play better with ui extensions
 	GCF.CloseButton:Hide()
 	for _,f in pairs({GCF:GetRegions()}) do
@@ -2299,10 +2310,10 @@ function addon:ScriptTrace(hook,frame,...)
 --@end-debug@
 end
 function addon:IsProgressMissionPage()
-	return GMF:IsShown() and GMFMissions:IsShown() and GMFMissions.showInProgress and not GMFFollowers:IsShown() and not GMF.MissionComplete:IsShown()
+	return GMF:IsShown() and GMF.MissionTab and GMF.MissionTab.MissionList.showInProgress
 end
 function addon:IsAvailableMissionPage()
-	return GMF:IsShown() and GMFMissions:IsShown() and not GMFMissions.showInProgress  and not GMFFollowers:IsShown() and not GMF.MissionComplete:IsShown()
+	return GMF:IsShown() and GMF.MissionTab:IsShown() and not GMF.MissionTab.MissionList.showInProgress
 end
 function addon:IsFollowerList()
 	return GMF:IsShown() and GMFFollowers:IsShown()
@@ -2315,22 +2326,25 @@ end
 function addon:IsMissionPage()
 	return GMF:IsShown() and GMFMissionPage:IsShown() and GMFFollowers:IsShown()
 end
-function addon:HookedGarrisonMissionList_SetTab(tab)
-	if (tab==GarrisonMissionFrameMissionsTab2) then
-		InProgress=true
-	else
-		InProgress=false
-	end
-	xprint("Inprogress",InProgress)
-end
+---
+-- Switches between missions (1) and followers (others) panels
 function addon:HookedGarrisonMissionFrame_SelectTab(id)
-	if (id~=1) then
-		InProgress=false
-	end
 	GMC:Hide()
 	GMC.tabMC:SetChecked(false)
 	wipe(GMCUsedFollowers)
 end
+---
+-- Switchs between active and availabla missions depending on tab object
+do
+	local original=GarrisonMissionList_SetTab
+		function GarrisonMissionList_SetTab(...)
+		-- I dont actually care wich page we are shoing, I know I must redraw missions
+		original(...)
+		for i=1,#GMFMissionListButtons do
+			GMFMissionListButtons.lastMissionID=nil
+		end
+	end
+end
 function addon:HookedGarrisonMissionFrame_HideCompleteMissions()
 	self:BuildMissionsCache(true,true)
 end
@@ -2409,9 +2423,9 @@ function addon:HookedGarrisonFollowerButton_UpdateCounters(frame,follower,showCo
 end
 function addon:HookedGarrisonFollowerListButton_OnClick(frame,button)
 --@debug@
-	trace("Click",frame:GetName(),button,GarrisonMissionFrame.FollowerTab.Model:IsShown())
+	trace("Click",frame:GetName(),button,GMF.FollowerTab.Model:IsShown())
 --@end-debug@
-	if (button=="LeftButton" and GarrisonMissionFrame.FollowerTab.FollowerID ~= frame.info.followerID) then
+	if (button=="LeftButton" and GMF.FollowerTab.FollowerID ~= frame.info.followerID) then
 		if (frame.info.isCollected) then
 			self:HookedGarrisonFollowerPage_ShowFollower(frame.info,frame.info.followerID)
 		end
@@ -2710,14 +2724,13 @@ function addon:SetUp(...)
 --/Interface/FriendsFrame/UI-Toast-FriendOnlineIcon
 end
 function addon:AddMenu()
-	GCF.Menu=self:CreateOptionsLayer(MP and 'CKMP' or nil,'BIGSCREEN','MOVEPANEL','IGM','IGP','NOFILL')
-	self:AddOptionToOptionsLayer(GCF.Menu,'MSORT')
-	self:AddOptionToOptionsLayer(GCF.Menu,'ShowMissionControl')
+	local menu,size=self:CreateOptionsLayer(MP and 'CKMP' or nil,'BIGSCREEN','MOVEPANEL','IGM','IGP','NOFILL','MSORT')
+	--self:AddOptionToOptionsLayer(GCF.Menu,'MSORT')
+	--self:AddOptionToOptionsLayer(GCF.Menu,'ShowMissionControl')
 --@debug@
-	self:AddOptionToOptionsLayer(GCF.Menu,'DBG')
-	self:AddOptionToOptionsLayer(GCF.Menu,'TRC')
+	self:AddOptionToOptionsLayer(menu,'DBG')
+	self:AddOptionToOptionsLayer(menu,'TRC')
 --@end-debug@
-	local menu=GCF.Menu
 	local frame=menu.frame
 	frame:Show()
 	menu:ClearAllPoints()
@@ -2725,6 +2738,7 @@ function addon:AddMenu()
 	menu:SetWidth(GCF:GetWidth()-50)
 	menu:SetHeight(GCF:GetHeight()-50)
 	menu:DoLayout()
+	GCF.Menu=menu
 end
 function addon:RemoveMenu()
 	if (GCF.Menu) then
@@ -2732,7 +2746,12 @@ function addon:RemoveMenu()
 		GCF.Menu=nil
 	end
 end
-
+function addon:AddMissionId(b)
+	if (b.info and b.info.missionID) then
+		GameTooltip:AddDoubleLine("MissionID",b.info.missionID)
+		GameTooltip:Show()
+	end
+end
 ---
 -- Additional setup
 -- This method is called every time garrison mission panel is open because
@@ -2759,9 +2778,8 @@ function addon:StartUp(...)
 	end
 	self:SafeSecureHook("GarrisonMissionFrame_HideCompleteMissions")	-- Mission reward completed
 	self:SafeSecureHook("GarrisonMissionPage_ShowMission")
-	self:SafeSecureHook("GarrisonMissionList_UpdateMissions")
 	self:SafeSecureHook("GarrisonMissionFrame_SelectTab")
-	self:SafeSecureHook("GarrisonMissionList_SetTab")
+	-- GarrisonMissionList_SetTab is overrided

 	self:SafeHookScript(GMFMissions,"OnShow")--,"GrowPanel")
 	self:SafeHookScript(GMFFollowers,"OnShow")--,"GrowPanel")
@@ -2770,18 +2788,19 @@ function addon:StartUp(...)
 	self:SafeSecureHook("GarrisonFollowerButton_UpdateCounters")
 	-- Mission management
 	self:SafeHookScript(GMF.MissionComplete.NextMissionButton,"OnClick","OnClick_GarrisonMissionFrame_MissionComplete_NextMissionButton",true)
-	self:SafeSecureHook("GarrisonMissionFrame_ShowCompleteMissions")
-	self:SafeSecureHook("GarrisonMissionFrame_CheckCompleteMissions")
-	self:SafeSecureHook("MissionCompletePreload_LoadMission")
 	-- Hooking mission buttons on click
 	for i=1,#GMFMissionListButtons do
 		local b=GMFMissionListButtons[i]
 		self:SafeHookScript(b,"OnClick","OnClick_GarrisonMissionButton",true)
+--@debug@
+		self:SafeHookScript(b,"OnEnter","AddMissionId",true)
+--@end-debug@
 	end
 	self:ScheduleRepeatingTimer("Clock",1)
 	self:BuildMissionsCache(true,true)
 	self:BuildRunningMissionsCache()
 	self:Trigger("MSORT")
+	self:Trigger("CKMP")
 end
 function addon:MarkAsNew(obj,key,message)
 	if (not db.news[key]) then
@@ -2801,18 +2820,23 @@ function addon:PermanentEvents()
 	self:SafeRegisterEvent("GARRISON_FOLLOWER_ADDED")
 	self:SafeRegisterEvent("GARRISON_FOLLOWER_REMOVED")
 	self:RegisterBucketEvent("GARRISON_MISSION_LIST_UPDATE",2,"EventGARRISON_MISSION_LIST_UPDATE")
-
+	self:SafeRegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE")
 --@debug@
 	self:DebugEvents()
 --@end-debug@
 end
 function addon:DebugEvents()
-	self:SafeRegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE") -- Should be used only when has true as parameter
 	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")
+	self:SafeSecureHook("GarrisonMissionList_UpdateMissions")
+	self:SafeSecureHook("GarrisonMissionFrame_ShowCompleteMissions")
+	self:SafeSecureHook("GarrisonMissionFrame_CheckCompleteMissions")
+	self:SafeSecureHook("MissionCompletePreload_LoadMission")
+
+
 end
 function addon:checkMethod(method,hook)
 	if (type(self[method])=="function") then
@@ -2980,6 +3004,7 @@ function addon:GetFollowerStatusForMission(followerID,skipbusy)
 	end
 end
 function addon:GetFollowerStatus(followerID,withTime,colored)
+	if (not followerID) then return UNAVAILABLE end
 	local status=G.GetFollowerStatus(followerID)
 	if (status and status== GARRISON_FOLLOWER_ON_MISSION and withTime) then
 		local running=dbcache.running[dbcache.runningIndex[followerID]]
@@ -3090,28 +3115,31 @@ function addon:RenderFollowerButton(frame,followerID,missionID)
 		frame.NotFull:Hide()
 	end
 	if (not followerID) then
-		frame.PortraitFrame.Empty:Show()
 		if (frame.Name) then
+			frame.PortraitFrame.Empty:Show()
 			frame.Name:Hide()
 			frame.Class:Hide()
 			frame.Status:Hide()
 		else
-			frame.PortraitFrame.Empty:SetAlpha(0.5)
-			frame.PortraitFrame.Portrait:Hide()
+			frame.PortraitFrame.Empty:Hide()
+			frame.PortraitFrame.Portrait:Show()
 			frame.PortraitFrame.LevelBorder:SetAtlas("GarrMission_PortraitRing_iLvlBorder");
 			frame.PortraitFrame.LevelBorder:SetWidth(70);
-			frame.PortraitFrame.Level:SetText("Missing")
+			frame.PortraitFrame.Level:SetText(MISSING)
+			frame.PortraitFrame.Level:SetTextColor(1,0,0,0.7)
 		end
 		frame.PortraitFrame.LevelBorder:SetAtlas("GarrMission_PortraitRing_LevelBorder");
 		frame.PortraitFrame.LevelBorder:SetWidth(58);
 		GarrisonFollowerPortrait_Set(frame.PortraitFrame.Portrait)
-		frame.info=nil
+		frame.PortraitFrame.PortraitRingQuality:SetVertexColor(C.Silver());
+		frame.PortraitFrame.LevelBorder:SetVertexColor(C.Silver());
 		return
 	end
+	frame.PortraitFrame.Level:SetTextColor(1,1,1,1)
 	frame.PortraitFrame.Portrait:Show()
-	frame.info=self:GetFollowerData(followerID)
-	local info=frame.info
+	local info=self:GetFollowerData(followerID)
 	if (not info) then return end
+	frame.info=info
 	frame.missionID=missionID
 	if (frame.Name) then
 		frame.Name:Show()
@@ -3128,7 +3156,7 @@ function addon:RenderFollowerButton(frame,followerID,missionID)
 	frame.PortraitFrame.Empty:Hide();

 	local showItemLevel;
-	if (info.level == GarrisonMissionFrame.followerMaxLevel ) then
+	if (info.level == GMF.followerMaxLevel ) then
 		frame.PortraitFrame.LevelBorder:SetAtlas("GarrMission_PortraitRing_iLvlBorder");
 		frame.PortraitFrame.LevelBorder:SetWidth(70);
 		showItemLevel = true;
@@ -3209,8 +3237,8 @@ function addon:RenderExtraButton(button,numRewards)
 	local missionInfo=button.info
 	local missionID=missionInfo.missionID
 	panel.missionID=missionID
-	local mission=self:GetMissionData(missionID)
-	if not mission then return end -- something went wrong while refreshing
+	local mission=missionInfo
+	if not mission then print "not yet updated missions" return end -- something went wrong while refreshing
 	if (not bigscreen) then
 		local index=mission.numFollowers+numRewards-3
 		local position=(index * -65) - 130
@@ -3221,8 +3249,7 @@ function addon:RenderExtraButton(button,numRewards)
 		local perc=select(4,G.GetPartyMissionInfo(missionID))
 		panel.Percent:SetFormattedText(GARRISON_MISSION_PERCENT_CHANCE,perc)
 		panel.Age:Hide()
-		local q=self:GetDifficultyColor(perc)
-		panel.Percent:SetTextColor(q.r,q.g,q.b)
+		panel.Percent:SetTextColor(self:GetDifficultyColors(perc))
 		for i=1,3 do
 			local frame=button.gcPANEL.Party[i]
 			if (missionInfo.followers[i]) then
@@ -3236,6 +3263,7 @@ function addon:RenderExtraButton(button,numRewards)
 	end
 	local party=parties[missionID]
 	if (#party.members==0) then
+		local mission=self:GetMissionData(missionID) -- matchmaker and fillcounters need our enriched mission
 		self:FillCounters(missionID,mission)
 		self:MatchMaker(missionID,mission,party)
 	end
@@ -3259,13 +3287,11 @@ function addon:RenderExtraButton(button,numRewards)
 	end
 	panel=button.gcINDICATOR
 	panel.Percent:SetFormattedText(GARRISON_MISSION_PERCENT_CHANCE,perc)
-	local q=self:GetDifficultyColor(perc)
-	panel.Percent:SetTextColor(q.r,q.g,q.b)
+	panel.Percent:SetTextColor(self:GetDifficultyColors(perc))
 	panel.Percent:SetWidth(80)
 	panel.Percent:SetJustifyH("RIGHT")
 	if (age) then
 		local expire=ns.wowhead[missionID]
-		if expire then expire=expire.cd else expire =9999999 end
 		if (expire==9999999) then
 			panel.Age:SetText("Expires: Far far away")
 			panel.Age:SetTextColor(C.White())
@@ -3288,7 +3314,7 @@ function addon:RenderExtraButton(button,numRewards)
 end
 function addon:CheckExpire(missionID)
 	local age=tonumber(dbcache.seen[missionID])
-	local expire=ns.wowhead[missionID].cd
+	local expire=ns.wowhead[missionID]
 	print("Age",date("%m/%d/%y %H:%M:%S",age))
 	print("Now",date("%m/%d/%y %H:%M:%S"))
 	print("Expire",expire,ns.expire[missionID])
@@ -3428,7 +3454,8 @@ function addon:RenderButton(button,rewards,numRewards)
 --@end-debug@
 	end
 	local missionID=button.info.missionID
-	--if (GMF.MissionTab.MissionList.showInProgress) then return end
+	if GMF.MissionTab.MissionList.showInProgress and missionID==button.lastMissionID then return end
+	button.lastMissionID=missionID
 	if (bigscreen) then
 		local width=GMF.MissionTab.MissionList.showInProgress and BIGBUTTON or SMALLBUTTON
 		button:SetWidth(width+600)
@@ -3506,6 +3533,34 @@ function addon:RenderButton(button,rewards,numRewards)
 				button.Env:Hide()
 			end
 		end
+		if (numRewards > 0) then
+			local index=1
+			for id,reward in pairs(rewards) do
+				local Reward = button.Rewards[index];
+				Reward.Quantity:SetTextColor(C.Yellow())
+				if (reward.followerXP) then
+					Reward.Quantity:SetText(reward.followerXP)
+					Reward.Quantity:Show()
+				elseif (reward.currencyID==0) then
+					Reward.Quantity:SetFormattedText("%d",reward.quantity/10000)
+					Reward.Quantity:Show()
+				elseif (reward.itemID and reward.itemID==120205) then
+					Reward.Quantity:SetFormattedText("%d",self:GetMissionData(missionID,'xp') or 1)
+					Reward.Quantity:Show()
+				elseif (reward.itemID and reward.quantity==1) then
+					local _,_,q,i=GetItemInfo(reward.itemID)
+					Reward.Quantity:SetText(i)
+					local c=ITEM_QUALITY_COLORS[q]
+					if (not c) then
+						Reward.Quantity:SetTextColor(1,1,1)
+					else
+						Reward.Quantity:SetTextColor(c.r,c.g,c.b)
+					end
+					Reward.Quantity:Show()
+				end
+				index=index+1
+			end
+		end
 	else
 		if (button.Env) then button.Env:Hide() end
 	end
@@ -3514,407 +3569,17 @@ function addon:RenderButton(button,rewards,numRewards)
 			button.GcThreats[i]:Hide()
 		end
 	end
-	if (numRewards > 0) then
-		local index=1
-		for id,reward in pairs(rewards) do
-			local Reward = button.Rewards[index];
-			Reward.Quantity:SetTextColor(C.Yellow())
-			if (reward.followerXP) then
-				Reward.Quantity:SetText(reward.followerXP)
-				Reward.Quantity:Show()
-			elseif (reward.currencyID==0) then
-				Reward.Quantity:SetFormattedText("%d",reward.quantity/10000)
-				Reward.Quantity:Show()
-			elseif (reward.itemID and reward.itemID==120205) then
-				Reward.Quantity:SetFormattedText("%d",self:GetMissionData(missionID,'xp') or 1)
-				Reward.Quantity:Show()
-			elseif (reward.itemID and reward.quantity==1) then
-				local _,_,q,i=GetItemInfo(reward.itemID)
-				Reward.Quantity:SetText(i)
-				local c=ITEM_QUALITY_COLORS[q]
-				if (not c) then
-					Reward.Quantity:SetTextColor(1,1,1)
-				else
-					Reward.Quantity:SetTextColor(c.r,c.g,c.b)
-				end
-				Reward.Quantity:Show()
-			end
-			index=index+1
-		end
-	end
 	if (button.fromFollowerPage) then
-		--button.Title:ClearAllPoints()
-		--button.Title:SetPoint("TOPLEFT",165,-5)
-		--button.Summary:ClearAllPoints()
-		--button.Summary:SetPoint("BOTTOMLEFT",165,5)
-		--button:SetHeight(70)
+		print("From follower page")
 		return
 	end
 	if (not button.gcPANEL) then
 		self:BuildExtraButton(button)
 	end
+	print("Renderng extrabutton")
 	self:RenderExtraButton(button,numRewards)
 end

---@do-not-package@
-_G.GAC=addon
---[[
-
-GMFMissions.CompleteDialog.BorderFrame.CompleteAll
-Garrison page structure
-Tab selection:
-Managed by
-GarrisonMissionFrameTab(1|2) onclick:
-->GarrisonMissionFrameTab_OnClick(self)
---->GarrisonMissionFrame_SelectTab(self:GetID()) - 1 for Missions, 2 for followers
-
-Main Container is GarrisonMissionFrame
-Followers tab selected:
-->GarrisonMissionFrameFollowers -> anchored GarrisonMissionFrame TOPLEFT 33,-64
--->GarrisonMissionFrameFollowersListScrollFrame
---->GarrisonMissionFrameFollowersListScrooFrameScrollChild
----->GarrisonMissionFrameFollowersListScrooFrameButton(1..9)
-->GarrisonMissionFrame.FollowerTab -> abcuored GarrisonMissionFrame TOPRIGHT -35 -64
-Missions tab selected
-->GarrisonMissionFrameMissions -> anchored (parent)e TOPLEFT 35,-65
-
-
-
-
-GarrisonMissionFrameMissionsListScrollFrameButtonx.info:
-Dump: value=GarrisonMissionFrameMissionsListScrollFrameButton1.info
-[1]={
-	description="In a remote corner of Talador, a small faction of draenei has embraced the worship of Sargeras. Stop their cult before it spreads.",
-	cost=10,
-	duration="4 hr",
-	durationSeconds=14400,
-	level=100,
-	type="Combat",
-	locPrefix="GarrMissionLocation-Talador",
-	rewards={
-		[290]={
-			title="Money Reward",
-			quantity=600000,
-			icon="Interface\\Icons\\inv_misc_coin_01",
-			currencyID=0
-		}
-	},
-	numRewards=1,
-	numFollowers=2,
-	state=-2,
-	iLevel=0,
-	name="Cult of Sargeras",
-	followers={
-	},
-	location="Talador",
-	isRare=false,
-	typeAtlas="GarrMission_MissionIcon-Combat",
-	missionID=126
-}
-Dump: value=G.GetFollowerInfo("0x000000000002F5E1")
-[1]={
-	displayHeight=0.5,
-	iLevel=600,
-	scale=0.60000002384186,
-	classAtlas="GarrMission_ClassIcon-Druid",
-	garrFollowerID="0x0000000000000022",
-	displayScale=1,
-	status="On Mission",
-	level=100,
-	quality=4,
-	portraitIconID=1066112,
-	isFavorite=false,
-	xp=0,
-	className="Guardian Druid",
-	classSpec=8,
-	name="Qiana Moonshadow",
-	followerID="0x000000000002F5E1",
-	height=1.3999999761581,
-	displayID=55047,
-	levelXP=0,
-	isCollected=true
-}
-value=GarrisonMissionFrame.MissionTab.MissionList.availableMissions[13]
-[1]={
-	description="Scouts report a many-headed beast named Festerbloom waylaying travelers crossing the Murkbog.  Clear the path for everyone's sake.",
-	cost=20,
-	duration="10 hr",
-	durationSeconds=36000,
-	level=96,
-	type="Combat",
-	locPrefix="GarrMissionLocation-SpiresofArak",
-	rewards={
-		[778]={
-			title="Bonus Follower XP",
-			followerXP=1400,
-			tooltip="+1,400 XP",
-			icon="Interface\\Icons\\XPBonus_Icon",
-			name="+1,400 XP"
-		}
-	},
-	numRewards=1,
-	numFollowers=3,
-	state=-2,
-	iLevel=0,
-	name="Murkbog Terror",
-	followers={
-	},
-	location="Spires of Arak",
-	isRare=false,
-	typeAtlas="GarrMission_MissionIcon-Combat",
-	missionID=374
-}
-Dump: value=GarrisonMissionFrame.MissionTab.MissionList.inProgressMissions
-[1]={
-	description="The voidlords and voidcallers plaguing Shadowmoon Valley are being summoned by someone. Find and kill whoever is responsible.",
-	cost=15,
-	duration="6 hr",
-	durationSeconds=21600,
-	level=100,
-	timeLeft="1 hr 12 min",
-	type="Combat",
-	inProgress=true,
-	locPrefix="GarrMissionLocation-ShadowmoonValley",
-	rewards={
-		[251]={
-			title="Bonus Follower XP",
-			followerXP=8000,
-			tooltip="+8,000 XP",
-			icon="Interface\\Icons\\XPBonus_Icon",
-			name="+8,000 XP"
-		}
-	},
-	numRewards=1,
-	numFollowers=3,
-	state=-1,
-	iLevel=0,
-	name="Twisting the Nether",
-	followers={
-		[1]="0x000000000002F5E1",
-		[2]="0x0000000000079D62",
-		[3]="0x00000000001307EF"
-	},
-	location="Shadowmoon Valley",
-	isRare=false,
-	typeAtlas="GarrMission_MissionIcon-Combat",
-	missionID=114
-}
-Dump: value=G.GetMissionInfo(119)
-local location, xp, environment, environmentDesc, environmentTexture, locPrefix, isExhausting, enemies = C_Garrison.GetMissionInfo(missionID);
-[1]="Nagrand",
-[2]=1500,
-[3]="Orc",
-[4]="Lok'tar ogar!",
-[5]="Interface\\ICONS\\Achievement_Boss_General_Nazgrim.blp",
-[6]="GarrMissionLocation-Nagrand",
-[7]=false,
-[8]={
-	[1]={
-		portraitFileDataID=1067358,
-		displayID=56189,
-		name="Warsong Earthcaller",
-		mechanics={
-			[4]={
-				description="A dangerous harmful effect that should be dispelled.",
-				name="Magic Debuff",
-				icon="Interface\\ICONS\\Spell_Shadow_ShadowWordPain.blp"
-			},
-			[8]={
-				description="A dangerous spell that should be interrupted.",
-				name="Powerful Spell",
-				icon="Interface\\ICONS\\Spell_Shadow_ShadowBolt.blp"
-			}
-		}
-	}
-}
-local totalTimeString, totalTimeSeconds, isMissionTimeImproved, successChance, partyBuffs, isEnvMechanicCountered, xpBonus, materialMultiplier = C_Garrison.GetPartyMissionInfo(MISSION_PAGE_FRAME.missionInfo.missionID);
-Dump: value=C_Garrison.GetPartyMissionInfo(118)
-[1]="8 hr",
-[2]=28800,
-[3]=false,
-[4]=0,
-[5]={
-},
-[6]=false,
-[7]=0,
-[8]=1
-Dump: value=table returned by GetFollowerInfo for a collected follower
-[1]={
-	displayHeight=0.5,
-	iLevel=600,
-	isCollected=true,
-	classAtlas="GarrMission_ClassIcon-Druid",
-	garrFollowerID="0x0000000000000022",
-	displayScale=1,
-	level=100,
-	quality=4,
-	portraitIconID=1066112,
-	isFavorite=false,
-	xp=0,
-	className="Guardian Druid",
-	classSpec=8,
-	name="Qiana Moonshadow",
-	followerID="0x000000000002F5E1",
-	height=1.3999999761581,
-	displayID=55047,
-	scale=0.60000002384186,
-	levelXP=0
-}
-	local location, xp, environment, environmentDesc, environmentTexture, locPrefix, isExhausting, enemies = G.GetMissionInfo(missionID)
---]]
-function addon:GetScroller(title,type)
-	type=type or "Frame"
-	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:AddRow(obj,text,...)
-		local l=AceGUI:Create("Label")
-		l:SetText(text)
-		l:SetColor(...)
-		l:SetFullWidth(true)
-		obj:AddChild(l)
-end
-function addon:cutePrint(scroll,level,k,v)
-	if (type(level)=="table") then
-		for k,v in pairs(level) do
-			self:cutePrint(scroll,"",k,v)
-		end
-		return
-	end
-	if (type(v)=="table") then
-		self:AddRow(scroll,level..C(k,"Azure")..":" ..C("Table","Orange"))
-		for kk,vv in pairs(v) do
-			self:cutePrint(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:AddRow(scroll,level..C(k,"White")..":" ..C(v,"Yellow"))
-	end
-end
-function addon:DumpFollower(name)
-	local follower=self:GetFollowerData(name)
-	if (follower) then
-		local scroll=self:GetScroller(follower.name)
-		self:cutePrint(scroll,follower)
-	end
-
-end
-function addon:DumpFollowerMissions(missionID)
-	local scroll=self:GetScroller("FollowerMissions " .. self:GetMissionData(missionID,'name'))
-	self:cutePrint(scroll,followerMissions.missions[missionID])
-end
-function addon:DumpIfnored()
-	local scroll=self:GetScroller("Ignored")
-	self:cutePrint(scroll,self.privatedb.profile.ignored)
-end
-function addon:DumpMission(missionID)
-	local scroll=self:GetScroller("MissionCache " .. self:GetMissionData(missionID,'name'))
-	self:cutePrint(scroll,cache.missions[missionID])
-end
-function addon:DumpMissions()
-	local scroll=self:GetScroller("MissionCache")
-	for id,data in pairs(cache.missions) do
-		self:cutePrint(scroll,id .. '.'..data.name)
-	end
-end
----
--- Debug function
---@param missionID Identificativo missione
-function addon:DumpCounters(missionID)
-	local scroll=self:GetScroller("Counters " .. self:GetMissionData(missionID,'name'))
-	self:cutePrint(scroll,counters[missionID])
-	self:cutePrint(scroll,"Lista per follower","","")
-	self:cutePrint(scroll,counterFollowerIndex[missionID])
-	self:cutePrint(scroll,"Lista per threat","","")
-	self:cutePrint(scroll,counterThreatIndex[missionID])
-end
-function addon:Dump(title,data)
-	local scroll=self:GetScroller(title)
-	self:cutePrint(scroll,data)
-
-end
-function addon:DumpCounterers(missionID)
-	local scroll=self:GetScroller("Counterers " .. self:GetMissionData(missionID,'name'))
-	self:cutePrint(scroll,cache.missions[missionID].counterers)
-end
-function addon:DumpParty(missionID)
-	local scroll=self:GetScroller("Party " .. self:GetMissionData(missionID,'name'))
-	self:cutePrint(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@
 -- Courtesy of Motig
 -- Concept and interface reused with permission
 -- Mission building rewritten from scratch
@@ -4052,7 +3717,6 @@ do
 	local currentMission=0
 	local x=0
 	function addon:GMCCalculateMissions(this,elapsed)
-		InProgress=false
 		db.news.MissionControl=true
 		timeElapsed = timeElapsed + elapsed
 		if (#aMissions == 0 ) then
@@ -4187,7 +3851,12 @@ function addon:GMCBuildPanel()
 	GMC.startButton:SetScript('OnLeave', function() GameTooltip:Hide() end)
 	GMC.runButton = CreateFrame('BUTTON', nil,list.frame, 'GameMenuButtonTemplate')
 	GMC.runButton:SetText('Send all mission at once')
-	GMC.runButton:SetScript('OnEnter', function() GameTooltip:SetOwner(GMC.runButton, 'ANCHOR_TOPRIGHT') GameTooltip:AddLine('Submit all yopur mission at once. No question asked.') GameTooltip:Show() end)
+	GMC.runButton:SetScript('OnEnter', function()
+		GameTooltip:SetOwner(GMC.runButton, 'ANCHOR_TOPRIGHT')
+		GameTooltip:AddLine('Submit all yopur mission at once. No question asked.')
+		GameTooltip:AddLine('You can also send mission one by one clicking on each button.')
+		GameTooltip:Show()
+	end)
 	GMC.runButton:SetScript('OnLeave', function() GameTooltip:Hide() end)
 	GMC.runButton:SetWidth(148)
 	GMC.runButton:SetPoint('TOPRIGHT',-15,25)
@@ -4200,6 +3869,7 @@ function addon:GMCBuildPanel()
 end
 function addon:GMCRewardRefresh()
 	local single=GMC.settings.useOneChance
+	local ref
 	for i=1,#GMC.ignoreFrames do
 		local frame=GMC.ignoreFrames[i]
 		local allowed=GMC.settings.allowedRewards[frame.key]
@@ -4214,11 +3884,14 @@ function addon:GMCRewardRefresh()
 			frame.slider:Hide()
 			frame:SetPoint(a1,o,a2,100,y)
 		end
+		ref=frame
 	end
 	if (single) then
+		GMC.itf2:SetPoint('TOPLEFT',ref,'BOTTOMLEFT', -110, -15)
 		GMC.cp:SetDesaturated(false)
 		GMC.ct:SetTextColor(C.Green())
 	else
+		GMC.itf2:SetPoint('TOPLEFT',ref,'BOTTOMLEFT', 10, -15)
 		GMC.cp:SetDesaturated(true)
 		GMC.ct:SetTextColor(C.Silver())
 	end
@@ -4394,7 +4067,7 @@ function addon:GMCBuildRewards()
 	end
 	self:GMCRewardRefresh()
 	GMC.aif:SetSize(256, (scale*h+gap) * #t)
-	GMC.itf2:SetPoint('TOPLEFT',ref,'BOTTOMLEFT', 0, -15)
+	GMC.itf2:SetPoint('TOPLEFT',ref,'BOTTOMLEFT', 5, -15)
 	return GMC.aif
 end

@@ -4547,33 +4220,158 @@ function addon:GMCBuildMissionList()
 	return ml.widget

 end
---@debug@
+--@do-not-package@
+_G.GAC=addon
 --- Enable a trace for every function call. It's a VERY heavy debug
 --
-local memorysinks=setmetatable({},{__index=function(t,k) return 0 end})
+local memorysinks={}
+local lib=LibStub("LibInit")
 for k,v in pairs(addon) do
-	if (type(v))=="function" then
+	if (type(v))=="function" and not lib[k] then
 		local wrapped
 		do
 			local original=addon[k]
 			wrapped=function(...)
-				if not trc then
-					return original(addon,...)
-				else
-					local membefore=floor(UpdateAddOnMemoryUsage("GarrisonCommander"))
-					local a1,a2,a3,a4,a5,a6,a7,a8,a9=original(addon,...)
-					local memafter=floor(UpdateAddOnMemoryUsage("GarrisonCommander"))
-					return a1,a2,a3,a4,a5,a6,a7,a8,a9
+				if trc then
+					UpdateAddOnMemoryUsage()
+				end
+				local membefore=floor(GetAddOnMemoryUsage("GarrisonCommander"))
+				local s=GetTime()
+				local a1,a2,a3,a4,a5,a6,a7,a8,a9=original(...)
+				local e=GetTime()
+				local memafter=floor(GetAddOnMemoryUsage("GarrisonCommander"))
+				memorysinks[k].mem=memorysinks[k].mem+memafter-membefore
+				memorysinks[k].calls=memorysinks[k].calls+1
+				memorysinks[k].elapsed=memorysinks[k].elapsed+e-s
+				if (memafter-membefore > 100) then
+					pp(C(k,'Red'),'used ',memafter-membefore)
 				end
+				return a1,a2,a3,a4,a5,a6,a7,a8,a9
 			end
 		end
 		addon[k]=wrapped
+		memorysinks[k]={mem=0,elapsed=0,calls=0}
 	end
 end
+function addon:ResetSinks()
+	for k,v in pairs(memorysinks) do
+		memorysinks[k].mem=0
+		memorysinks[k].calls=0
+		memorysinks[k].elapsed=0
+	end
+end
+local sorted={}
 function addon:DumpSinks()
-	local scroll=self:GetScroller("Sinks")
-	self:cutePrint(scroll,memorysinks)
+	local scroll=self:GetScroller("Sinks",400,1000)
+	wipe(sorted)
+	for k,v in pairs(memorysinks) do
+		if v.mem > 0 then
+			tinsert(sorted,format("Mem %06d %-80s (calls: %3d) Mem per call:%3.2f  Elapsed %3.3f (per call %3.3f)",v.mem,k,v.calls,v.mem/v.calls,v.elapsed,v.elapsed/v.calls))
+		end
+	end
+	table.sort(sorted,function(a,b) return a>b end)
+	self:cutePrint(scroll,sorted)
+end
+function addon:GetScroller(title,type,h,w)
+	h=h or 800
+	w=w or 400
+	type=type or "Frame"
+	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(h)
+	scrollerWindow:SetWidth(w)
+	scrollerWindow:SetPoint("CENTER")
+	scrollerWindow:Show()
+	return scroll
+end
+function addon:AddRow(obj,text,...)
+		local l=AceGUI:Create("Label")
+		l:SetText(text)
+		l:SetColor(...)
+		l:SetFullWidth(true)
+		obj:AddChild(l)
+end
+function addon:cutePrint(scroll,level,k,v)
+	if (type(level)=="table") then
+		for k,v in pairs(level) do
+			self:cutePrint(scroll,"",k,v)
+		end
+		return
+	end
+	if (type(v)=="table") then
+		self:AddRow(scroll,level..C(k,"Azure")..":" ..C("Table","Orange"))
+		for kk,vv in pairs(v) do
+			self:cutePrint(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:AddRow(scroll,level..C(k,"White")..":" ..C(v,"Yellow"))
+	end
+end
+function addon:DumpFollower(name)
+	local follower=self:GetFollowerData(name)
+	if (follower) then
+		local scroll=self:GetScroller(follower.name)
+		self:cutePrint(scroll,follower)
+	end
+
+end
+function addon:DumpFollowerMissions(missionID)
+	local scroll=self:GetScroller("FollowerMissions " .. self:GetMissionData(missionID,'name'))
+	self:cutePrint(scroll,followerMissions.missions[missionID])
+end
+function addon:DumpIgnored()
+	local scroll=self:GetScroller("Ignored")
+	self:cutePrint(scroll,self.privatedb.profile.ignored)
+end
+function addon:DumpMission(missionID)
+	local scroll=self:GetScroller("MissionCache " .. self:GetMissionData(missionID,'name'))
+	self:cutePrint(scroll,cache.missions[missionID])
+end
+function addon:DumpMissions()
+	local scroll=self:GetScroller("MissionCache")
+	for id,data in pairs(cache.missions) do
+		self:cutePrint(scroll,id .. '.'..data.name)
+	end
+end
+---
+-- Debug function
+--@param missionID Identificativo missione
+function addon:DumpCounters(missionID)
+	local scroll=self:GetScroller("Counters " .. self:GetMissionData(missionID,'name'))
+	self:cutePrint(scroll,counters[missionID])
+	self:cutePrint(scroll,"Lista per follower","","")
+	self:cutePrint(scroll,counterFollowerIndex[missionID])
+	self:cutePrint(scroll,"Lista per threat","","")
+	self:cutePrint(scroll,counterThreatIndex[missionID])
+end
+function addon:Dump(title,data)
+	local scroll=self:GetScroller(title)
+	self:cutePrint(scroll,data)
+
+end
+function addon:DumpCounterers(missionID)
+	local scroll=self:GetScroller("Counterers " .. self:GetMissionData(missionID,'name'))
+	self:cutePrint(scroll,cache.missions[missionID].counterers)
+end
+function addon:DumpParty(missionID)
+	local scroll=self:GetScroller("Party " .. self:GetMissionData(missionID,'name'))
+	self:cutePrint(scroll,parties[missionID])
 end

 _G.GCF=GCF
---@end-debug@
\ No newline at end of file
+--@end-do-not-package@
diff --git a/doc.txt b/doc.txt
index 02b7e22..fb27416 100644
--- a/doc.txt
+++ b/doc.txt
@@ -39,4 +39,216 @@ Dump: value=C_Garrison.GetMissionRewardInfo(91)
 		itemID=112848,
 		quantity=1
 	}
-}
\ No newline at end of file
+}
+
+--[[
+
+GMFMissions.CompleteDialog.BorderFrame.CompleteAll
+Garrison page structure
+Tab selection:
+Managed by
+GarrisonMissionFrameTab(1|2) onclick:
+->GarrisonMissionFrameTab_OnClick(self)
+--->GarrisonMissionFrame_SelectTab(self:GetID()) - 1 for Missions, 2 for followers
+
+Main Container is GarrisonMissionFrame
+Followers tab selected:
+->GarrisonMissionFrameFollowers -> anchored GarrisonMissionFrame TOPLEFT 33,-64
+-->GarrisonMissionFrameFollowersListScrollFrame
+--->GarrisonMissionFrameFollowersListScrooFrameScrollChild
+---->GarrisonMissionFrameFollowersListScrooFrameButton(1..9)
+->GarrisonMissionFrame.FollowerTab -> abcuored GarrisonMissionFrame TOPRIGHT -35 -64
+Missions tab selected
+->GarrisonMissionFrameMissions -> anchored (parent)e TOPLEFT 35,-65
+
+
+
+
+GarrisonMissionFrameMissionsListScrollFrameButtonx.info:
+Dump: value=GarrisonMissionFrameMissionsListScrollFrameButton1.info
+[1]={
+	description="In a remote corner of Talador, a small faction of draenei has embraced the worship of Sargeras. Stop their cult before it spreads.",
+	cost=10,
+	duration="4 hr",
+	durationSeconds=14400,
+	level=100,
+	type="Combat",
+	locPrefix="GarrMissionLocation-Talador",
+	rewards={
+		[290]={
+			title="Money Reward",
+			quantity=600000,
+			icon="Interface\\Icons\\inv_misc_coin_01",
+			currencyID=0
+		}
+	},
+	numRewards=1,
+	numFollowers=2,
+	state=-2,
+	iLevel=0,
+	name="Cult of Sargeras",
+	followers={
+	},
+	location="Talador",
+	isRare=false,
+	typeAtlas="GarrMission_MissionIcon-Combat",
+	missionID=126
+}
+Dump: value=G.GetFollowerInfo("0x000000000002F5E1")
+[1]={
+	displayHeight=0.5,
+	iLevel=600,
+	scale=0.60000002384186,
+	classAtlas="GarrMission_ClassIcon-Druid",
+	garrFollowerID="0x0000000000000022",
+	displayScale=1,
+	status="On Mission",
+	level=100,
+	quality=4,
+	portraitIconID=1066112,
+	isFavorite=false,
+	xp=0,
+	className="Guardian Druid",
+	classSpec=8,
+	name="Qiana Moonshadow",
+	followerID="0x000000000002F5E1",
+	height=1.3999999761581,
+	displayID=55047,
+	levelXP=0,
+	isCollected=true
+}
+value=GarrisonMissionFrame.MissionTab.MissionList.availableMissions[13]
+[1]={
+	description="Scouts report a many-headed beast named Festerbloom waylaying travelers crossing the Murkbog.  Clear the path for everyone's sake.",
+	cost=20,
+	duration="10 hr",
+	durationSeconds=36000,
+	level=96,
+	type="Combat",
+	locPrefix="GarrMissionLocation-SpiresofArak",
+	rewards={
+		[778]={
+			title="Bonus Follower XP",
+			followerXP=1400,
+			tooltip="+1,400 XP",
+			icon="Interface\\Icons\\XPBonus_Icon",
+			name="+1,400 XP"
+		}
+	},
+	numRewards=1,
+	numFollowers=3,
+	state=-2,
+	iLevel=0,
+	name="Murkbog Terror",
+	followers={
+	},
+	location="Spires of Arak",
+	isRare=false,
+	typeAtlas="GarrMission_MissionIcon-Combat",
+	missionID=374
+}
+Dump: value=GarrisonMissionFrame.MissionTab.MissionList.inProgressMissions
+[1]={
+	description="The voidlords and voidcallers plaguing Shadowmoon Valley are being summoned by someone. Find and kill whoever is responsible.",
+	cost=15,
+	duration="6 hr",
+	durationSeconds=21600,
+	level=100,
+	timeLeft="1 hr 12 min",
+	type="Combat",
+	inProgress=true,
+	locPrefix="GarrMissionLocation-ShadowmoonValley",
+	rewards={
+		[251]={
+			title="Bonus Follower XP",
+			followerXP=8000,
+			tooltip="+8,000 XP",
+			icon="Interface\\Icons\\XPBonus_Icon",
+			name="+8,000 XP"
+		}
+	},
+	numRewards=1,
+	numFollowers=3,
+	state=-1,
+	iLevel=0,
+	name="Twisting the Nether",
+	followers={
+		[1]="0x000000000002F5E1",
+		[2]="0x0000000000079D62",
+		[3]="0x00000000001307EF"
+	},
+	location="Shadowmoon Valley",
+	isRare=false,
+	typeAtlas="GarrMission_MissionIcon-Combat",
+	missionID=114
+}
+Dump: value=G.GetMissionInfo(119)
+local location, xp, environment, environmentDesc, environmentTexture, locPrefix, isExhausting, enemies = C_Garrison.GetMissionInfo(missionID);
+[1]="Nagrand",
+[2]=1500,
+[3]="Orc",
+[4]="Lok'tar ogar!",
+[5]="Interface\\ICONS\\Achievement_Boss_General_Nazgrim.blp",
+[6]="GarrMissionLocation-Nagrand",
+[7]=false,
+[8]={
+	[1]={
+		portraitFileDataID=1067358,
+		displayID=56189,
+		name="Warsong Earthcaller",
+		mechanics={
+			[4]={
+				description="A dangerous harmful effect that should be dispelled.",
+				name="Magic Debuff",
+				icon="Interface\\ICONS\\Spell_Shadow_ShadowWordPain.blp"
+			},
+			[8]={
+				description="A dangerous spell that should be interrupted.",
+				name="Powerful Spell",
+				icon="Interface\\ICONS\\Spell_Shadow_ShadowBolt.blp"
+			}
+		}
+	}
+}
+local totalTimeString, totalTimeSeconds, isMissionTimeImproved, successChance, partyBuffs, isEnvMechanicCountered, xpBonus, materialMultiplier = C_Garrison.GetPartyMissionInfo(MISSION_PAGE_FRAME.missionInfo.missionID);
+Dump: value=C_Garrison.GetPartyMissionInfo(118)
+[1]="8 hr",
+[2]=28800,
+[3]=false,
+[4]=0,
+[5]={
+},
+[6]=false,
+[7]=0,
+[8]=1
+Dump: value=table returned by GetFollowerInfo for a collected follower
+[1]={
+	displayHeight=0.5,
+	iLevel=600,
+	isCollected=true,
+	classAtlas="GarrMission_ClassIcon-Druid",
+	garrFollowerID="0x0000000000000022",
+	displayScale=1,
+	level=100,
+	quality=4,
+	portraitIconID=1066112,
+	isFavorite=false,
+	xp=0,
+	className="Guardian Druid",
+	classSpec=8,
+	name="Qiana Moonshadow",
+	followerID="0x000000000002F5E1",
+	height=1.3999999761581,
+	displayID=55047,
+	scale=0.60000002384186,
+	levelXP=0
+}
+	local location, xp, environment, environmentDesc, environmentTexture, locPrefix, isExhausting, enemies = G.GetMissionInfo(missionID)
+--]]
+-- In case we need to change rown number in GMF
+		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
diff --git a/wowhead.lua b/wowhead.lua
index 79582ea..a8aa0ad 100644
--- a/wowhead.lua
+++ b/wowhead.lua
@@ -1,407 +1,408 @@
--- DataMined from WowHead on 06/01/2015
+-- DataMined from WowHead on 11/01/2015
 -- Contains 304 missions
 --[[
 Array
 (
-		[id] => 2
-		[level] => 90
-		[itemlevel] => 0
-		[traveltime] => 0
-		[missiontime] => 1800
-		[cooldown] => 9999999
-		[cost] => 0
-		[followers] => 1
-		[experience] => 100
-		[basebonuschance] => 65
-		[name] => Gronnlings Abound
-		[description] => Gronnlings are a menace to the region.  We should partner with the Frostwolf clan to thin the population.  One may even join our cause...
-		[location] => Frostwall Approach
-		[mechanictype] => 23
-		[missiontype] => 3
-		[flags] => 0
-		[rewards] => Array
-				(
-						[experience] => Array
-								(
-								)
+    [id] => 2
+    [level] => 90
+    [itemlevel] => 0
+    [traveltime] => 0
+    [missiontime] => 1800
+    [cooldown] => 9999999
+    [cost] => 0
+    [followers] => 1
+    [experience] => 100
+    [basebonuschance] => 65
+    [name] => Gronnlings Abound
+    [description] => Gronnlings are a menace to the region.  We should partner with the Frostwolf clan to thin the population.  One may even join our cause...
+    [location] => Frostwall Approach
+    [mechanictype] => 23
+    [missiontype] => 3
+    [flags] => 0
+    [rewards] => Array
+        (
+            [experience] => Array
+                (
+                )

-						[prestige] => Array
-								(
-								)
+            [prestige] => Array
+                (
+                )

-						[item] => Array
-								(
-										[0] => Array
-												(
-														[item] => 112737
-														[amount] => 1
-												)
+            [item] => Array
+                (
+                    [0] => Array
+                        (
+                            [item] => 112737
+                            [amount] => 1
+                        )

-								)
+                )

-						[currency] => Array
-								(
-								)
+            [currency] => Array
+                (
+                )

-						[chest] => Array
-								(
-								)
+            [chest] => Array
+                (
+                )

-				)
+        )

-		[encounters] => Array
-				(
-						[1] => Array
-								(
-										[setkey] => 2
-										[id] => 1
-										[npc] => 80693
-										[name] => Frostfire Gronnling
-										[portraitfile] => 1067373
-										[portraitfilename] => enemyportrait_56633
-										[mechanics] => Array
-												(
-														[10] => Array
-																(
-																		[setkey] => 2
-																		[id] => 10
-																		[amount] => 300
-																		[type] => 1
-																		[category] => 2
-																		[name] => Wild Aggression
-																		[description] => An unpredictable enemy whose aggression should be controlled.
-																		[icon] => spell_nature_reincarnation
-																)
+    [encounters] => Array
+        (
+            [1] => Array
+                (
+                    [setkey] => 2
+                    [id] => 1
+                    [npc] => 80693
+                    [name] => Frostfire Gronnling
+                    [portraitfile] => 1067373
+                    [portraitfilename] => enemyportrait_56633
+                    [mechanics] => Array
+                        (
+                            [10] => Array
+                                (
+                                    [setkey] => 2
+                                    [id] => 10
+                                    [amount] => 300
+                                    [type] => 1
+                                    [category] => 2
+                                    [name] => Wild Aggression
+                                    [description] => An unpredictable enemy whose aggression should be controlled.
+                                    [icon] => spell_nature_reincarnation
+                                )

-												)
+                        )

-								)
+                )

-				)
+        )

-		[mechanics] => Array
-				(
-						[0] => Array
-								(
-										[setkey] => 2
-										[id] => 0
-										[amount] => 0
-										[type] => 23
-										[category] => 0
-										[name] => Snow
-										[description] => An arctic region.
-										[icon] => achievement_zone_stormpeaks_02
-								)
+    [mechanics] => Array
+        (
+            [0] => Array
+                (
+                    [setkey] => 2
+                    [id] => 0
+                    [amount] => 0
+                    [type] => 23
+                    [category] => 0
+                    [name] => Snow
+                    [description] => An arctic region.
+                    [icon] => achievement_zone_stormpeaks_02
+                )

-				)
+        )

 )
 --]]
 local me,ns=...
-ns.wowhead={
-[2]={cd=9999999,cs=0},
-[3]={cd=9999999,cs=5},
-[6]={cd=9999999,cs=10},
-[7]={cd=9999999,cs=10},
-[43]={cd=9999999,cs=0},
-[44]={cd=9999999,cs=0},
-[55]={cd=9999999,cs=0},
-[65]={cd=9999999,cs=5},
-[66]={cd=9999999,cs=0},
-[67]={cd=0,cs=10},
-[73]={cd=86400,cs=0},
-[86]={cd=9999999,cs=5},
-[87]={cd=9999999,cs=5},
-[88]={cd=9999999,cs=0},
-[89]={cd=0,cs=10},
-[90]={cd=9999999,cs=10},
-[91]={cd=9999999,cs=10},
-[107]={cd=129600,cs=15},
-[108]={cd=129600,cs=15},
-[109]={cd=129600,cs=15},
-[110]={cd=129600,cs=15},
-[111]={cd=129600,cs=15},
-[112]={cd=129600,cs=15},
-[113]={cd=129600,cs=15},
-[114]={cd=129600,cs=15},
-[115]={cd=129600,cs=10},
-[116]={cd=129600,cs=20},
-[117]={cd=129600,cs=10},
-[118]={cd=129600,cs=15},
-[119]={cd=129600,cs=15},
-[120]={cd=129600,cs=10},
-[125]={cd=129600,cs=20},
-[126]={cd=129600,cs=10},
-[127]={cd=129600,cs=15},
-[128]={cd=129600,cs=10},
-[129]={cd=129600,cs=10},
-[130]={cd=129600,cs=15},
-[131]={cd=129600,cs=15},
-[132]={cd=129600,cs=0},
-[133]={cd=129600,cs=0},
-[135]={cd=86400,cs=10},
-[136]={cd=86400,cs=10},
-[137]={cd=86400,cs=10},
-[138]={cd=86400,cs=10},
-[139]={cd=86400,cs=10},
-[140]={cd=86400,cs=10},
-[141]={cd=86400,cs=10},
-[142]={cd=86400,cs=10},
-[143]={cd=86400,cs=10},
-[144]={cd=86400,cs=10},
-[145]={cd=86400,cs=10},
-[146]={cd=86400,cs=10},
-[147]={cd=86400,cs=10},
-[148]={cd=86400,cs=10},
-[149]={cd=86400,cs=10},
-[150]={cd=86400,cs=10},
-[151]={cd=86400,cs=10},
-[152]={cd=86400,cs=10},
-[153]={cd=86400,cs=10},
-[154]={cd=86400,cs=10},
-[155]={cd=86400,cs=10},
-[156]={cd=86400,cs=10},
-[157]={cd=86400,cs=10},
-[158]={cd=86400,cs=10},
-[159]={cd=86400,cs=10},
-[160]={cd=86400,cs=10},
-[161]={cd=86400,cs=10},
-[162]={cd=86400,cs=10},
-[163]={cd=86400,cs=10},
-[164]={cd=86400,cs=10},
-[165]={cd=86400,cs=10},
-[166]={cd=86400,cs=10},
-[167]={cd=86400,cs=10},
-[168]={cd=86400,cs=10},
-[169]={cd=86400,cs=10},
-[170]={cd=86400,cs=10},
-[171]={cd=86400,cs=10},
-[172]={cd=86400,cs=10},
-[173]={cd=86400,cs=10},
-[174]={cd=86400,cs=10},
-[175]={cd=86400,cs=10},
-[176]={cd=86400,cs=10},
-[177]={cd=86400,cs=10},
-[178]={cd=86400,cs=10},
-[179]={cd=86400,cs=10},
-[180]={cd=86400,cs=10},
-[181]={cd=86400,cs=10},
-[182]={cd=86400,cs=10},
-[183]={cd=86400,cs=0},
-[184]={cd=86400,cs=0},
-[185]={cd=86400,cs=0},
-[186]={cd=86400,cs=0},
-[187]={cd=86400,cs=0},
-[188]={cd=86400,cs=0},
-[189]={cd=86400,cs=0},
-[190]={cd=86400,cs=0},
-[191]={cd=86400,cs=0},
-[192]={cd=86400,cs=0},
-[193]={cd=86400,cs=0},
-[194]={cd=86400,cs=0},
-[195]={cd=86400,cs=20},
-[196]={cd=86400,cs=20},
-[197]={cd=86400,cs=20},
-[198]={cd=86400,cs=20},
-[199]={cd=86400,cs=20},
-[200]={cd=86400,cs=20},
-[201]={cd=86400,cs=20},
-[202]={cd=86400,cs=20},
-[203]={cd=86400,cs=20},
-[204]={cd=86400,cs=20},
-[205]={cd=86400,cs=15},
-[206]={cd=86400,cs=15},
-[207]={cd=86400,cs=15},
-[208]={cd=86400,cs=15},
-[209]={cd=86400,cs=15},
-[210]={cd=86400,cs=15},
-[211]={cd=86400,cs=15},
-[212]={cd=86400,cs=15},
-[213]={cd=86400,cs=15},
-[214]={cd=86400,cs=15},
-[215]={cd=86400,cs=10},
-[217]={cd=86400,cs=10},
-[218]={cd=86400,cs=10},
-[219]={cd=86400,cs=10},
-[220]={cd=86400,cs=10},
-[221]={cd=9999999,cs=10},
-[222]={cd=9999999,cs=10},
-[223]={cd=86400,cs=10},
-[224]={cd=86400,cs=10},
-[228]={cd=9999999,cs=10},
-[229]={cd=9999999,cs=10},
-[230]={cd=86400,cs=10},
-[231]={cd=86400,cs=10},
-[232]={cd=86400,cs=10},
-[242]={cd=86400,cs=10},
-[243]={cd=86400,cs=10},
-[244]={cd=86400,cs=10},
-[245]={cd=86400,cs=10},
-[247]={cd=129600,cs=20},
-[248]={cd=129600,cs=20},
-[249]={cd=129600,cs=20},
-[250]={cd=129600,cs=20},
-[251]={cd=129600,cs=20},
-[252]={cd=129600,cs=20},
-[253]={cd=129600,cs=20},
-[254]={cd=129600,cs=20},
-[255]={cd=129600,cs=15},
-[256]={cd=129600,cs=25},
-[257]={cd=129600,cs=15},
-[258]={cd=129600,cs=20},
-[259]={cd=129600,cs=15},
-[260]={cd=129600,cs=15},
-[261]={cd=129600,cs=15},
-[262]={cd=129600,cs=15},
-[263]={cd=129600,cs=15},
-[264]={cd=129600,cs=15},
-[265]={cd=129600,cs=15},
-[266]={cd=129600,cs=15},
-[267]={cd=129600,cs=15},
-[268]={cd=129600,cs=0},
-[269]={cd=129600,cs=0},
-[271]={cd=86400,cs=15},
-[272]={cd=86400,cs=10},
-[273]={cd=86400,cs=20},
-[274]={cd=86400,cs=10},
-[275]={cd=86400,cs=15},
-[276]={cd=86400,cs=25},
-[277]={cd=86400,cs=10},
-[278]={cd=86400,cs=10},
-[279]={cd=86400,cs=10},
-[280]={cd=86400,cs=10},
-[281]={cd=86400,cs=10},
-[282]={cd=86400,cs=10},
-[283]={cd=86400,cs=10},
-[284]={cd=86400,cs=15},
-[285]={cd=86400,cs=10},
-[286]={cd=86400,cs=20},
-[287]={cd=86400,cs=15},
-[288]={cd=86400,cs=25},
-[289]={cd=86400,cs=10},
-[290]={cd=129600,cs=30},
-[291]={cd=129600,cs=30},
-[292]={cd=129600,cs=30},
-[293]={cd=129600,cs=30},
-[294]={cd=129600,cs=30},
-[295]={cd=129600,cs=30},
-[296]={cd=129600,cs=30},
-[297]={cd=129600,cs=30},
-[298]={cd=129600,cs=20},
-[299]={cd=129600,cs=40},
-[300]={cd=129600,cs=20},
-[301]={cd=129600,cs=30},
-[302]={cd=129600,cs=30},
-[303]={cd=129600,cs=20},
-[304]={cd=129600,cs=40},
-[305]={cd=129600,cs=20},
-[306]={cd=129600,cs=30},
-[307]={cd=129600,cs=20},
-[308]={cd=129600,cs=20},
-[309]={cd=129600,cs=20},
-[310]={cd=129600,cs=20},
-[311]={cd=129600,cs=0},
-[312]={cd=129600,cs=0},
-[313]={cd=1209000,cs=100},
-[314]={cd=1209000,cs=100},
-[315]={cd=1209000,cs=100},
-[316]={cd=1209000,cs=100},
-[317]={cd=1209000,cs=100},
-[318]={cd=1209000,cs=100},
-[319]={cd=1209000,cs=100},
-[320]={cd=1209000,cs=100},
-[321]={cd=1209000,cs=100},
-[322]={cd=1209000,cs=100},
-[323]={cd=1209000,cs=100},
-[324]={cd=1209000,cs=100},
-[325]={cd=1209000,cs=100},
-[326]={cd=1209000,cs=100},
-[327]={cd=1209000,cs=100},
-[328]={cd=1209000,cs=100},
-[329]={cd=86400,cs=5},
-[330]={cd=86400,cs=10},
-[331]={cd=86400,cs=10},
-[332]={cd=86400,cs=10},
-[333]={cd=86400,cs=0},
-[334]={cd=252000,cs=25},
-[335]={cd=252000,cs=25},
-[336]={cd=252000,cs=25},
-[337]={cd=252000,cs=25},
-[338]={cd=86400,cs=10},
-[339]={cd=86400,cs=10},
-[340]={cd=86400,cs=10},
-[341]={cd=86400,cs=10},
-[342]={cd=86400,cs=10},
-[343]={cd=86400,cs=10},
-[344]={cd=86400,cs=10},
-[345]={cd=86400,cs=10},
-[346]={cd=86400,cs=10},
-[347]={cd=86400,cs=0},
-[348]={cd=86400,cs=10},
-[349]={cd=86400,cs=10},
-[350]={cd=86400,cs=10},
-[351]={cd=86400,cs=10},
-[352]={cd=86400,cs=0},
-[353]={cd=86400,cs=10},
-[354]={cd=86400,cs=10},
-[355]={cd=86400,cs=10},
-[356]={cd=86400,cs=10},
-[357]={cd=86400,cs=10},
-[358]={cd=252000,cs=25},
-[359]={cd=252000,cs=25},
-[360]={cd=252000,cs=25},
-[361]={cd=252000,cs=25},
-[362]={cd=86400,cs=0},
-[363]={cd=86400,cs=0},
-[364]={cd=86400,cs=10},
-[365]={cd=86400,cs=25},
-[366]={cd=57600,cs=20},
-[367]={cd=57600,cs=20},
-[368]={cd=57600,cs=20},
-[369]={cd=57600,cs=20},
-[370]={cd=57600,cs=20},
-[371]={cd=57600,cs=20},
-[372]={cd=57600,cs=20},
-[373]={cd=57600,cs=20},
-[374]={cd=57600,cs=20},
-[375]={cd=57600,cs=20},
-[376]={cd=57600,cs=20},
-[377]={cd=57600,cs=20},
-[378]={cd=86400,cs=10},
-[379]={cd=86400,cs=10},
-[380]={cd=129600,cs=15},
-[381]={cd=86400,cs=10},
-[382]={cd=86400,cs=10},
-[383]={cd=86400,cs=10},
-[384]={cd=86400,cs=10},
-[385]={cd=129600,cs=15},
-[386]={cd=86400,cs=10},
-[387]={cd=86400,cs=10},
-[388]={cd=86400,cs=10},
-[389]={cd=86400,cs=10},
-[390]={cd=86400,cs=10},
-[391]={cd=86400,cs=10},
-[392]={cd=86400,cs=10},
-[393]={cd=86400,cs=10},
-[394]={cd=86400,cs=10},
-[395]={cd=86400,cs=10},
-[396]={cd=86400,cs=10},
-[397]={cd=86400,cs=10},
-[398]={cd=86400,cs=10},
-[399]={cd=86400,cs=10},
-[400]={cd=86400,cs=10},
-[401]={cd=86400,cs=10},
-[402]={cd=86400,cs=10},
-[403]={cd=1209000,cs=50},
-[404]={cd=1209000,cs=50},
-[405]={cd=1209000,cs=50},
-[406]={cd=1209000,cs=50},
-[407]={cd=1209000,cs=50},
-[408]={cd=1209000,cs=75},
-[409]={cd=1209000,cs=75},
-[410]={cd=1209000,cs=75},
-[411]={cd=1209000,cs=75},
-[412]={cd=1209000,cs=75},
-[413]={cd=1209000,cs=75},
-[99999999]={}
+ ns.wowhead={
+[2]=9999999,
+[3]=9999999,
+[6]=9999999,
+[7]=9999999,
+[43]=9999999,
+[44]=9999999,
+[55]=9999999,
+[65]=9999999,
+[66]=9999999,
+[67]=0,
+[73]=86400,
+[86]=9999999,
+[87]=9999999,
+[88]=9999999,
+[89]=0,
+[90]=9999999,
+[91]=9999999,
+[107]=129600,
+[108]=129600,
+[109]=129600,
+[110]=129600,
+[111]=129600,
+[112]=129600,
+[113]=129600,
+[114]=129600,
+[115]=129600,
+[116]=129600,
+[117]=129600,
+[118]=129600,
+[119]=129600,
+[120]=129600,
+[125]=129600,
+[126]=129600,
+[127]=129600,
+[128]=129600,
+[129]=129600,
+[130]=129600,
+[131]=129600,
+[132]=129600,
+[133]=129600,
+[135]=86400,
+[136]=86400,
+[137]=86400,
+[138]=86400,
+[139]=86400,
+[140]=86400,
+[141]=86400,
+[142]=86400,
+[143]=86400,
+[144]=86400,
+[145]=86400,
+[146]=86400,
+[147]=86400,
+[148]=86400,
+[149]=86400,
+[150]=86400,
+[151]=86400,
+[152]=86400,
+[153]=86400,
+[154]=86400,
+[155]=86400,
+[156]=86400,
+[157]=86400,
+[158]=86400,
+[159]=86400,
+[160]=86400,
+[161]=86400,
+[162]=86400,
+[163]=86400,
+[164]=86400,
+[165]=86400,
+[166]=86400,
+[167]=86400,
+[168]=86400,
+[169]=86400,
+[170]=86400,
+[171]=86400,
+[172]=86400,
+[173]=86400,
+[174]=86400,
+[175]=86400,
+[176]=86400,
+[177]=86400,
+[178]=86400,
+[179]=86400,
+[180]=86400,
+[181]=86400,
+[182]=86400,
+[183]=86400,
+[184]=86400,
+[185]=86400,
+[186]=86400,
+[187]=86400,
+[188]=86400,
+[189]=86400,
+[190]=86400,
+[191]=86400,
+[192]=86400,
+[193]=86400,
+[194]=86400,
+[195]=86400,
+[196]=86400,
+[197]=86400,
+[198]=86400,
+[199]=86400,
+[200]=86400,
+[201]=86400,
+[202]=86400,
+[203]=86400,
+[204]=86400,
+[205]=86400,
+[206]=86400,
+[207]=86400,
+[208]=86400,
+[209]=86400,
+[210]=86400,
+[211]=86400,
+[212]=86400,
+[213]=86400,
+[214]=86400,
+[215]=86400,
+[217]=86400,
+[218]=86400,
+[219]=86400,
+[220]=86400,
+[221]=9999999,
+[222]=9999999,
+[223]=86400,
+[224]=86400,
+[228]=9999999,
+[229]=9999999,
+[230]=86400,
+[231]=86400,
+[232]=86400,
+[242]=86400,
+[243]=86400,
+[244]=86400,
+[245]=86400,
+[247]=129600,
+[248]=129600,
+[249]=129600,
+[250]=129600,
+[251]=129600,
+[252]=129600,
+[253]=129600,
+[254]=129600,
+[255]=129600,
+[256]=129600,
+[257]=129600,
+[258]=129600,
+[259]=129600,
+[260]=129600,
+[261]=129600,
+[262]=129600,
+[263]=129600,
+[264]=129600,
+[265]=129600,
+[266]=129600,
+[267]=129600,
+[268]=129600,
+[269]=129600,
+[271]=86400,
+[272]=86400,
+[273]=86400,
+[274]=86400,
+[275]=86400,
+[276]=86400,
+[277]=86400,
+[278]=86400,
+[279]=86400,
+[280]=86400,
+[281]=86400,
+[282]=86400,
+[283]=86400,
+[284]=86400,
+[285]=86400,
+[286]=86400,
+[287]=86400,
+[288]=86400,
+[289]=86400,
+[290]=129600,
+[291]=129600,
+[292]=129600,
+[293]=129600,
+[294]=129600,
+[295]=129600,
+[296]=129600,
+[297]=129600,
+[298]=129600,
+[299]=129600,
+[300]=129600,
+[301]=129600,
+[302]=129600,
+[303]=129600,
+[304]=129600,
+[305]=129600,
+[306]=129600,
+[307]=129600,
+[308]=129600,
+[309]=129600,
+[310]=129600,
+[311]=129600,
+[312]=129600,
+[313]=1209000,
+[314]=1209000,
+[315]=1209000,
+[316]=1209000,
+[317]=1209000,
+[318]=1209000,
+[319]=1209000,
+[320]=1209000,
+[321]=1209000,
+[322]=1209000,
+[323]=1209000,
+[324]=1209000,
+[325]=1209000,
+[326]=1209000,
+[327]=1209000,
+[328]=1209000,
+[329]=86400,
+[330]=86400,
+[331]=86400,
+[332]=86400,
+[333]=86400,
+[334]=252000,
+[335]=252000,
+[336]=252000,
+[337]=252000,
+[338]=86400,
+[339]=86400,
+[340]=86400,
+[341]=86400,
+[342]=86400,
+[343]=86400,
+[344]=86400,
+[345]=86400,
+[346]=86400,
+[347]=86400,
+[348]=86400,
+[349]=86400,
+[350]=86400,
+[351]=86400,
+[352]=86400,
+[353]=86400,
+[354]=86400,
+[355]=86400,
+[356]=86400,
+[357]=86400,
+[358]=252000,
+[359]=252000,
+[360]=252000,
+[361]=252000,
+[362]=86400,
+[363]=86400,
+[364]=86400,
+[365]=86400,
+[366]=57600,
+[367]=57600,
+[368]=57600,
+[369]=57600,
+[370]=57600,
+[371]=57600,
+[372]=57600,
+[373]=57600,
+[374]=57600,
+[375]=57600,
+[376]=57600,
+[377]=57600,
+[378]=86400,
+[379]=86400,
+[380]=129600,
+[381]=86400,
+[382]=86400,
+[383]=86400,
+[384]=86400,
+[385]=129600,
+[386]=86400,
+[387]=86400,
+[388]=86400,
+[389]=86400,
+[390]=86400,
+[391]=86400,
+[392]=86400,
+[393]=86400,
+[394]=86400,
+[395]=86400,
+[396]=86400,
+[397]=86400,
+[398]=86400,
+[399]=86400,
+[400]=86400,
+[401]=86400,
+[402]=86400,
+[403]=1209000,
+[404]=1209000,
+[405]=1209000,
+[406]=1209000,
+[407]=1209000,
+[408]=1209000,
+[409]=1209000,
+[410]=1209000,
+[411]=1209000,
+[412]=1209000,
+[413]=1209000,
+_lastupdate_=1421009516
 }
+setmetatable(ns.wowhead,{__index=function(t,k) return 0 end})