Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement rangechecking with IsActionInRange() #38

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 135 additions & 26 deletions LibRangeCheck-3.0/LibRangeCheck-3.0.lua
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ local GetInventoryItemLink = GetInventoryItemLink
local GetTime = GetTime
local HandSlotId = GetInventorySlotInfo("HANDSSLOT")
local math_floor = math.floor
local string_format = string.format
local string_find = string.find
local string_match = string.match
local string_sub = string.sub
local UnitIsVisible = UnitIsVisible

local GetSpellInfo = GetSpellInfo or function(spellID)
Expand Down Expand Up @@ -132,6 +136,7 @@ end

-- << STATIC CONFIG

local MaxActionBar = 120
local UpdateDelay = 0.5
local ItemRequestTimeout = 10.0

Expand Down Expand Up @@ -2093,6 +2098,12 @@ else
-- },
}
end
local FriendItemRanges = {}
for range, items in pairs(FriendItems) do
for i = 1, #items do
FriendItemRanges[items[i]] = range
end
end

local HarmItems
if isEra then
Expand Down Expand Up @@ -3755,6 +3766,68 @@ end

-- >> END OF STATIC CONFIG


local actionsInit
local actionsToUpdate = {}
local FriendActions = {}

local function SetActionItem(action, item)
local cached = Item:CreateFromItemID(item):IsItemDataCached() and C_Item.GetItemInfo(item)
if cached == false then
cached = C_Item.GetItemInfo(item) -- make sure an event is returned when the item data is cached
end
if cached then
local range = FriendItemRanges[item]
if range then
FriendActions[action] = range
end
end
end

local function GetItemFromMacro(macro)
local name, icon, body = GetMacroInfo(macro)
if not body then return end

-- find the first slash command and make sure it's either /use or /cast
local firstCommand = string_find(body, "^[^\n]*/") or string_find(body, "%f[^\n] */")
if firstCommand then
body = string_sub(body, firstCommand)
local item = string_match(body, "^ */use +item: *([0-9]+)") or string_match(body, "^ */cast +item: *([0-9]+)")
if item then
return tonumber(item)
end
end
end

local function UpdateAction(action)
FriendActions[action] = nil
local actionType, id, subType = GetActionInfo(action)
if actionType == "item" then
SetActionItem(action, id)
elseif actionType == "macro" then
local item = GetItemFromMacro(id)
if item then
SetActionItem(action, item)
end
end
end

local function UpdateActions()
for action in pairs(actionsToUpdate) do
UpdateAction(action)
end
wipe(actionsToUpdate)
end

local function UpdateAllActions()
for action = 1, MaxActionBar do
UpdateAction(action)
end
wipe(actionsToUpdate)
actionsInit = true
end


-- temporary stuff

local pendingItemRequest = {}
Expand Down Expand Up @@ -3803,6 +3876,17 @@ local checkers_Interact = setmetatable({}, {
return func
end,
})
local checkers_Action = setmetatable({}, {
__index = function(t, actionSlot)
local func = function(unit)
if IsActionInRange(actionSlot, unit) then
return true
end
end
t[actionSlot] = func
return func
end,
})

-- helper functions
local function copyTable(src, dst)
Expand Down Expand Up @@ -3917,7 +4001,7 @@ local function addChecker(t, range, minRange, checker, info)
tinsert(t, rc)
end

local function createCheckerList(spellList, itemList, interactList)
local function createCheckerList(spellList, actionList, itemList, interactList)
local res, resInCombat = {}, {}
if itemList then
for range, items in pairs(itemList) do
Expand All @@ -3930,6 +4014,16 @@ local function createCheckerList(spellList, itemList, interactList)
end
end
end

if actionList then
local actionRanges = {}
for action, range in pairs(actionList) do
if not actionRanges[range] then
addChecker(resInCombat, range, nil, checkers_Action[action], "action:" .. action)
actionRanges[range] = true
end
end
end

