Quantcast

2.4.0 Alfa

Alar of Daggerspine [03-09-15 - 01:42]
2.4.0 Alfa

Signed-off-by: Alar of Daggerspine <alar@aspide.it>
Filename
BuildingPage.lua
CHANGELOG.txt
FollowerCache.lua
FollowerPage.lua
GarrisonCommander-Broker/ldb.lua
GarrisonCommander.lua
GarrisonCommander.toc
GarrisonCommander.xml
Init.lua
MatchMaker.lua
MissionCache.lua
MissionCompletion.lua
MissionControl.lua
diff --git a/BuildingPage.lua b/BuildingPage.lua
new file mode 100644
index 0000000..06df884
--- /dev/null
+++ b/BuildingPage.lua
@@ -0,0 +1,95 @@
+--[[
+GarrisonBuildingFrame.MapFrame.TownHall
+GarrisonBuildingFrame.MapFrame.Plots
+Plots[*]={
+buildingID=28
+plotID=23
+followerTooltip="colore + nome del follower"
+size= level
+Plot=framde del piedistallino
+Icon e IconRing contenuto e nordo dell'iconcina
+
+
+--]]
+local me,ns=...
+local addon=ns.addon
+--@debug@
+if LibDebug then LibDebug() end
+--@end-debug@
+local GBF=GarrisonBuildingFrame
+local GBFMap=GBF.MapFrame
+local G=C_Garrison
+local CreateFrame=CreateFrame
+local GARRISON_FOLLOWER_MAX_LEVEL=GARRISON_FOLLOWER_MAX_LEVEL
+local L=ns.L
+local D=ns.D
+local C=ns.C
+local new,del=ns.new,ns.del
+local module=addon:NewModule("BuildingPage",addon) --#module
+function module:OnInitialize()
+	--module:SafeHookScript(GBFMap,"OnShow","AddFollowersToMap")
+	module:SafeSecureHook("GarrisonBuildingList_Show","AddCheckBox")
+	module:SafeSecureHook("GarrisonPlot_UpdateBuilding","RefreshPlot")
+end
+function module:AddCheckBox()
+	if (not GBFMap.hideFollower) then
+		local ck=self:GetFactory():Checkbox(GBFMap,addon:GetToggle("HF"),addon:GetVarInfo("HF"))
+		ck:SetPoint("BOTTOMLEFT",5,20)
+		ck:Show()
+		ck:SetScript("OnClick",function(this)
+			addon:SetBoolean("HF",this:GetChecked())
+			module:AddFollowersToMap()
+		end)
+		GBFMap.hideFollower=ck
+	end
+end
+function module:RefreshPlot(plotID)
+	for i=1,#GBFMap.Plots do
+		if	GBFMap.Plots[i].plotID==plotID then
+			return self:AddFollowerToPlot(GBFMap.Plots[i])
+		end
+	end
+end
+function module:AddFollowerToPlot(plot)
+	if (not plot.followerIcon) then
+		plot.followerIcon=CreateFrame("Frame",nil,plot,"GarrisonCommanderMissionPageFollowerTemplateSmall")
+		plot.followerIcon:SetScale(0.8)
+		plot.followerIcon:SetPoint("CENTER",20,15)
+	end
+	local frame=plot.followerIcon
+	if (addon:GetToggle("HF")) then
+		return frame:Hide()
+	end
+	ns.xprint(plot.followerTooltip,plot.plotID)
+	if plot.followerTooltip then
+		local followerName, level, quality, displayID, followerID, garrFollowerID, status, portraitIconID = G.GetFollowerInfoForBuilding(plot.plotID)
+		if followerName then
+			if (level == GARRISON_FOLLOWER_MAX_LEVEL) then
+				level=G.GetFollowerItemLevelAverage(followerID)
+				frame.PortraitFrame.LevelBorder:SetAtlas("GarrMission_PortraitRing_iLvlBorder");
+				frame.PortraitFrame.LevelBorder:SetWidth(70);
+			else
+				frame.PortraitFrame.LevelBorder:SetAtlas("GarrMission_PortraitRing_LevelBorder");
+				frame.PortraitFrame.LevelBorder:SetWidth(58);
+			end
+			local info=new()
+			info.quality=quality
+			info.level=level
+			info.portraitIconID=portraitIconID
+			info.displayID=portraitIconID
+			GarrisonMissionFrame_SetFollowerPortrait(frame.PortraitFrame, info, false);
+			frame.PortraitFrame.Empty:Hide()
+			del(info)
+		else
+			frame.PortraitFrame.Empty:Show()
+		end
+		frame:Show()
+	else
+		frame:Hide()
+	end
+end
+function module:AddFollowersToMap()
+	for i=1,#GBFMap.Plots do
+		self:AddFollowerToPlot(GBFMap.Plots[i])
+	end
+end
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 59a1e3c..8ba57d4 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,6 +1,6 @@
 ==GarrisonCommander helps you when choosing the right follower for the right mission==
-* 2.3.7.1
-** Fix: Due to an issue in packaginc, 2.3.7 was build with no embedded libraries
-** Fix: Party display for In Progress missions sometimes was not not showing the right followers.
-** Fix: Matchmaking was trying too hard te get the lowest usefull follower, sometimes not achieving the best possible score
-** Fix: Added missing library to GarrisonCommander-Broker. Most people already had that library so onoy a few ones were impacred from it
\ No newline at end of file
+* 2.3.8
+** Feature: Quick mission report now accounts for bonuses
+** Feature: Quick mission competion button has now a name: GCQuickMissionCompletionButton
+** Feature: Easy upgrade. You can now upgraed your followers' equipment with a single click in follower list page
+** Feature: In buildings map, working follower are displayed on plots. Plots with no followers but which could have one are marked
diff --git a/FollowerCache.lua b/FollowerCache.lua
index 7bac519..d6b792a 100644
--- a/FollowerCache.lua
+++ b/FollowerCache.lua
@@ -93,6 +93,7 @@ function addon:GetFollowerData(followerID,key,default)
 --@debug@
 		ns.xprint("Not found",followerID,key,"at",idx,"len",#Mbase.followers)
 		print(debugstack())
+		return default
 --@end-debug@
 	end
 	if (key==nil) then
diff --git a/FollowerPage.lua b/FollowerPage.lua
index e69de29..f45b4a1 100644
--- a/FollowerPage.lua
+++ b/FollowerPage.lua
@@ -0,0 +1,208 @@
+local me, ns = ...
+local addon=ns.addon --#addon
+local L=ns.L
+local D=ns.D
+local C=ns.C
+local AceGUI=ns.AceGUI
+local _G=_G
+local new, del, copy =ns.new,ns.del,ns.copy
+-- Courtesy of Motig
+-- Concept and interface reused with permission
+-- Mission building rewritten from scratch
+--local GMC_G = {}
+local factory=addon:GetFactory()
+--GMC_G.frame = CreateFrame('FRAME')
+local aMissions={}
+local dbcache
+local cache
+local db
+local GMC
+local GMF=GarrisonMissionFrame
+local G=C_Garrison
+local GMCUsedFollowers={}
+local wipe=wipe
+local pairs=pairs
+local tinsert=tinsert
+local xprint=ns.xprint
+local coroutine=coroutine
+local GetItemInfo=GetItemInfo
+local GarrisonMissionFrame_SetItemRewardDetails=GarrisonMissionFrame_SetItemRewardDetails
+local GetItemCount=GetItemCount
+local strsplit=strsplit
+local GarrisonFollower_DisplayUpgradeConfirmation=GarrisonFollower_DisplayUpgradeConfirmation
+local StaticPopup_Show=StaticPopup_Show
+local CONFIRM_GARRISON_FOLLOWER_UPGRADE=CONFIRM_GARRISON_FOLLOWER_UPGRADE
+local GameTooltip=GameTooltip
+local StaticPopupDialogs=StaticPopupDialogs
+local YES=YES
+local NO=NO
+--@debug@
+_G.GAC=addon
+if LibDebug then LibDebug() end
+--@end-debug@
+local dbg
+
+function addon:ShowImprovements()
+	local scroller=self:GetScroller("Items")
+	scroller:AddRow("Follower Upgrades",C.Orange())
+	for i,v in pairs(self:GetUpgrades()) do
+		scroller:AddRow(i,C.Yellow())
+		for itemID,_ in pairs(v) do
+			local b=scroller:AddItem(itemID)
+			b:SetUserData("item",itemID)
+			b:SetCallback("OnEnter",function(this)
+				print("Item:",this:GetUserData("item"))
+				GameTooltip:SetOwner(this.frame,"ANCHOR_CURSOR")
+				GameTooltip:AddLine("Reward")
+				GameTooltip:SetItemByID(this:GetUserData("item"))
+				GameTooltip:Show() end)
+			b:SetCallback("OnLeave",function(this) GameTooltip:Hide() end)
+			b:SetCallback("OnClick",function(this) print("Clicckete") end)
+		end
+	end
+	scroller:AddRow("Item Tokens",C.Orange())
+	for i,v in pairs(self:GetItems()) do
+		local b=scroller:AddItem(i)
+	end
+end
+local CONFIRM1=L["Upgrading to %d"].."\n" .. CONFIRM_GARRISON_FOLLOWER_UPGRADE
+local CONFIRM2=L["Upgrading to %d"].."\n|cFFFF0000 "..L["You are wasting points!!!"].."|r\n" .. CONFIRM_GARRISON_FOLLOWER_UPGRADE
+local function DoUpgradeFollower(this)
+		G.CastSpellOnFollower(this.data);
+end
+local function UpgradeFollower(this)
+	local follower=this:GetParent()
+	local followerID=follower.followerID
+	local level=this.rawlevel
+	local genere=this.tipo:sub(1,1)
+	local mylevel=genere=="w" and follower.ItemWeapon.itemLevel or  follower.ItemArmor.itemLevel
+	local name = ITEM_QUALITY_COLORS[G.GetFollowerQuality(followerID)].hex..G.GetFollowerName(followerID)..FONT_COLOR_CODE_CLOSE;
+	local losing=false
+	if level > 600 and mylevel>600 then
+		losing=mylevel
+	elseif mylevel+level > GARRISON_FOLLOWER_MAX_ITEM_LEVEL then
+		losing=(mylevel+level)-GARRISON_FOLLOWER_MAX_ITEM_LEVEL
+	end
+	if losing then
+		addon:Popup(format(CONFIRM2,losing,name),0,DoUpgradeFollower,true,followerID,true)
+	else
+		if addon:GetToggle("NOCONFIRM") then
+			--G.CastSpellOnFollower(followerID);
+		else
+			addon:Popup(format(CONFIRM1,mylevel+level,name),0,DoUpgradeFollower,true,followerID,true)
+		end
+	end
+end
+local colors={
+	[1]="Yellow",
+	[3]="Uncommon",
+	[6]="Rare",
+	[9]="Epic",
+	[615]="Uncommon",
+	[630]="Rare",
+	[645]="Epic"
+}
+function addon:ShowUpgradeButtons(force)
+	local gf=GMF.FollowerTab
+	if (not force and not gf:IsShown()) then return end
+	if (not gf.showUpgrades) then
+		gf.showUpgrades=self:GetFactory():Checkbox(gf.Model,self:GetToggle("UPG"),self:GetVarInfo("UPG"))
+		gf.showUpgrades:SetPoint("TOPLEFT")
+		gf.showUpgrades:Show()
+		gf.showUpgrades:SetScript("OnClick",function(this)
+			addon:SetBoolean("UPG",this:GetChecked())
+			addon:ShowUpgradeButtons()
+		end)
+	end
+	if (not gf.noConfirm) then
+		gf.noConfirm=self:GetFactory():Checkbox(gf.Model,self:GetToggle("NOCONFIRM"),self:GetVarInfo("NOCONFIRM"))
+		gf.noConfirm:SetPoint("TOPLEFT",0,-25)
+		gf.noConfirm:Show()
+		gf.noConfirm:SetScript("OnClick",function(this)
+			addon:SetBoolean("NOCONFIRM",this:GetChecked())
+		end)
+	end
+	if not gf.upgradeButtons then gf.upgradeButtons ={} end
+	--if not gf.upgradeFrame then gf.upgradeFrame=CreateFrame("Frame",nil,gf.model) end
+	local b=gf.upgradeButtons
+	local upgrades=self:GetUpgrades()
+	local axpos=243
+	local wxpos=7
+	local wypos=-135
+	local aypos=-135
+	local used=1
+	if not gf.followerID then
+		return self:DelayedRefresh(0.1)
+	end
+	local followerID=gf.followerID
+	local followerInfo = followerID and G.GetFollowerInfo(followerID);
+	if ( followerInfo and followerInfo.isCollected and not followerInfo.status and followerInfo.level == GARRISON_FOLLOWER_MAX_LEVEL ) then
+		for i=1,#upgrades do
+			if not b[used] then
+				b[used]=CreateFrame("Button",nil,gf,"GarrisonCommanderUpgradeButton,SecureActionbuttonTemplate")
+			end
+			local tipo,itemID,level=strsplit(":",upgrades[i])
+			level=tonumber(level)
+			local A=b[used]
+			local qt=GetItemCount(itemID)
+			repeat
+			if (qt>0) then
+				A:ClearAllPoints()
+				A.tipo=tipo
+				local currentlevel=tipo:sub(1,1)=="w" and gf.ItemWeapon.itemLevel or  gf.ItemArmor.itemLevel
+				if level > 600 and level <= currentlevel then
+					break -- Pointless item for this toon
+				end
+				used=used+1
+				if (tipo:sub(1,1)=="a") then
+					A:SetPoint("TOPLEFT",axpos,aypos)
+					aypos=aypos-45
+				else
+					A:SetPoint("TOPLEFT",wxpos,wypos)
+					wypos=wypos-45
+				end
+				A:SetSize(40,40)
+				A.Icon:SetSize(40,40)
+				A.itemID=itemID
+				GarrisonMissionFrame_SetItemRewardDetails(A)
+				A.rawlevel=level
+				A.Level:SetText(level < 600 and (currentlevel+level) or level)
+				local c=colors[level]
+				A.Level:SetTextColor(C[c]())
+				A.Quantity:SetFormattedText("%d",qt)
+				A.Quantity:SetTextColor(C.Yellow())
+				A:SetFrameLevel(gf.Model:GetFrameLevel()+1)
+				A.Quantity:Show()
+				A.Level:Show()
+				A:EnableMouse(true)
+				A:RegisterForClicks("LeftButtonDown")
+				A:SetAttribute("type","item")
+				A:SetAttribute("item",select(2,GetItemInfo(itemID)))
+				A:Show()
+				if tipo=="at" or tipo =="wt" then
+					A.Level:Hide()
+					A:SetScript("PostClick",nil)
+				else
+					A.Level:Show()
+					A:SetScript("PostClick",UpgradeFollower)
+				end
+			end
+			until true -- Continue dei poveri
+		end
+	end
+	for i=used,#b do
+		b[i]:Hide()
+	end
+end
+function addon:DelayedRefresh(delay)
+	if GMF.FollowerTab:IsShown() then
+		if not tonumber(delay) then delay=0.5 end
+		return C_Timer.After(delay,function() addon:ShowUpgradeButtons() end)
+	end
+end
+function addon:FollowerPageStartUp()
+	self:RegisterEvent("GARRISON_FOLLOWER_UPGRADED","DelayedRefresh")
+	self:RegisterEvent("CHAT_MSG_LOOT","DelayedRefresh")
+end
+
+
diff --git a/GarrisonCommander-Broker/ldb.lua b/GarrisonCommander-Broker/ldb.lua
index ae86526..64cff9f 100644
--- a/GarrisonCommander-Broker/ldb.lua
+++ b/GarrisonCommander-Broker/ldb.lua
@@ -96,7 +96,7 @@ function dataobj:OnTooltipShow()
 			end
 		end
 	end
-	self("AddLine",me,0,1,0)
+	self:AddLine(me,0,1,0)
 end

 function dataobj:OnEnter()
diff --git a/GarrisonCommander.lua b/GarrisonCommander.lua
index 234db65..88f4f61 100644
--- a/GarrisonCommander.lua
+++ b/GarrisonCommander.lua
@@ -33,7 +33,9 @@ local trc=false
 local pin=false
 local baseHeight
 local minHeight
-if (LibDebug) then LibDebug() end
+--@debug@
+if LibDebug() then LibDebug() end
+--@end-debug@
 ns.bigscreen=true
 -- Blizzard functions override support
 local orig={} --#originals
@@ -396,7 +398,10 @@ function addon:OnInitialized()
 	self:AddSlider("MINPERC",50,0,100,L["Minimun chance success under which ignore missions"],nil,5)
 	self:AddToggle("ILV",true,L["Show weapon/armor level"],L["When checked, show on each follower button weapon and armor level for maxed followers"])
 	self:AddToggle("IXP",true,L["Show xp to next level"],L["When checked, show on each follower button missing xp to next level"])
-	--self:AddPrivateAction("ShowMissionControl",L["Mission control"],L["You can choose some criteria and have GC autosumbit missions for you"])
+	self:AddToggle("UPG",true,L["Show upgrade options"],L["Only meaningful upgrades are shown"])
+	self:AddToggle("NOCONFIRM",true,L["Don't ask for confirmation"],L["If checked, clicking an upgrade icon will consume the item and upgrade the follower\n|cFFFF0000NO QUESTION ASKED|r"])
+	self:AddLabel("Buildings Panel")
+	self:AddToggle("HF",false,L["Hide followers"],L["Do not show follower icon on plots"])
 --@debug@
 	self:AddLabel("Developers options")
 	self:AddToggle("DBG",false, "Enable Debug")
@@ -685,7 +690,7 @@ function addon:CreatePrivateDb()
 					maxDuration = 24,
 					epicExp = false,
 					skipRare=true,
-					skipEpic=true
+					skipEpic=not addon:HasSalvageYard()
 				}
 			}
 		},
