From 9ff647c57932839d4c4615a001fb1eab3e7a4374 Mon Sep 17 00:00:00 2001 From: Lyle Douglass Date: Sun, 17 Mar 2024 13:15:04 -0400 Subject: [PATCH] fix: macro not updating This fix changes the logic on how the macro is found and generated. Previously, the code would try to find the macro based off a macro index and try and do a string.find on RHT.b. Seeing RHT.b is a defunct part of the macro, I changed this to use GetMacroIndexByName as the macro name is always 'RHT'. This allows us to set the index in a much cleaner fashion. Lastly, I removed the last line of SetRandomHearthToy that was setting the RHT.b button which did not exist. This has been extensively tested and the bug is now resolved --- HearthstoneRandomizer.lua | 221 ++++++++++++++++---------------------- 1 file changed, 91 insertions(+), 130 deletions(-) diff --git a/HearthstoneRandomizer.lua b/HearthstoneRandomizer.lua index 536b5db..64ff2e7 100644 --- a/HearthstoneRandomizer.lua +++ b/HearthstoneRandomizer.lua @@ -8,54 +8,44 @@ local RHTInitialized = false --Frame to catch events local frame = CreateFrame("Frame") --- Setting up an invisible button named RHTB. Toys can only be used through a button click, so we need one for the macro to click. -RHT.b = CreateFrame("Button","RHTB",nil,"SecureActionButtonTemplate") -RHT.b:RegisterForClicks("AnyUp","AnyDown") -RHT.b:SetAttribute("type","item") -- Setting up a frame to wait and see if the toybox is loaded before getting stones on login. local timeOut = 10 --Delay for checking stones. RHT.to = CreateFrame("Frame","RHTO", UIParent) RHT.to:SetScript("OnUpdate", function (self, elapse) - if timeOut > 0 then - timeOut = timeOut - elapse - else - if C_ToyBox.GetNumToys() > 0 then - GetLearnedStones() - if RHTInitialized then - SetRandomHearthToy() - print "HearthstoneRandomizer initialized" - RHT.to:SetScript("OnUpdate", nil) - else - timeOut = 1 - end - else - timeOut = 1 - end - end + if timeOut > 0 then + timeOut = timeOut - elapse + else + if C_ToyBox.GetNumToys() > 0 then + GetLearnedStones() + if RHTInitialized then + SetRandomHearthToy() + -- Debug output + -- print "HearthstoneRandomizer initialized" + RHT.to:SetScript("OnUpdate", nil) + else + timeOut = 1 + end + else + timeOut = 1 + end + end end) frame:RegisterEvent("PLAYER_ENTERING_WORLD") --- Blizz broke deleting items from bags, leaving code incase I find a fix. Yeah. Right. ---frame:RegisterEvent("BAG_UPDATE") - -- Spellcast stopping is the check for if a hearthstone has been used. frame:RegisterEvent("UNIT_SPELLCAST_STOP") local function Event(self, event, arg1, arg2, arg3) - if event == "PLAYER_ENTERING_WORLD" then - GetMacroIndex() - frame:UnregisterEvent("PLAYER_ENTERING_WORLD") - end - -- When a spell cast stops and it's the player's spell, send the ID to check if it's a stone. - if event == "UNIT_SPELLCAST_STOP" and arg1 == "player" then - SpellcastUpdate(arg3) - end - -- Currently not used. Thx Blizz. - if event == "BAG_UPDATE" then - DeleteHearthstone() - end + if event == "PLAYER_ENTERING_WORLD" then + GetMacro() + frame:UnregisterEvent("PLAYER_ENTERING_WORLD") + end + -- When a spell cast stops and it's the player's spell, send the ID to check if it's a stone. + if event == "UNIT_SPELLCAST_STOP" and arg1 == "player" then + SpellcastUpdate(arg3) + end end frame:SetScript("OnEvent", Event) @@ -93,121 +83,92 @@ AllHearthToyIndex[212337] = 431644 --Stone of the Hearth -- This is the meat right here. function SetRandomHearthToy() - -- Setting the new stone while in combat is bad. - --if not InCombatLockdown() then - -- Find the macro. - CheckMacroIndex() - -- Rebuild the stone list if it's empty. - if next(UsableHearthToyIndex) == nil then - GetLearnedStones() - end - local itemID, toyName = '' - -- Randomly pick one. - local k = RandomKey(UsableHearthToyIndex) - local itemID, toyName = C_ToyBox.GetToyInfo(k) - if toyName then - -- Remove it from the list so we don't pick it again. - RemoveStone(k) - -- Write the macro. - GenMacro(itemID, toyName) - -- Set button for first use - if not RHT.b:GetAttribute("item") then RHT.b:SetAttribute("item",toyName) end - end - --end + -- Find the macro. + GetMacro() + -- Rebuild the stone list if it's empty. + if next(UsableHearthToyIndex) == nil then + GetLearnedStones() + end + local itemID, toyName = '' + -- Randomly pick one. + local k = RandomKey(UsableHearthToyIndex) + local itemID, toyName = C_ToyBox.GetToyInfo(k) + if toyName then + -- Remove it from the list so we don't pick it again. + RemoveStone(k) + -- Write the macro. + GenMacro(itemID, toyName) + end end -- Get stones learned and usable by character function GetLearnedStones() - -- Get the current setting for the toybox so we can set it back after we're done. - ToyCollSetting = C_ToyBox.GetCollectedShown() - ToyUnCollSetting = C_ToyBox.GetUncollectedShown() - ToyUsableSetting = C_ToyBox.GetUnusableShown() - - C_ToyBox.SetCollectedShown(true) -- List collected toys - C_ToyBox.SetUncollectedShown(false) -- Don't list uncollected toys - C_ToyBox.SetUnusableShown(false) -- Don't list unusable toys in the the collection. - - -- Go through all the toys to find the usable stons. - for i = 1, C_ToyBox.GetNumFilteredToys() do - -- Go through all the stone to see if this toy is a stone. - for k in pairs(AllHearthToyIndex) do - if k == C_ToyBox.GetToyFromIndex(i) then - UsableHearthToyIndex [k] = 1 - end - end - end - -- Reset the toybox filter - C_ToyBox.SetCollectedShown(ToyCollSetting) - C_ToyBox.SetUncollectedShown(ToyUnCollSetting) - C_ToyBox.SetUnusableShown(ToyUsableSetting) - if next(UsableHearthToyIndex) then - RHTInitialized = true - end -end - --- We've removed the name from the macro, so now we need to find it so we know which one to edit. -function GetMacroIndex() - local numg, numc = GetNumMacros() - for i = 1, numg do - local macroCont = GetMacroBody(i) - -- Hopefully no other macro ever made has "RHT.b" in it... - if string.find(macroCont, "RHT.b") then - RHTIndex = i - end - end + -- Get the current setting for the toybox so we can set it back after we're done. + ToyCollSetting = C_ToyBox.GetCollectedShown() + ToyUnCollSetting = C_ToyBox.GetUncollectedShown() + ToyUsableSetting = C_ToyBox.GetUnusableShown() + + C_ToyBox.SetCollectedShown(true) -- List collected toys + C_ToyBox.SetUncollectedShown(false) -- Don't list uncollected toys + C_ToyBox.SetUnusableShown(false) -- Don't list unusable toys in the the collection. + + -- Go through all the toys to find the usable stons. + for i = 1, C_ToyBox.GetNumFilteredToys() do + -- Go through all the stone to see if this toy is a stone. + for k in pairs(AllHearthToyIndex) do + if k == C_ToyBox.GetToyFromIndex(i) then + UsableHearthToyIndex [k] = 1 + end + end + end + -- Reset the toybox filter + C_ToyBox.SetCollectedShown(ToyCollSetting) + C_ToyBox.SetUncollectedShown(ToyUnCollSetting) + C_ToyBox.SetUnusableShown(ToyUsableSetting) + if next(UsableHearthToyIndex) then + RHTInitialized = true + end end --- Have we found the macro yet? Also, make sure the macro we're editing is the right one in case the user rearranged things or deleted it. If not, go find it. -function CheckMacroIndex() - local macroCont = GetMacroBody(RHTIndex) - if macroCont then - if string.find(macroCont, "RHT.b") then - return - end - end - GetMacroIndex() +-- We use RHT as the macro name, so we need to see if it exists. If it +-- does, we set the index. Else, it the nothing gets passed to GenMacro +-- and it creates a new one. +function GetMacro() + macroExists = GetMacroIndexByName("RHT") + if macroExists then + RHTIndex = macroExists + end end -- Macro writing time. function GenMacro(itemID, toyName) - -- Did we find the index? If so, edit that. The macro changes the button to the next stone, but only if we aren't in combat; can't SetAttribute. It then casts the toyName - if RHTIndex then - EditMacro(RHTIndex, "RHT", "INV_MISC_QUESTIONMARK", "#showtooltip item:" .. itemID .. "\r/run if not InCombatLockdown() then RHT.b:SetAttribute(\"item\",\"" .. toyName .. "\") end\r/cast " .. toyName) - else - -- No macro found, make a new one, get it's ID - CreateMacro("RHT", "INV_MISC_QUESTIONMARK", "#showtooltip item:" .. itemID .. "\r/run if not InCombatLockdown() then RHT.b:SetAttribute(\"item\",\"" .. toyName .. "\") end\r/cast " .. toyName) - GetMacroIndex() - end + if RHTIndex then + EditMacro(RHTIndex, "RHT", "INV_MISC_QUESTIONMARK", "#showtooltip item:" .. itemID .. "\r/cast " .. toyName) + -- Debug output + -- print "Macro updated" + else + CreateMacro("RHT", "INV_MISC_QUESTIONMARK", "#showtooltip item:" .. itemID .. "\r/cast " .. toyName) + -- Debug output + -- print "Macro created" + GetMacro() + end end -- Remove stone from the list so we don't use it again. (Here for debugging) function RemoveStone(k) - UsableHearthToyIndex[k] = nil + UsableHearthToyIndex[k] = nil end -- Did a stone get used? function SpellcastUpdate(spellID) if not InCombatLockdown() then - for k in pairs(AllHearthToyIndex) do - if spellID == AllHearthToyIndex[k] then - SetRandomHearthToy() - break - end - end -end + for k in pairs(AllHearthToyIndex) do + if spellID == AllHearthToyIndex[k] then + SetRandomHearthToy() + break + end + end end - --- Old function to delete the base HS from bags. Leaving in case I can find a workaround from Blizz's change. -function DeleteHearthstone() - for bag = 0,4 do - for slot = 1, 32 do - local itemID = GetContainerItemID(bag,slot) - if itemID == 6948 then - PickupContainerItem(bag,slot) - DeleteCursorItem() - end - end - end end -- Code to randomly pick a key from a table.