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.

391 lines
13 KiB

--Automatically add Dreamseed locations to Super Track
--Waypoints Priority: 1.Growing (haven't contributed) 2.Chest Available 3.Growing (contributed)
local _, addon = ...
local API = addon.API;
local WIDGET_UPDATE_INTERVAL = 2;
local WAYPOINT_MIN_DISTANCE = 10; --Don't add waypoint if it's closeby
local WAYPOINT_PRIOTIRY_DISTANCE = 180; --Prioritize location that is within x yd away from player --253 yd is where Dreamseed Chest shown on WorldMap
local VIGID_BOUNTY = 5971;
local MAPID_EMRALD_DREAM = 2200;
local DreamseedUtil = API.DreamseedUtil; --Defined in Dreamseed.lua
local GetCreatureIDFromGUID = API.GetCreatureIDFromGUID;
local GetPlayerMapCoord = API.GetPlayerMapCoord;
local SuperTrackFrame;
local C_VignetteInfo = C_VignetteInfo;
local ClearUserWaypoint = C_Map.ClearUserWaypoint;
local tinsert = table.insert;
local tsort = table.sort;
local EL;
local MODULE_ENABLED = false;
local DREAMSEED_FLAGS = {}; --key: creatureID
local CHEST_VIGNETTE_X_CREATURE = {};
local NAME_DREAMSEED_CHEST = nil; --Localized later by API
local FOCUSED_CREATURE; --Plant shown on the Arrow
local PRIORITIZE_CHEST = false; --if false, don't add new waypoints so player can go back and collect rewards
--Flags
--0: not spawned or not growing
--1: growing, contributed
--2: finished growing, has rewards (chest)
--3: growing, haven't contributed
local FLAG_ICON = {
[0] = "Dreamseed-Active",
[1] = "Dreamseed-Active-Visited",
[2] = "Dreamseed-Chest",
[3] = "Dreamseed-Active-New",
};
local function SetDreamseedFlag(creatureID, flag)
if DREAMSEED_FLAGS[creatureID] then
if DREAMSEED_FLAGS[creatureID] ~= flag then
DREAMSEED_FLAGS[creatureID] = flag;
return true
end
end
end
local function GetPlantPosition(creatureID)
local pos = DreamseedUtil:GetBackupLocation(creatureID);
return pos[1], pos[2]
end
function DreamseedUtil:SetNavigatorPrioritizingReward(state)
PRIORITIZE_CHEST = state;
end
function DreamseedUtil:IsNavigatorPrioritizingReward()
return PRIORITIZE_CHEST
end
local function SortFunc_Generic(loc1, loc2)
--locationData: creatureID, x, y, flag, remainingTime, distance
--Prioritize nearyby spawned chest
if loc1[4] == 2 and loc1[6] < WAYPOINT_PRIOTIRY_DISTANCE then
return true
elseif loc2[4] == 2 and loc2[6] < WAYPOINT_PRIOTIRY_DISTANCE then
return false
end
--If there are two uncontributed plants, prioritize the one whose time is running out
if loc1[4] == 3 and loc2[4] == 3 then
if loc1[5] + 60 < loc2[5] then
return true
elseif loc2[5] + 60 < loc1[5] then
return false
end
end
if loc1[4] ~= loc2[4] then
return loc1[4] > loc2[4]
elseif loc1[6] ~= loc2[6] then
return loc1[6] < loc2[6]
end
return false
end
local function SortFunc_RewardFirst(loc1, loc2)
--Prioritize nearyby spawned chest
if loc1[4] == 2 then
if loc2[4] == 2 then
return loc1[6] < loc2[6]
else
return true
end
elseif loc2[4] == 2 then
return false
end
if loc1[4] == 1 then
if loc2[4] == 1 then
--prioritize time
return loc1[5] < loc2[5]
else
return true
end
elseif loc2[4] == 1 then
return false
end
if loc1[6] ~= loc2[6] then
return loc1[6] < loc2[6]
end
return false
end
local function UpdateWaypoints()
if not (SuperTrackFrame and SuperTrackFrame:CanReceiveDataFromNavigator()) then return end;
local playerX, playerY = GetPlayerMapCoord(MAPID_EMRALD_DREAM);
if not (playerX and playerY) then return end;
local vignetteGUIDs = C_VignetteInfo.GetVignettes();
local info;
local uiMapID = MAPID_EMRALD_DREAM;
local creatureID;
local x, y;
local remainingTime, fullTime;
local isActive;
local hasReward, distance;
local flag;
local locations;
local processedCreatures = {};
for i, vignetteGUID in ipairs(vignetteGUIDs) do
info = C_VignetteInfo.GetVignetteInfo(vignetteGUID);
if info then
if info.vignetteID == VIGID_BOUNTY then
--Soil
creatureID = GetCreatureIDFromGUID(info.objectGUID);
elseif CHEST_VIGNETTE_X_CREATURE[info.vignetteID] then
--Dreamseed Chest
if not NAME_DREAMSEED_CHEST then
NAME_DREAMSEED_CHEST = info.name or "Dreamseed Chest";
NAME_DREAMSEED_CHEST = "|cff19ff19"..(NAME_DREAMSEED_CHEST or "Dreamseed Chest").."|r";
end
flag = 2;
creatureID = CHEST_VIGNETTE_X_CREATURE[info.vignetteID];
if not processedCreatures[creatureID] then
processedCreatures[creatureID] = true;
SetDreamseedFlag(creatureID, flag);
local vignettePosition, vignetteFacing = C_VignetteInfo.GetVignettePosition(info.vignetteGUID, uiMapID);
x, y = vignettePosition:GetXY();
distance = DreamseedUtil:GetPlayerDistanceToTarget(playerX, playerY, x, y);
if distance >= WAYPOINT_MIN_DISTANCE then
if not locations then
locations = {};
end
tinsert(locations, {creatureID, x, y, flag, 0, distance});
end
DreamseedUtil:SetPlantContributedByCreatureID(creatureID, true);
end
end
end
end
for creatureID in pairs(DREAMSEED_FLAGS) do
if not processedCreatures[creatureID] then
processedCreatures[creatureID] = true;
remainingTime, fullTime = DreamseedUtil:GetGrowthTimesByCreatureID(creatureID);
isActive = remainingTime and remainingTime > 0;
if DreamseedUtil:HasAnyRewardByCreatureID(creatureID) then
if isActive then
flag = 1;
else
flag = 2;
end
else
if isActive then
if remainingTime > 5 then
--We hide the uncontributed plant that is about to despawn
flag = 3;
else
flag = 0;
end
else
flag = 0;
end
end
SetDreamseedFlag(creatureID, flag)
hasReward = flag == 1 or flag == 2;
if isActive then
x, y = GetPlantPosition(creatureID);
distance = DreamseedUtil:GetPlayerDistanceToTarget(playerX, playerY, x, y);
if distance >= WAYPOINT_MIN_DISTANCE then
if not locations then
locations = {};
end
tinsert(locations, {creatureID, x, y, flag, remainingTime, distance});
end
elseif hasReward then
if not locations then
locations = {};
end
x, y = GetPlantPosition(creatureID);
distance = DreamseedUtil:GetPlayerDistanceToTarget(playerX, playerY, x, y);
if distance >= WAYPOINT_MIN_DISTANCE then
if not locations then
locations = {};
end
tinsert(locations, {creatureID, x, y, flag, 0, distance});
end
end
end
end
if locations then
if PRIORITIZE_CHEST then
tsort(locations, SortFunc_RewardFirst);
else
tsort(locations, SortFunc_Generic);
end
end
local bestCreatureID = locations and locations[1] and locations[1][1];
if bestCreatureID ~= FOCUSED_CREATURE or true then
FOCUSED_CREATURE = bestCreatureID;
if bestCreatureID then
local data = locations[1];
flag = data[4];
creatureID = data[1];
local plantName;
if flag == 2 then
plantName = NAME_DREAMSEED_CHEST;
else
plantName = DreamseedUtil:GetPlantNameByCreatureID(data[1]);
if flag == 3 then --haven't contributed
--plantName = plantName.."|TInterface/AddOns/Plumber/Art/MapPin/RedDot:8:8:4:4|t";
elseif flag == 1 then --has reward but still growing
plantName = "|cffcccccc"..plantName.."|r";
end
end
if flag == 0 then
ClearUserWaypoint();
return
end
local hasTimer = flag == 3 or flag == 1;
SuperTrackFrame:SetTimerTarget(plantName, uiMapID, data[2], data[3], FLAG_ICON[flag], hasTimer, data[5]);
else
ClearUserWaypoint();
end
end
end
local function EL_UpdateNow_OnUpdate(self, elapsed)
self.t = self.t + elapsed;
if self.t > WIDGET_UPDATE_INTERVAL then
self.t = 0;
self:SetScript("OnUpdate", nil);
if MODULE_ENABLED then
self:RegisterEvent("VIGNETTES_UPDATED");
self:RegisterEvent("UPDATE_UI_WIDGET");
end
end
end
local function EL_UpdateAfter_OnUpdate(self, elapsed)
self.t = self.t + elapsed;
if self.t > 1 then
self.t = 0;
self:SetScript("OnUpdate", nil);
if MODULE_ENABLED then
UpdateWaypoints();
self:RegisterEvent("VIGNETTES_UPDATED");
self:RegisterEvent("UPDATE_UI_WIDGET");
end
end
end
local function EL_OnEvent(self, event)
if event == "VIGNETTES_UPDATED" then
self.t = 0;
self:SetScript("OnUpdate", EL_UpdateAfter_OnUpdate);
self:UnregisterEvent(event);
elseif event == "UPDATE_UI_WIDGET" then
self.t = 0;
UpdateWaypoints();
self:SetScript("OnUpdate", EL_UpdateNow_OnUpdate);
self:UnregisterEvent(event);
end
end
local function EnableEventListener(state)
if EL then
MODULE_ENABLED = state;
if state then
for creatureID in pairs(DREAMSEED_FLAGS) do
DREAMSEED_FLAGS[creatureID] = 0;
end
EL:RegisterEvent("UPDATE_UI_WIDGET");
EL:RegisterEvent("VIGNETTES_UPDATED");
if not SuperTrackFrame then
SuperTrackFrame = addon.GetSuperTrackFrame();
end
SuperTrackFrame:TryEnableByModule();
else
EL:UnregisterEvent("UPDATE_UI_WIDGET");
EL:UnregisterEvent("VIGNETTES_UPDATED");
EL:SetScript("OnUpdate", nil);
EL.t = 0;
FOCUSED_CREATURE = nil;
if SuperTrackFrame then
SuperTrackFrame:EnableSuperTracking(false);
end
end
end
end
local ZoneTriggerModule;
local function EnableModule(state)
if state then
if not EL then
EL = CreateFrame("Frame");
EL:SetScript("OnEvent", EL_OnEvent);
DREAMSEED_FLAGS = DreamseedUtil:GetPlantCreatureIDs();
CHEST_VIGNETTE_X_CREATURE = DreamseedUtil:GetChestOwnerCreatureIDs();
end
if not ZoneTriggerModule then
local module = API.CreateZoneTriggeredModule("navigator-dreamseed");
ZoneTriggerModule = module;
module:SetValidZones(MAPID_EMRALD_DREAM);
local function OnEnterZoneCallback()
EnableEventListener(true);
end
local function OnLeaveZoneCallback()
EnableEventListener(false);
end
module:SetEnterZoneCallback(OnEnterZoneCallback);
module:SetLeaveZoneCallback(OnLeaveZoneCallback);
end
ZoneTriggerModule:SetEnabled(true);
ZoneTriggerModule:Update();
else
if ZoneTriggerModule then
ZoneTriggerModule:SetEnabled(false);
end
EnableEventListener(false);
end
end
do
local moduleData = {
name = addon.L["ModuleName Navigator_Dreamseed"],
dbKey = "Navigator_Dreamseed", --WorldMapPinSeedPlanting
description = addon.L["ModuleDescription Navigator_Dreamseed"],
toggleFunc = EnableModule,
moduleAddedTime = 1702258000,
categoryID = 10020000,
uiOrder = 4,
};
addon.ControlCenter:AddModule(moduleData);
end