@@ -1522,19 +1527,6 @@ function addon:HookedGarrisonMissionFrame_SelectTab(id)
 	self:RefreshFollowerStatus()
 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(...)
-		addon:RefreshFollowerStatus()
-		for i=1,#GMFMissionListButtons do
-			GMFMissionListButtons.lastMissionID=nil
-		end
-		if (HD) then addon:ResetSinks() end
-	end
-end
 function addon:HookedGarrisonMissionFrame_HideCompleteMissions()
 	xprint("Complete missions closed")
 end
@@ -1610,9 +1602,12 @@ end
 function addon:HookedGarrisonFollowerListButton_OnClick(frame,button)
 	if (frame.info.isCollected) then
 		if (button=="LeftButton") then
-			if (ns.bigscreen and frame and frame.info and frame.info.followerID)  then self:HookedGarrisonFollowerPage_ShowFollower(frame.info,frame.info.followerID) end
+			if (ns.bigscreen and frame and frame.info and frame.info.followerID)  then
+				self:HookedGarrisonFollowerPage_ShowFollower(frame.info,frame.info.followerID)
+			end
 		end
 		self:ScheduleTimer("HookedGarrisonFollowerButton_UpdateCounters",0.2,frame,frame.info,false)
+		self:ShowUpgradeButtons()
 	end
 end
 -- Shamelessly stolen from Blizzard Code