if interactList and not next(res) then
for index, range in pairs(interactList) do
Expand Down Expand Up @@ -4174,19 +4268,19 @@ end
-- friendRC and harmRC will be properly initialized later when we have all the necessary data for them
lib.checkerCache_Spell = lib.checkerCache_Spell or {}
lib.checkerCache_Item = lib.checkerCache_Item or {}
lib.miscRC = createCheckerList(nil, nil, DefaultInteractList)
lib.miscRC = createCheckerList(nil, nil, nil, DefaultInteractList)
lib.miscRCInCombat = {}
lib.friendRC = createCheckerList(nil, nil, DefaultInteractList)
lib.friendRC = createCheckerList(nil, nil, nil, DefaultInteractList)
lib.friendRCInCombat = {}
lib.harmRC = createCheckerList(nil, nil, DefaultInteractList)
lib.harmRC = createCheckerList(nil, nil, nil, DefaultInteractList)
lib.harmRCInCombat = {}
lib.resRC = createCheckerList(nil, nil, DefaultInteractList)
lib.resRC = createCheckerList(nil, nil, nil, DefaultInteractList)
lib.resRCInCombat = {}
lib.petRC = createCheckerList(nil, nil, DefaultInteractList)
lib.petRC = createCheckerList(nil, nil, nil, DefaultInteractList)
lib.petRCInCombat = {}
lib.friendNoItemsRC = createCheckerList(nil, nil, DefaultInteractList)
lib.friendNoItemsRC = createCheckerList(nil, nil, nil, DefaultInteractList)
lib.friendNoItemsRCInCombat = {}
lib.harmNoItemsRC = createCheckerList(nil, nil, DefaultInteractList)
lib.harmNoItemsRC = createCheckerList(nil, nil, nil, DefaultInteractList)
lib.harmNoItemsRCInCombat = {}

lib.failedItemRequests = {}
Expand Down Expand Up @@ -4239,28 +4333,33 @@ function lib:init(forced)
local _, playerClass = UnitClass("player")
local _, playerRace = UnitRace("player")

if actionsInit then
UpdateActions()
else
UpdateAllActions()
end
local interactList = InteractLists[playerRace] or DefaultInteractList
self.handSlotItem = GetInventoryItemLink("player", HandSlotId)
local changed = false
if updateCheckers(self.friendRC, self.friendRCInCombat, createCheckerList(FriendSpells[playerClass], FriendItems, interactList)) then
if updateCheckers(self.friendRC, self.friendRCInCombat, createCheckerList(FriendSpells[playerClass], FriendActions, FriendItems, interactList)) then
changed = true
end
if updateCheckers(self.harmRC, self.harmRCInCombat, createCheckerList(HarmSpells[playerClass], HarmItems, interactList)) then
if updateCheckers(self.harmRC, self.harmRCInCombat, createCheckerList(HarmSpells[playerClass], nil, HarmItems, interactList)) then
changed = true
end
if updateCheckers(self.friendNoItemsRC, self.friendNoItemsRCInCombat, createCheckerList(FriendSpells[playerClass], nil, interactList)) then
if updateCheckers(self.friendNoItemsRC, self.friendNoItemsRCInCombat, createCheckerList(FriendSpells[playerClass], FriendActions, nil, interactList)) then
changed = true
end
if updateCheckers(self.harmNoItemsRC, self.harmNoItemsRCInCombat, createCheckerList(HarmSpells[playerClass], nil, interactList)) then
if updateCheckers(self.harmNoItemsRC, self.harmNoItemsRCInCombat, createCheckerList(HarmSpells[playerClass], nil, nil, interactList)) then
changed = true
end
if updateCheckers(self.miscRC, self.miscRCInCombat, createCheckerList(nil, nil, interactList)) then
if updateCheckers(self.miscRC, self.miscRCInCombat, createCheckerList(nil, nil, nil, interactList)) then
changed = true
end
if updateCheckers(self.resRC, self.resRCInCombat, createCheckerList(ResSpells[playerClass], nil, interactList)) then
if updateCheckers(self.resRC, self.resRCInCombat, createCheckerList(ResSpells[playerClass], nil, nil, interactList)) then
changed = true
end
if updateCheckers(self.petRC, self.petRCInCombat, createCheckerList(PetSpells[playerClass], nil, interactList)) then
if updateCheckers(self.petRC, self.petRCInCombat, createCheckerList(PetSpells[playerClass], nil, nil, interactList)) then
changed = true
end
if changed and self.callbacks then
Expand Down Expand Up @@ -4456,6 +4555,12 @@ function lib:OnEvent(event, ...)
end
end

