Johnny C. Lam [03-16-13 - 08:04]
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")
--<private-static-properties>
-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
--</private-static-properties>
+--<public-static-properties>
+OvaleEnemies.activeEnemies = 0
+--</public-static-properties>
+
+--<private-static-methods>
+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
+--</private-static-methods>
+
--<public-static-methods>
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
---</public-static-methods>
+function OvaleEnemies:Debug()
+ for guid, timestamp in pairs(enemyLastSeen) do
+ Ovale:Print("enemy " .. guid .. " (" .. tostring(enemyName[guid]) .. ") last seen at " .. timestamp)
+ end
+end
+--</public-static-methods>