@@ -1820,11 +1815,11 @@ function addon:SetUp(...)
 	tabCF:SetPoint('TOPLEFT',GCF,'TOPRIGHT',0,-60)
 	tabMC:SetPoint('TOPLEFT',GCF,'TOPRIGHT',0,-110)
 	local ref=GMFMissions.CompleteDialog.BorderFrame.ViewButton
-	local bt = CreateFrame('BUTTON',nil, ref, 'UIPanelButtonTemplate')
+	local bt = CreateFrame('BUTTON','GCQuickMissionCompletionButton', ref, 'UIPanelButtonTemplate')
 	bt:SetWidth(300)
 	bt:SetText(L["Garrison Comander Quick Mission Completion"])
 	bt:SetPoint("CENTER",0,-50)
-	addon:ActivateButton(bt,"MissionComplete","Complete all missions without confirmation")
+	addon:ActivateButton(bt,"MissionComplete",L["Complete all missions without confirmation"])
 	return self:StartUp()
 	--collectgarbage("step",10)
 --/Interface/FriendsFrame/UI-Toast-FriendOnlineIcon
@@ -1896,6 +1891,11 @@ function addon:StartUp(...)

 	-- Mission management
 	self:SafeHookScript(GMF.MissionComplete.NextMissionButton,"OnClick","OnClick_GarrisonMissionFrame_MissionComplete_NextMissionButton",true)
+	self:SafeHookScript(GMFMissions.CompleteDialog,"OnShow","RaiseCompleteDialog")
+	self:SafeHookScript(GMFMissions.CompleteDialog,"OnHide",function() print("Closing reward frame") end)
+	if (GMFMissions.CompleteDialog:IsShown()) then
+		self:RaiseCompleteDialog()
+	end
 	-- Hooking mission buttons on click
 	for i=1,#GMFMissionListButtons do
 		local b=GMFMissionListButtons[i]
@@ -1906,8 +1906,18 @@ function addon:StartUp(...)
 	self:Trigger("MSORT")
 	self:Trigger("CKMP")
 	GMFMissions.listScroll.update = over.GarrisonMissionList_Update
+	self:FollowerPageStartUp()
 	return self:RefreshMissions()
 end
+function addon:RaiseCompleteDialog()
+	local f=GMFMissions.CompleteDialog
+	if f:GetFrameLevel() < 45 then
+		f:SetFrameLevel(45)
+	end
+	--print("Dialog:",GMFMissions.CompleteDialog:GetFrameLevel())
+	--C_Timer.After(0.1,function() local f=GMFMissions.CompleteDialog print("Dialog:",f:GetFrameLevel()) if f:GetFrameLevel() < 45 then f:SetFrameLevel(45) end print("Dialog:",f:GetFrameLevel()) end)
+end
+
 function addon:MarkAsNew(obj,key,message)
 	if (not db.news[key]) then
 		local f=CreateFrame("Frame",nil,obj,"GarrisonCommanderWhatsNew")
@@ -2077,22 +2087,9 @@ function addon:FillMissionPage(missionInfo)
 		for i=1,missionInfo.numFollowers do
 			local followerID=members[i]
 			if (followerID) then
-				local status=G.GetFollowerStatus(followerID)
-				if (false and status) then
-					if status == GARRISON_FOLLOWER_IN_PARTY then -- Left from a previous assignment?
---@debug@
-						ns.xprint(followerID,self:GetFollowerData(followerID,"name"),"was already on mission")
---@end-debug@
-						self:RemoveFromAllMissions(followerID)
-						GarrisonMissionPage_AddFollower(followerID)
-					else
-						self:Popup("You attemped to use a busy follower. Please check '" .. IGNORE_UNAIVALABLE_FOLLOWERS .."'",10)
-					end
-				else
-					pcall(G.RemoveFollowerFromMission,missionID,followerID)
-					ns.xprint("Adding",followerID,G.GetFollowerName(followerID))
-					GarrisonMissionPage_AddFollower(followerID)
-				end
+				pcall(G.RemoveFollowerFromMission,missionID,followerID)
+				ns.xprint("Adding",followerID,G.GetFollowerName(followerID))
+				GarrisonMissionPage_AddFollower(followerID)
 			end
 		end
 	end
@@ -2304,6 +2301,7 @@ function addon:BuildExtraButton(button,bigscreen)

 end
 function addon:OnShow_FollowerPage(page)
