You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
7.8 KiB
196 lines
7.8 KiB
local _,rematch = ...
|
|
local L = rematch.localization
|
|
local C = rematch.constants
|
|
local settings = rematch.settings
|
|
rematch.savedTargets = {}
|
|
|
|
--[[
|
|
Teams can contain a list of targets; but targets also need an ordered list of teams so teams can
|
|
load in a preferred order. There also needs to be a lookup table indexed by targetID so the player
|
|
changing targets will have an immediate answer to whether the target has a team.
|
|
|
|
rematch.savedTargets[targetID] = {
|
|
teamID1, -- ordered lists of teamIDs that use this target
|
|
teamID2,
|
|
teamID3,
|
|
}
|
|
|
|
targetID is "target:npcID"
|
|
|
|
Note: It's possible for npcID to not be a notable target. A player can save a target for any npc.
|
|
(Use rematch.targetInfo to get information about a targetID)
|
|
]]
|
|
|
|
Rematch5SavedTargets = {} -- savedvar indexed by targetID, an ordered list of teamIDs for this target
|
|
|
|
-- iterator for targets: for targetID,teams in rematch.savedTargets:AllTargets()
|
|
function rematch.savedTargets:AllTargets()
|
|
return next, Rematch5SavedTargets, nil
|
|
end
|
|
|
|
-- fills all savedTargets with teamIDs picked up from savedTeams
|
|
local targetsInTeams = {}
|
|
function rematch.savedTargets:Update()
|
|
|
|
-- wipe old lookup
|
|
for targetID,teams in pairs(targetsInTeams) do
|
|
wipe(targetsInTeams[targetID])
|
|
end
|
|
|
|
-- gather targetIDs in teams into lookup table
|
|
for teamID,team in rematch.savedTeams:AllTeams() do
|
|
if team.targets then
|
|
for _,targetID in ipairs(team.targets) do
|
|
if not targetsInTeams[targetID] then
|
|
targetsInTeams[targetID] = {}
|
|
end
|
|
targetsInTeams[targetID][teamID] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
-- if an existing saved target has no teams assigned to it, remove the saved target
|
|
for targetID in pairs(targetsInTeams) do
|
|
if not next(targetsInTeams[targetID]) then
|
|
targetsInTeams[targetID] = nil
|
|
rematch.savedTargets[targetID] = nil
|
|
end
|
|
end
|
|
|
|
-- remove teams not used in a target
|
|
for targetID,teams in rematch.savedTargets:AllTargets() do
|
|
for i=#teams,1,-1 do
|
|
if not targetsInTeams[targetID] or not targetsInTeams[targetID][teams[i]] then
|
|
tremove(teams,i)
|
|
end
|
|
end
|
|
if #teams==0 then -- and remove target if all teams removed
|
|
rematch.savedTargets[targetID] = nil
|
|
end
|
|
end
|
|
|
|
-- if any teams are not in savedTargets for a target, add them
|
|
for targetID in pairs(targetsInTeams) do
|
|
if not rematch.savedTargets[targetID] then
|
|
rematch.savedTargets[targetID] = {}
|
|
end
|
|
for teamID in pairs(targetsInTeams[targetID]) do
|
|
rematch.utils:TableInsertDistinct(rematch.savedTargets[targetID],teamID)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
-- saves an ordered list of teamIDs to the targetID; specifically, updates the targets in each of the affected
|
|
-- teams while preserving the order of teamIDs in targets and targetIDs in teams
|
|
function rematch.savedTargets:Set(targetID,newTeams)
|
|
if type(targetID)=="string" then
|
|
targetID = rematch.targetInfo:GetNpcID(targetID)
|
|
end
|
|
local oldTeams = rematch.savedTargets[targetID] or {}
|
|
-- first remove the targetID from any teams that are in oldTeams but not in newTeams
|
|
for _,teamID in ipairs(oldTeams) do
|
|
if not tContains(newTeams,targetID) then
|
|
local team = rematch.savedTeams[teamID]
|
|
if team and team.targets then
|
|
rematch.utils:TableRemoveByValue(team.targets,targetID)
|
|
end
|
|
-- if no more targets in this team, remove the targets table from the team
|
|
if #team.targets==0 then
|
|
team.targets = nil
|
|
end
|
|
end
|
|
end
|
|
-- next add targetID to any teams in newTeams that are not in oldTeams
|
|
for _,teamID in ipairs(newTeams) do
|
|
if not tContains(oldTeams,targetID) then
|
|
local team = rematch.savedTeams[teamID]
|
|
if team then
|
|
if not team.targets then
|
|
team.targets = {}
|
|
end
|
|
tinsert(team.targets,targetID)
|
|
end
|
|
end
|
|
end
|
|
-- update savedvar, bypassing setter
|
|
if #newTeams==0 then -- the new teams has no targets, removed savedTargets
|
|
Rematch5SavedTargets[targetID] = nil
|
|
else -- otherwise update savedTargets with new teams without using locked-down setter
|
|
-- create a savedvar for target if one doesn't already exist
|
|
if not Rematch5SavedTargets[targetID] then
|
|
Rematch5SavedTargets[targetID] = {}
|
|
end
|
|
-- then copy newTeams to the savedvar (preserver order)
|
|
wipe(Rematch5SavedTargets[targetID])
|
|
for _,teamID in ipairs(newTeams) do
|
|
tinsert(Rematch5SavedTargets[targetID],teamID)
|
|
end
|
|
end
|
|
-- finally, do a TeamsChanged so everything is ensured to be in sync
|
|
rematch.savedTeams:TeamsChanged()
|
|
end
|
|
|
|
-- returns the ordered list of teamIDs for a target and the index of the first team, which will usually
|
|
-- be 1 (topmost team is preferred teamID for the target), but it can change if Prefer Uninjured Teams
|
|
-- options is enabled. if there are no valid teams it returns nil. if all pets are injured it will return
|
|
-- first valid team's index
|
|
function rematch.savedTargets:GetTeams(targetID)
|
|
if type(targetID)=="string" then
|
|
targetID = rematch.targetInfo:GetNpcID(targetID)
|
|
end
|
|
local teams = targetID and Rematch5SavedTargets[targetID]
|
|
if not teams then
|
|
return nil -- this target has no teams, return nothing
|
|
elseif (#teams==1 or not settings.InteractPreferUninjured) and teams[1] and rematch.savedTeams[teams[1]] then
|
|
return teams,1 -- if only one team (or Prefer Uninjured Teams unchecked), just return the team
|
|
else
|
|
local validIndex -- becomes the index to the first valid team
|
|
for i=1,#teams do
|
|
local team = rematch.savedTeams[teams[i]]
|
|
if team then
|
|
local anyInjured = false
|
|
for j=1,3 do
|
|
anyInjured = anyInjured or rematch.petInfo:Fetch(team.pets[j]).isInjured
|
|
end
|
|
if not validIndex then
|
|
validIndex = i -- only set on first valid team encountered
|
|
end
|
|
if not anyInjured then
|
|
return teams,i -- found an uninjured team, return it
|
|
end
|
|
end
|
|
end
|
|
-- if reached here and a valid team was found, all teams are injured, return topmost team
|
|
if validIndex then
|
|
return teams,validIndex
|
|
else -- if no valid team found, return nil
|
|
return nil
|
|
end
|
|
end
|
|
end
|
|
|
|
-- getting a rematch.savedTargets[npcID] will return the Rematch5SavedTargets for that npcID
|
|
local function getter(self,targetID)
|
|
-- for quickly looking up whether a target has a saved tean it uses npcID, but lists use target:npcID; convert target:npcID to just the numeric npcID if so
|
|
if type(targetID)=="string" then
|
|
local npcID = tonumber(targetID:match("target:(.+)"))
|
|
if npcID then
|
|
targetID = npcID
|
|
end
|
|
end
|
|
if Rematch5SavedTargets[targetID] then
|
|
return Rematch5SavedTargets[targetID]
|
|
else
|
|
return rawget(self,targetID)
|
|
end
|
|
end
|
|
|
|
-- rematch.savedTargets[x] should only ever assign an empty table or nil; all other changes to savedTargets should be through Update or Set
|
|
local function setter(self,targetID,value)
|
|
if not value or (type(value)=="table" and not next(value)) then
|
|
Rematch5SavedTargets[targetID] = value
|
|
end
|
|
end
|
|
|
|
rematch.savedTargets = setmetatable(rematch.savedTargets,{__index = getter, __newindex = setter})
|
|
|