view ClassPlanShipments.lua @ 73:25f7dbc20a72

fix WorldMapTooltip getting stranded when flightmap is closed - quests that are not valid spell targets will have their icon go red - auto-complete scrolls will no longer hide pin frames; instead they become click through and blizzard POIs are activated beneath for taint-free interaction
author Nenue
date Fri, 07 Apr 2017 07:20:28 -0400
parents 589c444d4837
children b29b35cb8539
line wrap: on
line source
local _, db = ...

local wipe, tinsert, ipairs, select = table.wipe, table.insert, ipairs, select
local UnitClass = UnitClass
local time, max, min = time, max, min
local print = DEVIAN_WORKSPACE and function(...) print('ClassPlan', ...) end or nop


local CG_GetBuildings = C_Garrison.GetBuildings
local CG_GetFollowerShipments = C_Garrison.GetFollowerShipments
local CG_GetLooseShipments = C_Garrison.GetLooseShipments
local CG_GetTalentTrees = C_Garrison.GetTalentTrees
local CG_GetCompleteTalent = C_Garrison.GetCompleteTalent
local CG_GetLandingPageShipmentInfo = C_Garrison.GetLandingPageShipmentInfo
local CG_GetLandingPageShipmentInfoByContainerID = C_Garrison.GetLandingPageShipmentInfoByContainerID

local AK_NOTES, RECRUIT_MAJOR, RECRUIT_MINOR, OH_TALENT, NOMI = 2, 4, 8, 16, 32

local FollowerTypes = {
  ['Pathfinders'] = true,
  ['Acolytes'] = true,
}
local ShipmentOrder = {
  [AK_NOTES] = 2,
  [RECRUIT_MAJOR] = 3,
  [RECRUIT_MINOR] = 4,
  [NOMI] = 5,
  [OH_TALENT] = 6,
}
local SortKey = 'shipmentType'
local SortTable = ShipmentOrder

local ShipmentList = {
  templateName = 'ClassPlanShipmentEntry',
  listKey = {'shipments'},
  listTitle = {'Work Orders'},
  events = {
    'GARRISON_MISSION_LIST_UPDATE',
    'GARRISON_LANDINGPAGE_SHIPMENTS',
    'GARRISON_TALENT_UPDATE',
    "GARRISON_TALENT_COMPLETE",
    "GARRISON_SHIPMENT_RECEIVED",
    'GARRISON_FOLLOWER_LIST_UPDATE',
    'SHIPMENT_CRAFTER_INFO',
    'ITEM_PUSH'},
}

local ShipmentEntry = {}

function ShipmentList:Reanchor()
  print('|cFF00FFFF'..self:GetName()..':Reanchor|r')
  self:SetPoint('TOPLEFT', ClassOrderPlan.BackgroundInset, 'TOPLEFT')
  self:SetPoint('BOTTOMRIGHT', -ClassOrderPlan.BackgroundInset:GetWidth()/2, 0)
end