+	self:ShowUpgradeButtons()
 	if not GCFMissions then return end
 	ns.xprint("Onshow")
 	if type(GCFMissions.Header.info)=="table" then
@@ -2328,6 +2326,7 @@ do
 		local followerID=frame.info and frame.info.followerID or nil
 		local missionID=frame.missionID
 		if (not followerID) then return end
+		if (addon:IsRewardPage()) then return end
 		if (button=="LeftButton") then
 			self:OpenFollowersTab()
 			GMF.selectedFollower=followerID
@@ -2613,6 +2612,7 @@ do
 	local lastcall=math.floor(GetTime()*10)
 	local progressing
 	function over.GarrisonMissionList_Update()
+		if (addon:IsRewardPage()) then return end
 		local self = GarrisonMissionFrame.MissionTab.MissionList;
 		local missions;
 		if (self.showInProgress) then
@@ -2666,9 +2666,7 @@ function over.GarrisonMissionPageFollowerFrame_OnEnter(self)
 	if not self.info then
 		return;
 	end
-	if ns.missionautocompleting then
-		return
-	end
+	if (addon:IsRewardPage()) then return end
 	GarrisonFollowerTooltip:ClearAllPoints();
 	GarrisonFollowerTooltip:SetPoint("TOPLEFT", self, "BOTTOMRIGHT");
 	GarrisonFollowerTooltip_Show(self.info.garrFollowerID,
@@ -2696,6 +2694,7 @@ function over.GarrisonMissionButton_OnEnter(self, button)
 	if (self.info == nil) then
 		return;
 	end
+	if (addon:IsRewardPage()) then return end
 	collectgarbage("step",100)

 	GameTooltip:SetOwner(self, "ANCHOR_CURSOR_RIGHT");
@@ -2705,7 +2704,7 @@ function over.GarrisonMissionButton_OnEnter(self, button)
 	else
 		GameTooltip:SetText(self.info.name);
 		GameTooltip:AddLine(string.format(GARRISON_MISSION_TOOLTIP_NUM_REQUIRED_FOLLOWERS, self.info.numFollowers), 1, 1, 1);
-		GarrisonMissionButton_AddThreatsToTooltip(self.info.missionID);
+		pcall(GarrisonMissionButton_AddThreatsToTooltip,self.info.missionID);
 		--if (self.info.isRare) then
 		GameTooltip:AddLine(GARRISON_MISSION_AVAILABILITY);
 		GameTooltip:AddLine(self.info.offerTimeRemaining, 1, 1, 1);
@@ -2740,7 +2739,7 @@ function addon:DrawSingleButton(page,button,progressing,bigscreen)
 		over.GarrisonMissionButton_SetRewards(button, mission.rewards, mission.numRewards);
 		self:AddFollowersToButton(button,mission,missionID,bigscreen)
 		if page and not self:IsRewardPage() then
-			addon:AddThreatsToButton(button,mission,missionID,bigscreen)
+			self:AddThreatsToButton(button,mission,missionID,bigscreen)
 		end
 		local a1,f,a2,h,v=button.Title:GetPoint(1)
 		if page then
@@ -3019,6 +3018,17 @@ function addon:AddFollowersToButton(button,mission,missionID,bigscreen)
 		end
 	end
 end
+-- Switchs between active and availabla missions depending on tab object
+function over.GarrisonMissionList_SetTab(...)
+	-- I dont actually care wich page we are shoing, I know I must redraw missions
+	orig.GarrisonMissionList_SetTab(...)
+	addon:RefreshFollowerStatus()
+	for i=1,#GMFMissionListButtons do
+		GMFMissionListButtons.lastMissionID=nil
+	end
+	if (HD) then addon:ResetSinks() end
+end
+

 --hooksecurefunc("GarrisonMissionList_Update",function(...)print("Original GarrisonMissionList_Update",...)end)
 override("GarrisonMissionPage_Close")
@@ -3026,6 +3036,7 @@ override("GarrisonMissionList_Update")
 override("GarrisonMissionButton_SetRewards")
 override("GarrisonMissionButton_OnEnter")
 override("GarrisonMissionPageFollowerFrame_OnEnter")
+override("GarrisonMissionList_SetTab")

 GMF.MissionTab.MissionPage.CloseButton:SetScript("OnClick",over.GarrisonMissionPage_Close)
 for i=1,#GMFMissionListButtons do
diff --git a/GarrisonCommander.toc b/GarrisonCommander.toc
index d378eec..9f2cea0 100644
--- a/GarrisonCommander.toc
+++ b/GarrisonCommander.toc
@@ -35,4 +35,5 @@ FollowerPage.lua
 MatchMaker.lua
 FollowerRecruiting.lua
 GarrisonCommander.xml
+BuildingPage.lua
 RelNotes.lua
diff --git a/GarrisonCommander.xml b/GarrisonCommander.xml
index b6a3062..b344334 100644
--- a/GarrisonCommander.xml
+++ b/GarrisonCommander.xml
@@ -360,4 +360,50 @@
 			</OnLoad>
 		</Scripts>
 	</Frame>
+	<Frame name="GarrisonCommanderUpgradeButton" enableMouse="true" virtual="true">
+		<Size x="32" y="32"/>
+		<Layers>
+			<Layer level="ARTWORK">
+				<Texture parentKey="Icon">
+					<Size x="32" y="32"/>
+					<Anchors>
+						<Anchor point="CENTER"/>
+					</Anchors>
+				</Texture>
+			</Layer>
+			<Layer level="ARTWORK" textureSubLevel="1">
+				<FontString parentKey="Quantity" inherits="NumberFontNormal">
+					<Anchors>
+						<Anchor point="TOPRIGHT" relativeKey="$parent.Icon"/>
+					</Anchors>
+				</FontString>
+				<FontString parentKey="Level" inherits="NumberFontNormal">
+					<Anchors>
+						<Anchor point="BOTTOMRIGHT" relativeKey="$parent.Icon"/>
+					</Anchors>
+				</FontString>
+			</Layer>
+		</Layers>
+		<Scripts>
+			<OnEnter>
+				GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
+				if (self.itemID) then
+					GameTooltip:SetItemByID(self.itemID);
+					return;
+				end
+				if (self.currencyID and self.currencyID ~= 0) then
+					GameTooltip:SetCurrencyByID(self.currencyID);
+					return;
+				end
+				if (self.title) then
+					GameTooltip:SetText(self.title);
+				end
+				if (self.tooltip) then
+					GameTooltip:AddLine(self.tooltip, 1, 1, 1, true);
+				end
+				GameTooltip:Show();
+			</OnEnter>
+			<OnLeave function="GameTooltip_Hide"/>
+		</Scripts>
+	</Frame>
 </Ui>
\ No newline at end of file
diff --git a/Init.lua b/Init.lua
index f8105a3..a51fd69 100644
--- a/Init.lua
+++ b/Init.lua
@@ -9,9 +9,11 @@ local GetChatFrame=GetChatFrame
 local format=format
 local GetTime=GetTime
 local strjoin=strjoin
+local strspilit=strsplit
 local tostringall=tostringall
 --@debug@
 LoadAddOn("Blizzard_DebugTools")
+if LibDebug then LibDebug() end
 --@end-debug@
 ns.addon=LibStub("LibInit"):NewAddon(me,'AceHook-3.0','AceTimer-3.0','AceEvent-3.0','AceBucket-3.0')
 local chatframe=ns.addon:GetChatFrame("aDebug")
@@ -31,10 +33,11 @@ ns.trace=ns.addon:Wrap("Trace")
 ns.xprint=function() end
 ns.xdump=function() end
 ns.xtrace=function() end
+if not _G.GARRISON_FOLLOWER_MAX_ITEM_LEVEL then _G.GARRISON_FOLLOWER_MAX_ITEM_LEVEL=675 end
 --@debug@
---ns.xprint=function(...) pd("|cffff9900DBG|r",...) end
---ns.xdump=function(d,t) pp("|cffff9900DMP|r",t) DevTools_Dump(d) end
---ns.xtrace=ns.trace
+	ns.xprint=print
+	ns.xdump=function(d,t) pp("|cffff9900DMP|r",t) DevTools_Dump(d) end
+	ns.xtrace=print
 --@end-debug@
 do
 	--@debug@
@@ -110,6 +113,99 @@ function addon:releaseEvents()
 end
 local holdEvents,releaseEvents=addon.holdEvents,addon.releaseEvents
 ns.OnLeave=function() GameTooltip:Hide() end
+local upgrades={
+	"wt:120302:1",
+	"we:114128:3",
+	"we:114129:6",
+	"we:114131:9",
+	"wf:114616:615",
+	"wf:114081:630",
+	"wf:114622:645",
+	"at:120301:1",
+	"ae:114745:3",
+	"ae:114808:6",
+	"ae:114822:9",
+	"af:114807:615",
+	"af:114806:630",
+	"af:114746:645",
+}
+local followerItems={}
+local items={
+[114053]={icon='inv_glove_plate_dungeonplate_c_06',quality=2},
+[114052]={icon='inv_jewelry_ring_146',quality=3},
+[114109]={icon='inv_sword_46',quality=3},
+[114068]={icon='inv_misc_pvp_trinket',quality=3},
+[114058]={icon='inv_chest_cloth_reputation_c_01',quality=3},
+[114063]={icon='inv_shoulder_cloth_reputation_c_01',quality=3},
+[114059]={icon='inv_boots_cloth_reputation_c_01',quality=3},
+[114066]={icon='inv_jewelry_necklace_70',quality=3},
+[114057]={icon='inv_bracer_cloth_reputation_c_01',quality=3},
+[114101]={icon='inv_belt_cloth_reputation_c_01',quality=3},
+[114098]={icon='inv_helmet_cloth_reputation_c_01',quality=3},
+[114096]={icon='inv_boots_cloth_reputation_c_01',quality=3},
+[114108]={icon='inv_sword_46',quality=3},
+[114094]={icon='inv_bracer_cloth_reputation_c_01',quality=3},
+[114099]={icon='inv_pants_cloth_reputation_c_01',quality=3},
+[114097]={icon='inv_gauntlets_cloth_reputation_c_01',quality=3},
+[114105]={icon='inv_misc_pvp_trinket',quality=3},
+[114100]={icon='inv_shoulder_cloth_reputation_c_01',quality=3},
+[114110]={icon='inv_sword_46',quality=3},
+[114080]={icon='inv_misc_pvp_trinket',quality=3},
+[114070]={icon='inv_chest_cloth_reputation_c_01',quality=3},
+[114075]={icon='inv_shoulder_cloth_reputation_c_01',quality=3},
+[114071]={icon='inv_boots_cloth_reputation_c_01',quality=3},
+[114078]={icon='inv_jewelry_necklace_70',quality=3},
+[114069]={icon='inv_bracer_cloth_reputation_c_01',quality=3},
+[114112]={icon='inv_sword_46',quality=4},
+[114087]={icon='inv_misc_pvp_trinket',quality=4},
+[114083]={icon='inv_chest_cloth_reputation_c_01',quality=4},
+[114085]={icon='inv_shoulder_cloth_reputation_c_01',quality=4},
+[114084]={icon='inv_boots_cloth_reputation_c_01',quality=4},
+[114086]={icon='inv_jewelry_necklace_70',quality=4},
+[114082]={icon='inv_bracer_cloth_reputation_c_01',quality=4},
+}
+for i=1,#upgrades do
+	local _,id,level=strsplit(':',upgrades[i])
+	followerItems[id]=level
+end
+function addon:GetUpgrades()
+	return upgrades
+end
+function addon:GetItems()
+	return items
+end
+-- to be moved in LibInit
+function addon:coroutineExecute(interval,func)
+	local co=coroutine.wrap(func)
+	local interval=interval
+	local repeater
+	repeater=function()
+		if (co()) then
+			C_Timer.After(interval,repeater)
+		else
+			repeater=nil
+		end
+	end
+	return repeater()
+end
+addon:coroutineExecute(0.1,
+	function ()
+		for itemID,_ in pairs(followerItems) do
+			GetItemInfo(itemID)
+			coroutine.yield(true)
+		end
+		for i,v in pairs(items) do
+			GetItemInfo(i)
+			coroutine.yield(true)
+		end
+	end
+)
+function addon:GetType(itemID)
+	if (items[itemID]) then return "equip" end
+	if (followerItems[itemID]) then return "followerEquip" end
+	return "generic"
+end
+

 -------------------- to be estracted to CountersCache
 --
@@ -188,6 +284,39 @@ function addon:DumpSinks()
 	self:cutePrint(scroll,sorted)
 end
 end
+local m={}
+function m:AddRow(text,...)
+	local l=AceGUI:Create("Label")
+	l:SetText(text)
+	l:SetColor(...)
+	l:SetFullWidth(true)
+	self:AddChild(l)
+	return l
+end
+function m:AddIconText(icon,text,qt)
+	local l=AceGUI:Create("InteractiveLabel")
+	l:SetFontObject(GameFontNormalSmall)
+	if (qt) then
+		l:SetText(format("%s x %s",text,qt))
+	else
+		l:SetText(text)
+	end
+	l:SetImage(icon)
+	l:SetImageSize(24,24)
+	l:SetFullWidth(true)
+	l.frame:EnableMouse(true)
+	l.frame:SetFrameLevel(999)
+	self:AddChild(l)
+	return l
+end
+function m:AddItem(itemID,qt)
+	local _,itemlink,itemquality,_,_,_,_,_,_,itemtexture=GetItemInfo(itemID)
+	if not itemlink then
+		return self:AddIconText(itemtexture,itemID)
+	else
+		return self:AddIconText(itemtexture,itemlink)
+	end
+end
 function addon:GetScroller(title,type,h,w)
 	h=h or 800
 	w=w or 400
@@ -210,7 +339,7 @@ function addon:GetScroller(title,type,h,w)
 	scrollerWindow:SetWidth(w)
 	scrollerWindow:SetPoint("CENTER")
 	scrollerWindow:Show()
-	scroll.AddRow=function (self,...) return addon:AddRow(self,...) end
+	for k,v in pairs(m) do scroll[k]=v end
 	scroll.addRow=scroll.AddRow
 	return scroll
 end
@@ -309,16 +438,14 @@ function addon:DumpParty(missionID)
 	self:cutePrint(scroll,parties[missionID])
 end
 function addon:DumpAgeDb()
-	local t=new()
+	local t=ns.new()
 	for i,v in pairs(dbcache.seen) do
 		tinsert(t,format("%80s %s %d",self:GetMissionData(i,'name'),date("%d/%m/%y %H:%M:%S",v),ns.wowhead[i]))
 	end
 	local scroll=self:GetScroller("Expire db")
 	self:cutePrint(scroll,t)
-	del(t)
+	ns.del(t)
 end
-_G.GCF=GCF
-_G.MW=173
 --[[
 PlaySound("UI_Garrison_CommandTable_Open");
 	PlaySound("UI_Garrison_CommandTable_Close");
diff --git a/MatchMaker.lua b/MatchMaker.lua
index c927c79..d4e036b 100644
--- a/MatchMaker.lua
+++ b/MatchMaker.lua
@@ -223,16 +223,18 @@ local function MatchMaker(self,missionID,party,includeBusy,onlyBest)
 	P:Close(party)
 	del(buffed)
 end
-function addon:MCMatchMaker(missionID,party)
+function addon:MCMatchMaker(missionID,party,skipEpic)
 	MatchMaker(self,missionID,party,false)
-	if (self:GetMissionData(missionID,'class')=='xp') then
-		for i=1,#party.members do
-			if not self:GetFollowerData(party.members[i],'maxed') then
-				return
+	if (skipEpic) then
+		if (self:GetMissionData(missionID,'class')=='xp') then
+			for i=1,#party.members do
+				if not self:GetFollowerData(party.members[i],'maxed') then
+					return
+				end
 			end
+			party.full=false
+			wipe(party.members)
 		end
-		party.full=false
-		wipe(party.members)
 	end
 end
 function addon:MatchMaker(missionID,party,includeBusy)
diff --git a/MissionCache.lua b/MissionCache.lua
index dfdb9ab..fabd938 100644
--- a/MissionCache.lua
+++ b/MissionCache.lua
@@ -78,6 +78,7 @@ function AddExtraData(mission)
 	mission.followerUpgrade=0
 	mission.itemLevel=0
 	mission.xpBonus=0
+	mission.others=0
 	local numrewards=0
 	for k,v in pairs(mission.rewards) do
 		numrewards=numrewards+1
@@ -87,7 +88,7 @@ function AddExtraData(mission)
 		if (v.icon=="Interface\\Icons\\XPBonus_Icon" and v.followerXP) then
 			mission.xpBonus=mission.xpBonus+v.followerXP
 		elseif (v.itemID) then
-			if (v.itemID~=120205) then
+			if (v.itemID~=120205) then -- xp item
 				local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, itemStackCount,itemEquipLoc, itemTexture, itemSellPrice = GetItemInfo(v.itemID)
 				if (itemName and (not v.quantity or v.quantity==1) and not v.followerXP ) then
 					if (itemLevel > 1 and itemMinLevel >=90 ) then
@@ -95,11 +96,13 @@ function AddExtraData(mission)
 					else
 						mission.followerUpgrade=itemRarity
 					end
+				else
+					mission.others=mission.others+v.quantity
 				end
 			end
 		end
 	end
-	if (mission.resources==0 and mission.gold==0 and mission.itemLevel==0 and mission.followerUpgrade==0 and numrewards <2) then
+	if (mission.resources==0 and mission.gold==0 and mission.itemLevel==0 and mission.followerUpgrade==0 and mission.others==0 and numrewards <2) then
 		mission.xpOnly=true
 		mission.class="xp"
 	else
diff --git a/MissionCompletion.lua b/MissionCompletion.lua
index 144cc57..2c8bfb7 100644
--- a/MissionCompletion.lua
+++ b/MissionCompletion.lua
@@ -5,13 +5,38 @@ local D=ns.D
 local C=ns.C
 local AceGUI=ns.AceGUI
 local _G=_G
+--@debug@
+if LibDebug() then LibDebug() end
+--@end-debug@
+local xprint=ns.xprint
 local new, del, copy =ns.new,ns.del,ns.copy
 local GMF=GarrisonMissionFrame
 local GMFMissions=GarrisonMissionFrameMissions
 local G=C_Garrison
 local GARRISON_CURRENCY=GARRISON_CURRENCY
 ns.missionautocompleting=false
+local pairs=pairs
+local format=format
+local strsplit=strsplit
 local generated
+local salvages={
+114120,114119,114116}
+local converter=CreateFrame("Frame"):CreateTexture()
+function addon:GetFollowerTexture(followerID)
+	local rc,iconID=pcall(addon.GetFollowerData,addon,followerID,"portraitIconID")
+	if rc then
+		xprint(followerID,iconID)
+		if iconID then
+			converter:SetToFileData(iconID)
+			xprint(converter:GetTexture())
+			return converter:GetTexture()
+		end
+		return "Interface\\Garrison\\Portraits\\FollowerPortrait_NoPortrait"
+	else
+		xprint(iconID)
+		return "Interface\\Garrison\\Portraits\\FollowerPortrait_NoPortrait"
+	end
+end
 function addon:GenerateMissionCompleteList(title)
 	if not generated then
 		generated=true
@@ -20,12 +45,6 @@ function addon:GenerateMissionCompleteList(title)
 			local Type="GCMCList"
 			local Version=1
 			local m={} --#Widget
-			local function onEnter(self)
-				if (self.itemlink) then
-					GameTooltip:SetHyperlink(self.itemlink)
-					GameTooltip:Show()
-				end
-			end
 			function m:ScrollDown()
 				local obj=self.scroll
 				if (#self.missions >1 and obj.scrollbar and obj.scrollbar:IsShown()) then
@@ -37,7 +56,6 @@ function addon:GenerateMissionCompleteList(title)
 				wipe(self.missions)
 			end
 			function m:OnClose()
-				print("azzero completing")
 				ns.missionautocompleting=nil
 			end
 			function m:Show()
@@ -47,6 +65,14 @@ function addon:GenerateMissionCompleteList(title)
 				self.frame:Hide()
 				self:Release()
 			end
+			function m:AddButton(text,action)
+				local obj=self.scroll
+				local b=AceGUI:Create("Button")
+				b:SetFullWidth(true)
+				b:SetText(text)
+				b:SetCallback("OnClick",action)
+				obj:AddChild(b)
+			end
 			function m:AddMissionButton(mission)
 				local obj=self.scroll
 				local b=AceGUI:Create("GMCSlimMissionButton")
@@ -56,7 +82,7 @@ function addon:GenerateMissionCompleteList(title)
 				self.missions[mission.missionID]=b
 				obj:AddChild(b)
 			end
-			function m:AddMissionName(missionID,success)
+			function m:AddMissionResult(missionID,success)
 				local mission=self.missions[missionID]
 				if mission then
 					local frame=mission.frame
@@ -89,14 +115,16 @@ function addon:GenerateMissionCompleteList(title)
 			function m:AddFollower(followerID,xp,levelup)
 				local follower=addon:GetFollowerData(followerID)
 				if follower.maxed and not levelup then
-					return self:AddRow(format("%s is already at maximum xp",addon:GetFollowerData(followerID,'fullname')))
+					return self:AddIconText(addon:GetFollowerTexture(followerID),
+										format("%s is already at maximum xp",addon:GetFollowerData(followerID,'fullname')))
 				end
 				local quality=G.GetFollowerQuality(followerID) or follower.quality
 				local level=G.GetFollowerLevel(followerID) or follower.level
 				if levelup then
 					PlaySound("UI_Garrison_CommandTable_Follower_LevelUp");
 				end
-				return self:AddRow(format("%s gained %d xp%s%s",addon:GetFollowerData(followerID,'fullname',true),xp,
+				return self:AddIconText(addon:GetFollowerTexture(followerID),
+				format("%s gained %d xp%s%s",addon:GetFollowerData(followerID,'fullname',true),xp,
 				levelup and " |cffffed1a*** Level Up ***|r ." or ".",
 				format(" %d to go.",addon:GetFollowerData(followerID,'levelXP')-addon:GetFollowerData(followerID,'xp'))))
 			end
@@ -123,9 +151,9 @@ function addon:GenerateMissionCompleteList(title)
 				local obj=self.scroll
 				local _,itemlink,itemquality,_,_,_,_,_,_,itemtexture=GetItemInfo(itemID)
 				if not itemlink then
-					self:AddIconText(itemtexture,itemID)
+					self:AddIconText(itemtexture,itemID,qt)
 				else
-					self:AddIconText(itemtexture,itemlink)
+					self:AddIconText(itemtexture,itemlink,qt)
 				end
 			end
 			local function Constructor()
@@ -157,7 +185,7 @@ do
 	local states={}
 	local currentMission
 	local rewards={
-		items=setmetatable({},{__index=function() return 0 end}),
+		items={},
 		followerBase={},
 		followerXP=setmetatable({},{__index=function() return 0 end}),
 		currencies=setmetatable({},{__index=function(t,k) rawset(t,k,{icon="",qt=0}) return t[k] end}),
@@ -193,13 +221,11 @@ do
 		self:UnregisterEvent("GARRISON_MISSION_BONUS_ROLL_LOOT")
 		self:UnregisterEvent("GARRISON_MISSION_COMPLETE_RESPONSE")
 		self:UnregisterEvent("GARRISON_FOLLOWER_XP_CHANGED")
-		self:UnregisterEvent("GET_ITEM_INFO_RECEIVED")
 		if start then
 			self:RegisterEvent("GARRISON_MISSION_BONUS_ROLL_LOOT","MissionAutoComplete")
 			self:RegisterEvent("GARRISON_MISSION_BONUS_ROLL_COMPLETE","MissionAutoComplete")
 			self:RegisterEvent("GARRISON_MISSION_COMPLETE_RESPONSE","MissionAutoComplete")
 			self:RegisterEvent("GARRISON_FOLLOWER_XP_CHANGED","MissionAutoComplete")
-			self:RegisterEvent("GET_ITEM_INFO_RECEIVED","MissionAutoComplete")
 		else
 			self:SafeRegisterEvent("GARRISON_MISSION_BONUS_ROLL_LOOT")
 			self:SafeRegisterEvent("GARRISON_MISSION_BONUS_ROLL_COMPLETE")
@@ -229,17 +255,20 @@ do
 				for k,v in pairs(missions[i].followers) do
 					rewards.followerBase[v]=self:GetFollowerData(v,'qLevel')
 				end
+				local m=missions[i]
+				local _
+				_,_,_,m.successChance,_,_,m.xpBonus,m.resourceMultiplier,m.goldMultiplier=G.GetPartyMissionInfo(m.missionID)
 			end
 			currentMission=tremove(missions)
-			self:MissionEvents(true)
 			self:MissionAutoComplete("LOOP")
+			self:MissionEvents(true)
 		end
 	end
 	function addon:MissionAutoComplete(event,ID,arg1,arg2,arg3,arg4)
 -- C_Garrison.MarkMissionComplete Mark mission as complete and prepare it for bonus roll, da chiamare solo in caso di successo
 -- C_Garrison.MissionBonusRoll
 	--@debug@
-		print("evt",event,ID,arg1,arg2,agr3)
+		print("evt",event,ID,arg1,arg2,arg3)
 	--@end-debug@
 		if self['Event'..event] then
 			self['Event'..event](self,event,ID,arg1,arg2,arg3,arg4)
@@ -259,13 +288,9 @@ do
 				rewards.followerXP[ID]=rewards.followerXP[ID]+tonumber(arg1) or 0
 			end
 			return
-		-- GET_ITEM_INFO_RECEIVED: itemID
-		elseif (event=="GET_ITEM_INFO_RECEIVED") then
-			rewards.items[format("%d:%s",currentMission.missionID,ID)]=1
-			return
-		-- GET_ITEM_INFO_RECEIVED: itemID
+		-- GARRISON_MISSION_BONUS_ROLL_LOOT: itemID
 		elseif (event=="GARRISON_MISSION_BONUS_ROLL_LOOT") then
-			if (currentMissission) then
+			if (currentMission) then
 				rewards.items[format("%d:%s",currentMission.missionID,ID)]=1
 			else
 				rewards.items[format("%d:%s",0,ID)]=1
@@ -280,8 +305,6 @@ do
 				currentMission.state=1
 			else -- failure, just print results
 				currentMission.state=2
-				startTimer(0.1)
-				return
 			end
 			startTimer(0.1)
 			return
@@ -303,9 +326,7 @@ do
 				if (step<1) then
 					step=0
 					currentMission.state=0
-					local _
-					_,_,_,currentMission.successChance,_,_,currentMission.xpBonus,currentMission.multiplier,currentMission.golds=G.GetPartyMissionInfo(currentMission.missionID)
-					currentMission.golds=currentMission.golds or 1
+					currentMission.goldMultiplier=currentMission.goldMultiplier or 1
 					currentMission.xp=select(2,G.GetMissionInfo(currentMission.missionID))
 					report:AddMissionButton(currentMission)
 				end
@@ -322,31 +343,31 @@ do
 				end
 				currentMission.state=step
 			else
-				report:AddRow(L["              Final Report                "])
-				startTimer(0.3,"LOOT")
+				report:AddButton(L["Building Final report"],function() addon:MissionsPrintResult() end)
+				startTimer(1,"LOOT")
 			end
 		end
 	end
 	function addon:GetMissionResults(success)
 		stopTimer()
 		if (success) then
-			report:AddMissionName(currentMission.missionID,true)
+			report:AddMissionResult(currentMission.missionID,true)
 			PlaySound("UI_Garrison_Mission_Complete_Mission_Success")
 		else
-			report:AddMissionName(currentMission.missionID,false)
+			report:AddMissionResult(currentMission.missionID,false)
 			PlaySound("UI_Garrison_Mission_Complete_Encounter_Fail")
 		end
 		if success then
+			local resourceMultiplier=currentMission.resourceMultiplier or 1
+			local goldMultiplier=currentMission.goldMultiplier or 1
 			for k,v in pairs(currentMission.rewards) do
 				v.quantity=v.quantity or 0
-				v.multiplier=v.multiplier or 1
-				v.golds=v.golds or 1
 				if v.currencyID then
 					rewards.currencies[v.currencyID].icon=v.icon
 					if v.currencyID == 0 then
-						rewards.currencies[v.currencyID].qt=rewards.currencies[v.currencyID].qt+v.quantity * v.golds
+						rewards.currencies[v.currencyID].qt=rewards.currencies[v.currencyID].qt+v.quantity * goldMultiplier
 					elseif v.currencyID == GARRISON_CURRENCY then
-						rewards.currencies[v.currencyID].qt=rewards.currencies[v.currencyID].qt+v.quantity * v.multiplier
+						rewards.currencies[v.currencyID].qt=rewards.currencies[v.currencyID].qt+v.quantity * resourceMultiplier
 					else
 						rewards.currencies[v.currencyID].qt=rewards.currencies[v.currencyID].qt+v.quantity
 					end
@@ -375,10 +396,19 @@ do
 				report:AddIconText(v.icon,GetCurrencyLink(k),v.qt)
 			end
 		end
+		local items=new()
 		for k,v in pairs(rewards.items) do
 			local missionid,itemid=strsplit(":",k)
-			report:AddItem(itemid,v)
+			if (not items[itemid]) then
+				items[itemid]=1
+			else
+				items[itemid]=items[itemid]+1
+			end
+		end
+		for itemid,qt in pairs(items) do
+			report:AddItem(itemid,qt)
 		end
+		del(items)
 		for k,v in pairs(rewards.followerXP) do
 			report:AddFollower(k,v,self:GetFollowerData(k,'qLevel') > rewards.followerBase[k])
 		end
diff --git a/MissionControl.lua b/MissionControl.lua
index ed86884..c2d7973 100644
--- a/MissionControl.lua
+++ b/MissionControl.lua
@@ -130,6 +130,7 @@ do
 				GMC.ml.widget:SetTitleColor(C.Green())
 				wipe(GMCUsedFollowers)
 				this:Enable()
+				GMC.runButton:Enable()
 				if (#GMC.ml.Parties>0) then
 					GMC.runButton:Enable()
 				end
@@ -158,7 +159,7 @@ do
 					minimumChance=tonumber(GMC.settings.rewardChance[checkprio]) or 100
 				end
 				local party={members={},perc=0}
-				self:MCMatchMaker(missionID,party,false,false)
+				self:MCMatchMaker(missionID,party,GMC.settings.skipEpic)
 				xprint ("                           Requested",class,";",minimumChance,"Mission",party.perc,party.full)
 				if ( party.full and party.perc >= minimumChance) then
 					xprint("                           Mission accepted")
@@ -206,9 +207,17 @@ function addon:GMC_OnClick_Start(this,button)
 	GMC.ml.widget:ClearChildren()
 	if (self:GetTotFollowers(AVAILABLE) == 0) then
 		GMC.ml.widget:SetTitle("All followers are busy")
+		GMC.ml.widget:SetTitleColor(C.Orange())
+		return
+	end
+	if ( G.IsAboveFollowerSoftCap() ) then
+		GMC.ml.widget:SetTitle(GARRISON_MAX_FOLLOWERS_MISSION_TOOLTIP)
+		GMC.ml.widget:SetTitleColor(C.Red())
 		return
 	end
 	this:Disable()
+	GMC.runButton:Disable()
+	GMC.ml.widget:SetTitleColor(C.Green())
 	addon:GMCCreateMissionList(aMissions)
 	wipe(GMCUsedFollowers)
 	wipe(GMC.ml.Parties)
@@ -222,6 +231,13 @@ function addon:GMC_OnClick_Start(this,button)
 	self:RawHookScript(GMC.startButton,'OnUpdate',"GMCCalculateMissions")

 end
+function addon:HasSalvageYard()
+	local buildings=G.GetBuildings()
+	for i =1,#buildings do
+		local building=buildings[i]
+		if building.texPrefix=="GarrBuilding_SalvageYard_1_A" then return true end
+	end
+end
 local chestTexture
 function addon:GMCBuildPanel(bigscreen)
 	db=self.db.global
@@ -230,8 +246,9 @@ function addon:GMCBuildPanel(bigscreen)
 	chestTexture='GarrMission-'..UnitFactionGroup('player').. 'Chest'
 	GMC = CreateFrame('FRAME', 'GMCOptions', GMF)
 	GMC.settings=dbcache.missionControl
-	GMC:SetPoint('CENTER')
-	GMC:SetSize(GMF:GetWidth(), GMF:GetHeight())
+	GMC:SetAllPoints()
+	--GMC:SetPoint('LEFT')
+	--GMC:SetSize(GMF:GetWidth(), GMF:GetHeight())
 	GMC:Hide()
 	local chance=self:GMCBuildChance()
 	local duration=self:GMCBuildDuration()
@@ -241,13 +258,13 @@ function addon:GMCBuildPanel(bigscreen)
 	duration:SetPoint("TOPLEFT",0,-50)
 	chance:SetPoint("TOPLEFT",duration,"TOPRIGHT",bigscreen and 50 or 10,0)
 	priorities:SetPoint("TOPLEFT",duration,"BOTTOMLEFT",25,-40)
-	rewards:SetPoint("TOPLEFT",priorities,"TOPRIGHT",bigscreen and 50 or 15,0)
+	rewards:SetPoint("TOPLEFT",priorities,"TOPRIGHT",bigscreen and 50 or 15,30)
 	list:SetPoint("TOPLEFT",chance,"TOPRIGHT",10,-30)
 	list:SetPoint("BOTTOMRIGHT",GMF,"BOTTOMRIGHT",-25,25)
 	GMC.startButton = CreateFrame('BUTTON',nil,  list.frame, 'GameMenuButtonTemplate')
 	GMC.startButton:SetText('Calculate')
 	GMC.startButton:SetWidth(148)
-	GMC.startButton:SetPoint('TOPLEFT',15,25)
+	GMC.startButton:SetPoint('TOPLEFT',10,25)
 	GMC.startButton:SetScript('OnClick', function(this,button) self:GMC_OnClick_Start(this,button) end)
 	GMC.startButton:SetScript('OnEnter', function() GameTooltip:SetOwner(GMC.startButton, 'ANCHOR_TOPRIGHT') GameTooltip:AddLine('Assign your followers to missions.') GameTooltip:Show() end)
 	GMC.startButton:SetScript('OnLeave', function() GameTooltip:Hide() end)
@@ -261,9 +278,14 @@ function addon:GMCBuildPanel(bigscreen)
 	end)
 	GMC.runButton:SetScript('OnLeave', function() GameTooltip:Hide() end)
 	GMC.runButton:SetWidth(148)
-	GMC.runButton:SetPoint('TOPRIGHT',-15,25)
 	GMC.runButton:SetScript('OnClick',function(this,button) self:GMC_OnClick_Run(this,button) end)
 	GMC.runButton:Disable()
+	GMC.runButton:SetPoint('TOPRIGHT',-10,25)
+	GMC.logoutButton=CreateFrame('BUTTON', nil,list.frame, 'GameMenuButtonTemplate')
+	GMC.logoutButton:SetText(LOGOUT)
+	GMC.logoutButton:SetWidth(ns.bigscreen and 148 or 90)
+	GMC.logoutButton:SetScript("OnClick",Logout)
+	GMC.logoutButton:SetPoint('TOP',0,25)
 	GMC.skipRare=factory:Checkbox(GMC,GMC.settings.skipRare,L["Ignore rare missions"])
 	GMC.skipRare:SetPoint("TOPLEFT",priorities,"BOTTOMLEFT",0,-10)
 	GMC.skipRare:SetScript("OnClick",function(this)
@@ -276,9 +298,18 @@ function addon:GMCBuildPanel(bigscreen)
 	warning:SetPoint("TOPRIGHT",GMC,"TOPRIGHT",0,-25)
 	warning:SetJustifyH("CENTER")
 	warning:SetTextColor(C.Orange())
-	GMC.Credits=GMC:CreateFontString(nil,"ARTWORK","DestinyFontLarge")
+	if (GMC.settings.skipEpic) then warning:Show() else warning:Hide() end
+	GMC.skipEpic=factory:Checkbox(GMC,GMC.settings.skipEpic,L["Ignore epic followers for xp only missions"])
+	GMC.skipEpic:SetPoint("TOPLEFT",GMC.skipRare,"BOTTOMLEFT",0,-10)
+	GMC.skipEpic:SetScript("OnClick",function(this)
+		GMC.settings.skipEpic=this:GetChecked()
+		if (GMC.settings.skipEpic) then warning:Show() else warning:Hide() end
+		addon:GMC_OnClick_Start(GMC.startButton,"LeftUp")
+	end)
+	GMC.Credits=GMC:CreateFontString(nil,"ARTWORK","QuestFont_Shadow_Small")
 	GMC.Credits:SetWidth(0)
 	GMC.Credits:SetFormattedText(C("Original concept and interface by %s",'Yellow'),C("Motig","Red") )
+	GMC.Credits:SetJustifyH("LEFT")
 	GMC.Credits:SetPoint("BOTTOMLEFT",25,25)
 	return GMC
 end
@@ -412,8 +443,6 @@ end
 function addon:GMCBuildRewards()
 	--Allowed rewards
 	GMC.aif = CreateFrame('FRAME', nil, GMC)
-	GMC.aif:SetPoint('CENTER', 0, 120)
-
 	GMC.itf = GMC.aif:CreateFontString()
 	GMC.itf:SetFontObject('GameFontNormalHuge')
 	GMC.itf:SetText('Allowed Rewards')
@@ -431,7 +460,8 @@ function addon:GMCBuildRewards()
 		{t = 'Enable/Disable other currency awards. (Resources/Seals)', i= 'Interface\\Icons\\inv_garrison_resource', key = 'resources'},
 		{t = 'Enable/Disable Follower XP Bonus rewards.', i = 'Interface\\Icons\\XPBonus_Icon', key = 'xp'},
 		{t = 'Enable/Disable follower equip enhancement.', i = 'Interface\\ICONS\\Garrison_ArmorUpgrade', key = 'followerEquip'},
-		{t = 'Enable/Disable item tokens.', i = "Interface\\ICONS\\INV_Bracer_Cloth_Reputation_C_01", key = 'equip'}
+		{t = 'Enable/Disable item tokens.', i = "Interface\\ICONS\\INV_Bracer_Cloth_Reputation_C_01", key = 'equip'},
+		{t = 'Enable/Disable other rewards.', i = "Interface\\ICONS\\INV_Box_02", key = 'generic'}
 	}
 	local scale=1.1
 	GMC.ignoreFrames = {}
@@ -510,7 +540,8 @@ do
 		followerUpgrade="Followr Upgrade",
 		xp="Xp gain",
 		gold="Gold Reward",
-		resources="Resource Rewards"
+		resources="Resource Rewards",
+		generic="Other Rewards"
 	}
 	prioVoices=0
 	for _ in pairs(prioTitles) do prioVoices=prioVoices+1 end