From 8a33fb2e8d7bbfcb21802f5ccf99009b6b772dc4 Mon Sep 17 00:00:00 2001 From: "Johnny C. Lam" Date: Sat, 16 Mar 2013 08:04:03 +0000 Subject: [PATCH] Fix OvaleEnemies to track the number of enemies correctly. Before this change, the enemies table was not being updated properly when UNIT_DIED was received. Split out the routines to add and remove enemies into public methods to make the code more DRY. API change: Remove method GetNumberOfEnemies() and introduce a public static variable ``activeEnemies'' that holds the number of active enemies. Schedule a timer to remove enemies that haven't been active for at least 3 seconds. These are either not in combat with your group, out of range, or incapacitated and shouldn't count toward your active enemies. When a unit is no longer an active enemy, throw a new Ovale event ``Ovale_InactiveUnit'' that has the GUID of the dead unit as an event parameter. git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@780 d5049fe3-3747-40f7-a4b5-f36d6801af5f --- OvaleCondition.lua | 2 +- OvaleEnemies.lua | 123 ++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 87 insertions(+), 38 deletions(-) diff --git a/OvaleCondition.lua b/OvaleCondition.lua index 8eabbe8..dcc9195 100644 --- a/OvaleCondition.lua +++ b/OvaleCondition.lua @@ -1195,7 +1195,7 @@ end -- if Enemies(more 4) Spell(fan_of_knives) OvaleCondition.conditions.enemies = function(condition) - return compare(OvaleEnemies:GetNumberOfEnemies(), condition[1], condition[2]) + return compare(OvaleEnemies.activeEnemies, condition[1], condition[2]) end --- Get the current amount of energy for feral druids, non-mistweaver monks, and rogues. diff --git a/OvaleEnemies.lua b/OvaleEnemies.lua index 1d4f5c1..4e60065 100644 --- a/OvaleEnemies.lua +++ b/OvaleEnemies.lua @@ -10,71 +10,120 @@ -- Gather information about ennemies local _, Ovale = ... -local OvaleEnemies = Ovale:NewModule("OvaleEnemies", "AceEvent-3.0") +local OvaleEnemies = Ovale:NewModule("OvaleEnemies", "AceEvent-3.0", "AceTimer-3.0") -- -local bit_band, pairs, select, tostring = bit.band, pairs, select, tostring -local wipe = wipe +local bit_band = bit.band +local pairs = pairs +local select = select +local time = time +local tostring = tostring +local wipe = table.wipe local COMBATLOG_OBJECT_AFFILIATION_OUTSIDER = COMBATLOG_OBJECT_AFFILIATION_OUTSIDER local COMBATLOG_OBJECT_REACTION_HOSTILE = COMBATLOG_OBJECT_REACTION_HOSTILE -numberOfEnemies = 0 -enemies = {} +-- enemyLastSeen[guid] = timestamp +local enemyLastSeen = {} +-- enemyName[guid] = name +local enemyName = {} +-- timer for reaper function to remove inactive enemies +local reaperTimer = nil +local REAP_INTERVAL = 3 -- +-- +OvaleEnemies.activeEnemies = 0 +-- + +-- +function AddEnemy(guid, name, timestamp) + if not guid then return end + local seen = enemyLastSeen[guid] + enemyLastSeen[guid] = timestamp + enemyName[guid] = name + if not seen then + OvaleEnemies.activeEnemies = OvaleEnemies.activeEnemies + 1 + Ovale:DebugPrint("enemy", "New enemy (" .. OvaleEnemies.activeEnemies .. " total): " .. guid .. "(" .. tostring(name) .. ")") + Ovale.refreshNeeded["player"] = true + end +end + +function RemoveEnemy(guid, isDead) + if not guid then return end + local seen = enemyLastSeen[guid] + local name = enemyName[guid] + enemyLastSeen[guid] = nil + if seen then + if OvaleEnemies.activeEnemies > 0 then + OvaleEnemies.activeEnemies = OvaleEnemies.activeEnemies - 1 + end + if isDead then + Ovale:DebugPrint("enemy", "Enemy died (" .. OvaleEnemies.activeEnemies .. " total): " .. guid .. " (" .. tostring(name) .. ")") + else + Ovale:DebugPrint("enemy", "Enemy removed: (" .. OvaleEnemies.activeEnemies .. " total): " .. guid .. " (" .. tostring(name) .. "), last seen at " .. seen) + end + OvaleEnemies:SendMessage("Ovale_InactiveUnit", guid) + Ovale.refreshNeeded["player"] = true + end +end +-- + -- function OvaleEnemies:OnEnable() + if not reaperTimer then + reaperTimer = self:ScheduleRepeatingTimer("RemoveInactiveEnemies", REAP_INTERVAL) + end self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") self:RegisterEvent("PLAYER_REGEN_DISABLED") end function OvaleEnemies:OnDisable() + if not reaperTimer then + self:CancelTimer(reaperTimer) + reaperTimer = nil + end self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED") self:UnregisterEvent("PLAYER_REGEN_DISABLED") end function OvaleEnemies:COMBAT_LOG_EVENT_UNFILTERED(event, ...) - local time, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags = select(1, ...) + local timestamp, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags = select(1, ...) if event == "UNIT_DIED" then - for k,v in pairs(enemies) do - if k==destGUID then - enemies[v] = nil - numberOfEnemies = numberOfEnemies - 1 - Ovale.refreshNeeded["player"] = true - Ovale:DebugPrint("enemy", "enemy die") - end - end - elseif sourceFlags and not enemies[sourceGUID] and bit_band(sourceFlags, COMBATLOG_OBJECT_REACTION_HOSTILE)>0 - and bit_band(sourceFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) > 0 and - destFlags and bit_band(destFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) == 0 then - enemies[sourceGUID] = true - Ovale:DebugPrint("enemy", "new enemy source=" .. tostring(sourceName)) - numberOfEnemies = numberOfEnemies + 1 - Ovale.refreshNeeded["player"] = true - elseif destGUID and not enemies[destGUID] and bit_band(destFlags, COMBATLOG_OBJECT_REACTION_HOSTILE)>0 - and bit_band(destFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) > 0 and - sourceFlags and bit_band(sourceFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) == 0 then - enemies[destGUID] = true - Ovale:DebugPrint("enemy", "new enemy dest=".. tostring(destName)) - numberOfEnemies = numberOfEnemies + 1 - Ovale.refreshNeeded["player"] = true + RemoveEnemy(destGUID, true) + elseif sourceFlags and bit_band(sourceFlags, COMBATLOG_OBJECT_REACTION_HOSTILE) > 0 + and bit_band(sourceFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) > 0 + and destFlags and bit_band(destFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) == 0 then + AddEnemy(sourceGUID, sourceName, Ovale.now) + elseif destGUID and bit_band(destFlags, COMBATLOG_OBJECT_REACTION_HOSTILE) > 0 + and bit_band(destFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) > 0 + and sourceFlags and bit_band(sourceFlags, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) == 0 then + AddEnemy(destGUID, destName, Ovale.now) end end function OvaleEnemies:PLAYER_REGEN_DISABLED() - if numberOfEnemies then - numberOfEnemies = 0 - wipe(enemies) - end + -- Reset enemy tracking when combat starts. + wipe(enemyLastSeen) + wipe(enemyName) + self.activeEnemies = 0 end -function OvaleEnemies:GetNumberOfEnemies() - if not numberOfEnemies then - numberOfEnemies = 0 +-- Remove enemies that have been inactive for at least REAP_INTERVAL seconds. +-- These enemies are not in combat with your group, out of range, or +-- incapacitated and shouldn't count toward the number of active enemies. +function OvaleEnemies:RemoveInactiveEnemies() + for guid, timestamp in pairs(enemyLastSeen) do + if Ovale.now - timestamp > REAP_INTERVAL then + RemoveEnemy(guid) + end end - return numberOfEnemies end --- +function OvaleEnemies:Debug() + for guid, timestamp in pairs(enemyLastSeen) do + Ovale:Print("enemy " .. guid .. " (" .. tostring(enemyName[guid]) .. ") last seen at " .. timestamp) + end +end +-- -- 1.7.9.5