Quantcast

Preserve auras applied by already-cast instant-cast spells between updates.

Johnny C. Lam [05-03-14 - 00:25]
Preserve auras applied by already-cast instant-cast spells between updates.

This fixes the problem where an instant-cast spell cast in the simulator
applies a debuff on the target which is added to the state machine, then
instantly removed before being added to the true aura database.  For
example, a subtlety rogue's Hemorrhage applies a DoT on the target, but
there is a small lag betwen the spell hitting the target and the DoT being
applied.  When the user casts the spell, OvaleFuture queues it up to the
cast in the simulator, which applies a DoT to the target in the simulator.
However, the simulator's state is reset on every update, so the debuff was
being lost until it appeared on the actual target.  During that brief lag,
Ovale thinks Hemorrhage still needs to be cast to apply the DoT.

Instead of dumping the entire state aura database for each update, just
remove state auras that are older than the corresponding auras in the true
aura database.  This preserves debuffs applied in the simulator that are
the result of instant-cast spells until they appear in the true aura
database.

git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@1354 d5049fe3-3747-40f7-a4b5-f36d6801af5f
Filename
OvaleAura.lua
diff --git a/OvaleAura.lua b/OvaleAura.lua
index 5788381..ac77f69 100644
--- a/OvaleAura.lua
+++ b/OvaleAura.lua
@@ -199,6 +199,7 @@ local function RemoveAurasOnGUID(auraDB, guid)
 		for auraId, whoseTable in pairs(auraTable) do
 			for casterGUID, aura in pairs(whoseTable) do
 				self_pool:Release(aura)
+				whoseTable[casterGUID] = nil
 			end
 			self_pool:Release(whoseTable)
 			auraTable[auraId] = nil
@@ -418,6 +419,7 @@ function OvaleAura:GainedAuraOnGUID(guid, atTime, auraId, casterGUID, filter, vi
 			aura.start = atTime
 		end
 		aura.gain = atTime
+		aura.lastUpdated = atTime
 		aura.stacks = count
 		aura.consumed = nil
 		aura.filter = filter
@@ -506,6 +508,7 @@ function OvaleAura:LostAuraOnGUID(guid, atTime, auraId, casterGUID)
 			end
 		end
 	end
+	aura.lastUpdated = atTime

 	self:SendMessage("Ovale_AuraRemoved", atTime, guid, auraId, aura.source)
 	local unitId = OvaleGUID:GetUnitId(guid)
@@ -632,11 +635,32 @@ end

 -- Reset the state to the current conditions.
 function OvaleAura:ResetState(state)
-	-- Garbage-collect auras in the state machine.
-	if not Ovale.enCombat then
-		self:CleanState(state)
-	end
+	-- Advance age of auras in state machine.
 	state.serial = state.serial + 1
+
+	-- Garbage-collect auras in the state machine that are more recently updated in the true aura database.
+	for guid, auraTable in pairs(state.aura) do
+		for auraId, whoseTable in pairs(auraTable) do
+			for casterGUID, aura in pairs(whoseTable) do
+				local auraFound = GetAura(self.aura, guid, auraId, casterGUID)
+				if auraFound and aura.lastUpdated <= auraFound.lastUpdated then
+					self_pool:Release(aura)
+					whoseTable[casterGUID] = nil
+				else
+					-- Reset the aura age relative to the state of the simulator.
+					aura.serial = state.serial
+				end
+			end
+			if not next(whoseTable) then
+				self_pool:Release(whoseTable)
+				auraTable[auraId] = nil
+			end
+		end
+		if not next(auraTable) then
+			self_pool:Release(auraTable)
+			state.aura[guid] = nil
+		end
+	end
 end

 -- Release state resources prior to removing from the simulator.
@@ -1031,6 +1055,7 @@ statePrototype.AddAuraToGUID = function(state, guid, auraId, casterGUID, filter,
 	local aura = self_pool:Get()
 	aura.state = true
 	aura.serial = state.serial
+	aura.lastUpdated = state.currentTime
 	aura.filter = filter
 	aura.mine = mine
 	aura.start = start or 0
@@ -1069,6 +1094,7 @@ statePrototype.RemoveAuraOnGUID = function(state, guid, auraId, filter, mine, at
 		-- Expire the aura.
 		aura.stacks = 0
 		aura.ending = atTime
+		aura.lastUpdated = atTime
 	end
 end