function lib:ACTIONBAR_SLOT_CHANGED(event, action)
actionsToUpdate[action] = true
self:scheduleInit()
lastUpdate = UpdateDelay
end

function lib:LEARNED_SPELL_IN_TAB()
self:scheduleInit()
end
Expand All @@ -4465,7 +4570,9 @@ function lib:CHARACTER_POINTS_CHANGED()
end

function lib:PLAYER_TALENT_UPDATE()
actionsInit = nil
self:scheduleInit()
lastUpdate = UpdateDelay
end

function lib:SPELLS_CHANGED()
Expand Down Expand Up @@ -4500,6 +4607,12 @@ function lib:GET_ITEM_INFO_RECEIVED(event, item, success)
end
lastUpdate = UpdateDelay
end
if FriendItemRanges[item] and success then
-- recheck all action bars for items with cached data
actionsInit = nil
self:scheduleInit()
lastUpdate = UpdateDelay
end
end

function lib:processItemRequests(itemRequests)
Expand Down Expand Up @@ -4532,9 +4645,6 @@ function lib:processItemRequests(itemRequests)
-- print("### processItemRequests: waiting: " .. tostring(item))
itemRequestTimeoutAt[item] = GetTime() + ItemRequestTimeout
pendingItemRequest[item] = true
if not self.frame:IsEventRegistered("GET_ITEM_INFO_RECEIVED") then
self.frame:RegisterEvent("GET_ITEM_INFO_RECEIVED")
end
return true
elseif GetTime() >= itemRequestTimeoutAt[item] then
-- print("### processItemRequests: timeout: " .. tostring(item))
Expand All @@ -4553,7 +4663,7 @@ function lib:processItemRequests(itemRequests)
end

function lib:initialOnUpdate()
self:init()
self:init(next(actionsToUpdate))
if friendItemRequests then
if self:processItemRequests(friendItemRequests) then
return
Expand All @@ -4575,7 +4685,6 @@ function lib:initialOnUpdate()
cacheAllItems = nil
end
self.frame:Hide()
self.frame:UnregisterEvent("GET_ITEM_INFO_RECEIVED")
end

function lib:scheduleInit()
Expand Down Expand Up @@ -4930,9 +5039,9 @@ function lib:speedTest(numBatches, numIterationsPerBatch)

local minRange, maxRange = self:getRange("target")

print(string.format("SpeedTest: numBatches = %d, numIterationsPerBatch = %d", numBatches, numIterationsPerBatch))
print(string.format(" Range: min = %d, max = %d", minRange, maxRange))
print(string.format(" Time per batch: min = %f, max = %f, total = %f, avg = %f", min, max, total, total / numBatches))
print(string_format("SpeedTest: numBatches = %d, numIterationsPerBatch = %d", numBatches, numIterationsPerBatch))
print(string_format(" Range: min = %d, max = %d", minRange, maxRange))
print(string_format(" Time per batch: min = %f, max = %f, total = %f, avg = %f", min, max, total, total / numBatches))
end

-- >> DEBUG STUFF
Expand All @@ -4945,6 +5054,8 @@ function lib:activate()
local frame = CreateFrame("Frame")
self.frame = frame

frame:RegisterEvent("GET_ITEM_INFO_RECEIVED")
frame:RegisterEvent("ACTIONBAR_SLOT_CHANGED")
frame:RegisterEvent("LEARNED_SPELL_IN_TAB")
frame:RegisterEvent("CHARACTER_POINTS_CHANGED")
frame:RegisterEvent("SPELLS_CHANGED")
Expand All @@ -4953,9 +5064,7 @@ function lib:activate()
frame:RegisterEvent("CVAR_UPDATE")
end

if isRetail or isCata then
frame:RegisterEvent("PLAYER_TALENT_UPDATE")
end
frame:RegisterEvent("PLAYER_TALENT_UPDATE")

local _, playerClass = UnitClass("player")
if playerClass == "MAGE" or playerClass == "SHAMAN" then
Expand Down