do
  local ShipmentsInfo = {}
  local AddShipmentInfo = function(shipmentType, name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID, followerID)
    -- early login queries may return empty tables, causing the sorter to compare nil
    if not creationTime then
      return
    end
    --print(shipmentType, name, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString)
    tinsert(ShipmentsInfo,
      {
        shipmentType = shipmentType,
        name = name,
        icon = texture,
        shipmentCapacity = shipmentCapacity,
        shipmentsReady = shipmentsReady,
        shipmentsTotal = shipmentsTotal,
        creationTime = creationTime,
        duration = duration,
        timeleftString = timeleftString,
        itemName = itemName,
        itemIcon = itemIcon,
        itemQuality = itemQuality,
        itemID = itemID,
        followerID = followerID,
      })
    print('  ', name, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration)
  end
  function ShipmentList:GetPlayerData ()
    local profileList = self:GetParent().profile.shipments
    wipe(ShipmentsInfo)

    local garrisonType = LE_GARRISON_TYPE_7_0
    local buildings = CG_GetBuildings(garrisonType);
    local shipmentIndex = 0
    --print('Buildings:')
    for i = 1, #buildings do
      local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID = CG_GetLandingPageShipmentInfo(i);
      AddShipmentInfo(RECRUIT_MAJOR, name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID)
    end

    --print('Follower:')
    local followerShipments = CG_GetFollowerShipments(garrisonType);
    for i = 1, #followerShipments do
      local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, _, _, _, _, followerID = CG_GetLandingPageShipmentInfoByContainerID(followerShipments[i]);
      AddShipmentInfo(RECRUIT_MINOR, name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, nil, nil, nil, nil, followerID)
    end

    --print('Loose:')
    local looseShipments = CG_GetLooseShipments(garrisonType)
    for i = 1, #looseShipments do
      local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString = CG_GetLandingPageShipmentInfoByContainerID(looseShipments[i]);
      AddShipmentInfo(AK_NOTES, name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString)
    end

    local talentTrees = CG_GetTalentTrees(garrisonType, select(3, UnitClass("player")));
    -- this is a talent that has completed, but has not been seen in the talent UI yet.
    local completeTalentID = CG_GetCompleteTalent(garrisonType);
    --print('Talents:')
    if (talentTrees) then
      for treeIndex, tree in ipairs(talentTrees) do
        for talentIndex, talent in ipairs(tree) do
          local showTalent = false;
          if (talent.isBeingResearched) or (talent.id == completeTalentID) then
            AddShipmentInfo(OH_TALENT, talent.name, talent.icon, 1, (talent.isBeingResearched and 0 or 1), 1, talent.researchStartTime, talent.researchDuration, talent.timeleftString)
          end
        end
      end
    end

    wipe(profileList)
    for index, data in ipairs(ShipmentsInfo) do
      --DEFAULT_CHAT_FRAME:AddMessage(data.shipmentType ..' '.. tostring(data.name) ..' '.. tostring(data.creationTime) ..' '.. tostring(data.duration))
      tinsert(profileList, data)
    end
    self.isStale = true
    return true
  end
end
-- Update shipment flags data
local SetActualShipmentTime = function(self)

  if self.isComplete then
    return nil, nil
  end

  local timestamp = time()
  local timeLeft = self.creationTime + self.duration - timestamp
  local duration = self.duration * (self.fullDuration and (self.shipmentsTotal - self.shipmentsReady) or 1)
  local justFinished = false
  while (self.shipmentsReady < self.shipmentsTotal) and (timeLeft <= 0) do
    if not self.originalReady then
      self.originalReady = self.shipmentsReady
      self.originalCreationTime = self.creationTime
    end

    self.shipmentsReady = self.shipmentsReady + 1
    self.creationTime = self.creationTime + self.duration
    timeLeft = timeLeft + self.duration
    print('|cFF00FF88  pre-parse "'..self.name..'"|r', 'timeLeft:', timeLeft, 'shipments:', self.shipmentsReady, self.shipmentsTotal)
  end

  if (timeLeft <= 0) and (not self.isBeingResearched) then
    self.isComplete = true
    self.isStale = true
  end

  local expires = (self.originalCreationTime or self.creationTime) + duration
  return expires, duration
end

function ShipmentList:OnEvent(event, ...)
  if (event == 'SHIPMENT_CRAFTER_INFO' or event == 'ITEM_PUSH' or event == 'GARRISON_FOLLOWER_LIST_UPDATE') then
    C_Garrison.RequestLandingPageShipmentInfo()
  elseif event == 'SHIPMENT_UPDATE' then
    local shipmentStarted = ...
    if shipmentStarted then
      C_Garrison.RequestLandingPageShipmentInfo()
    end
  elseif event == 'GARRISON_LANDINGPAGE_SHIPMENTS' then
    --WorldPlan:print("New shipments data received.")
    self:RefreshData()
  else
    ClassPlanHandlerBase.OnEvent(self, event, ...)
  end
end


function ShipmentList:OnGetItem (data)
  if data.shipmentsTotal then
    local expires = SetActualShipmentTime(data)
    if expires and (expires > time()) then
      self:ScheduleUpdate(expires)
    end
  end

  if data.shipmentType == 255 or type(data.shipmentType == 'string') then
    if data.name == 'Artifact Research Notes' then
      data.shipmentType = AK_NOTES
    elseif string.match(data.name, 'Recipes') then
      data.shipmentType = NOMI
    elseif FollowerTypes[data.name] then
      data.shipmentType = RECRUIT_MINOR
    else
      data.shipmentType = OH_TALENT
    end
  end


end

function ShipmentList:OnHeaderClick()
  -- flip sort table and key, push a sort and refresh
end


ShipmentList.SortHandler = function(a, b)
  if a[SortKey]  then
    if b[SortKey] then
      return SortTable[a[SortKey]] < SortTable[b[SortKey]]
    else
      return true
    end
  else
    if b.isComplete ~= a.isComplete then
      return a.isComplete and true or false
    else
      if a.profileKey ~= b.profileKey then
        return a.profileKey < b.profileKey
      else
        if a.shipmentsReady and b.shipmentsReady then
          return (a.shipmentsReady) > (b.shipmentsReady)
        elseif a.shipmentsReady or b.shipmentsReady then
          return (a.shipmentsReady) or true or false
        else

          if (a.creationTime ~= b.creationTime) then
            return (a.creationTime) < (b.creationTime)
          else
            return (a.name) < (b.name)
          end
        end

      end
    end
  end
end

function ShipmentList:OnLoad()
end
function  ShipmentList:OnShow()
  print('|cFF00FF88'..self:GetName()..':OnShow()|r')
end

function ShipmentEntry:OnLoad()
  ClassPlanMissionEntryMixin.OnLoad(self)
end


function ShipmentEntry:Update()
  --print('  |cFF00FF88"'.. self.name..'":Update()|r')
  self.Icon:SetTexture(self.icon)
  self.Count:SetText(self.shipmentsReady ..'/'.. self.shipmentsTotal)

  -- flag as complete
  local itemType = db.ClassPlanTypes.inProgress
  if ( self.shipmentsReady >= self.shipmentsTotal ) and (not self.isBeingResearched) then
    self.Swipe:SetCooldownUNIX(0, 0);
    itemType = db.ClassPlanTypes.complete
  else
    if (self.shipmentsReady >= 1) and (self.shipmentsReady < self.shipmentsTotal) then
      itemType = db.ClassPlanTypes.shipmentsReady
    end
    self.Swipe:SetCooldownUNIX(self.creationTime or 0 , self.duration or 0);
  end
  self.Background:SetColorTexture(unpack(itemType.backgroundColor))

  SetActualShipmentTime(self)
  self.throttle = 2
end



function ShipmentEntry:OnUpdate(sinceLast)
  self.throttle = (self.throttle or 1) + sinceLast
  if self.throttle >= 1 then
    self.throttle = self.throttle - 1
  else
    return
  end

  if (self.shipmentsReady and self.shipmentsTotal) and (self.shipmentsReady < self.shipmentsTotal) then
    local expires, duration = SetActualShipmentTime(self)
    if self.isComplete then
      self.TimeLeft:SetText('Complete!')
      self.TimeLeft:SetTextColor(0,1,1)
    elseif self.shipmentsReady >= 1 then
      self:SetTimeLeft(expires, duration)
      self.TimeLeft:SetTextColor(1,1,0)
    else
      self:SetTimeLeft(expires, duration)
      self.TimeLeft:SetTextColor(1,1,1)
    end
  elseif self.isBeingResearched then
    self:SetTimeLeft(self.researchStartTime + self.researchDuration - time(), self.researchDuration)
    self.TimeLeft:SetTextColor(1,1,1)
  else
    self.TimeLeft:SetText('Complete!')
    self.TimeLeft:SetTextColor(0,1,0)
  end
end

function ShipmentEntry:OnEnter()
  if ( self.shipmentsReady and self.shipmentsTotal ) then
    GameTooltip:SetOwner(self, 'ANCHOR_LEFT')
    GameTooltip:AddLine(self.Owner:GetText(), self.Owner:GetTextColor())
    GameTooltip:AddLine(self.shipmentsReady .. ' of '.. self.shipmentsTotal)
    GameTooltip:Show()
  end
end


function ShipmentEntry:OnLeave()
  if GameTooltip:IsOwned(self) then
    GameTooltip:Hide()
  end
end

function ShipmentEntry:OnClick(button)
  self.fullDuration = not self.fullDuration
  self:Update()
end

ClassPlanShipmentHandler = CreateFromMixins(ClassPlanHandlerBase, ShipmentList)
ClassPlanShipmentEntryMixin = CreateFromMixins(ClassPlanEntryBase, ShipmentEntry)