Quantcast

use spellId instead of spellName

Sidoine De Wispelaere [10-16-10 - 15:26]
use spellId instead of spellName
warlock: various improvements


git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@276 d5049fe3-3747-40f7-a4b5-f36d6801af5f
Filename
Condition.lua
Ovale.lua
Ovale.toc
OvaleCompile.lua
OvaleFrame.lua
OvaleIcone.lua
defaut/Chasseur.lua
defaut/Demoniste.lua
defaut/Druide.lua
defaut/Paladin.lua
diff --git a/Condition.lua b/Condition.lua
index 44cc282..3de21f7 100644
--- a/Condition.lua
+++ b/Condition.lua
@@ -114,7 +114,7 @@ local function buildRootSpellList()
 	end
 	rootSpellList = {}
 	for k, v in pairs(rootSpellIdList) do
-		rootSpellList[Ovale:GetSpellInfoOrNil(v)] = true
+		rootSpellList[v] = true
 	end
 end

@@ -124,7 +124,7 @@ local function buildStunSpellList()
 	end
 	stunSpellList = {}
 	for k, v in pairs(stunSpellIdList) do
-		stunListList[Ovale:GetSpellInfoOrNil(v)] = true
+		stunListList[v] = true
 	end
 end

@@ -134,7 +134,7 @@ local function buildIncapacitateSpellList()
 	end
 	incapacitateSpellList = {}
 	for k, v in pairs(incapacitateSpellIdList) do
-		incapacitateSpellList[Ovale:GetSpellInfoOrNil(v)] = true
+		incapacitateSpellList[v] = true
 	end
 end

@@ -144,18 +144,18 @@ local function buildFearSpellList()
 	end
 	fearSpellList = {}
 	for k, v in pairs(fearSpellIdList) do
-		fearSpellList[Ovale:GetSpellInfoOrNil(v)] = true
+		fearSpellList[v] = true
 	end
 end

 local function isDebuffInList(list)
 	local i=1;
 	while (true) do
-		local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable =  UnitDebuff("player", i);
+		local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellId =  UnitDebuff("player", i);
 		if (not name) then
 			break
 		end
-		if (list[name]) then
+		if (list[spellId]) then
 			return true
 		end
 		i = i +1
@@ -232,6 +232,17 @@ local function addTime(time1, duration)
 	end
 end

+--Return time2-time1
+local function diffTime(time1, time2)
+	if not time1 then
+		return 0
+	end
+	if not time2 then
+		return nil
+	end
+	return time2 - time1
+end
+
 local function addOrSubTime(time1, operator, duration)
 	if operator == "more" then
 		return addTime(time1, -duration)
@@ -261,13 +272,13 @@ local function GetManaTime(mana, withBerserker)
 		end
 		local rate= 10
 		if (className == "ROGUE") then
-			local rush = Ovale:GetSpellInfoOrNil(13750)
-			if UnitBuff("player", rush) then
+			local rush = Ovale:GetAura("player", "HELPFUL", 13750)
+			if rush.stacks>0 then
 				rate = rate * 2
 			end
 		elseif withBerserker then
-			local berserk = Ovale:GetSpellInfoOrNil(50334)
-			if UnitBuff("player", berserk) then
+			local berserk = Ovale:GetAura("player", "HELPFUL", 50334)
+			if berserk.stacks>0 then
 				mana = mana/2
 			end
 		end
@@ -320,8 +331,8 @@ local function GetTargetAura(condition, filter, target)
 	if (not condition.mine or aura.mine) and aura.stacks>=stacks then
 		local ending
 		if condition.forceduration then
-			if Ovale.spellInfo[name] and Ovale.spellInfo[name].duration then
-				ending = aura.start + Ovale.spellInfo[name].duration
+			if Ovale.spellInfo[spellId] and Ovale.spellInfo[spellId].duration then
+				ending = aura.start + Ovale.spellInfo[spellId].duration
 			else
 				ending = aura.start + condition.forceduration
 			end
@@ -334,48 +345,6 @@ local function GetTargetAura(condition, filter, target)
 	end
 end

---[[	local auraName, auraRank, auraIcon = Ovale:GetSpellInfoOrNil(spellId)
-	local i=1;
-	local startTime = nil
-	local endTime = nil
-	local stacksLeft = nil
-	while (true) do
-		local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable =  UnitAura(target, i, filter);
-		if (not name) then
-			break
-		end
-		if (not condition.mine or unitCaster=="player") then
-			if (name == auraName and icon == auraIcon) then
-				startTime = expirationTime - duration
-				endTime = expirationTime - Ovale.maintenant
-				stacksLeft = count
-				break
-			end
-		end
-		i = i + 1;
-	end
-
-	if spellId then
-		for k=1,Ovale.spellStack.length do
-			local newSpell = Ovale.spellStack[k]
-			if (newSpell.info and newSpell.info[target] and newSpell.info[target][filter] and newSpell.info[target][filter][spellId]) then
-				local duration = newSpell.info[target][filter][spellId]
-				if duration>0 then
-					if (not endTime or endTime < newSpell.attenteFinCast) then
-						stacksLeft = 1
-					else
-						stacksLeft = stacksLeft + 1
-					end
-					endTime = duration + newSpell.attenteFinCast
-				else
-					endTime = nil
-				end
-			end
-		end
-	end
-	return endTime, stacksLeft
-end]]
-
 local lastSaved
 local savedHealth
 local targetGUID
@@ -435,11 +404,12 @@ Ovale.conditions=
 		return compare(nombre, condition[2], condition[3])
 	end,
 	BuffDuration = function(condition)
-		local name, rank, icon, count, debuffType, duration = UnitBuff("player", Ovale:GetSpellInfoOrNil(condition[1]))
-		if not name then
-			return nil
-		end
-		return compare(duration, condition[2], condition[3])
+		--local name, rank, icon, count, debuffType, duration = UnitBuff("player", Ovale:GetSpellInfoOrNil(condition[1]))
+		--if not name then
+--			return nil
+	--	end
+		local start, ending = GetTargetAura(condition, "HELPFUL", "player")
+		return compare(diffTime(start, ending), condition[2], condition[3])
 	end,
 	-- Test if a buff will expire on the player after a given time
 	-- 1 : buff spell id
@@ -448,8 +418,8 @@ Ovale.conditions=
 		local start, ending = GetTargetAura(condition, "HELPFUL", "player")
 		local timeBefore = avecHate(condition[2], condition.haste)
 		if Ovale.trace then
-			Ovale:Print("timeBefore = " .. timeBefore)
-			Ovale:Print("start = " .. ending)
+			Ovale:Print("timeBefore = " .. nilstring(timeBefore))
+			Ovale:Print("start = " .. nilstring(ending))
 		end
 		return addTime(ending, -timeBefore)
 	end,
@@ -457,13 +427,13 @@ Ovale.conditions=
 	-- 1 : buff spell id
 	-- 2 : time since the buff gain
 	BuffGain = function(condition)
-		local spell, rank, icon = Ovale:GetSpellInfoOrNil(condition[1])
+		local spellId = condition[1]
 		if (spell) then
-			if (not Ovale.buff[spell]) then
+			if (not Ovale.buff[spellId]) then
 				return 0
 			end
-			local timeGain = Ovale.buff[spell].gain
-			if (not timeGain or Ovale.buff[spell].icon~=icon) then
+			local timeGain = Ovale.buff[spellId].gain
+			if not timeGain then
 				timeGain = 0
 			end

@@ -480,12 +450,8 @@ Ovale.conditions=
 		return start, addTime(ending, -timeBefore)
 	end,
 	Casting = function(condition)
-		local spell, rank, name, icon, start, ending = UnitCastingInfo("player")
-		if (not spell) then
-			return nil
-		end
-		if Ovale:GetSpellInfoOrNil(condition[1])==spell then
-			return start/1000, ending/1000
+		if Ovale.currentSpellId == condition[1] then
+			return Ovale.startCast, Ovale.endCast
 		else
 			return nil
 		end
@@ -551,7 +517,7 @@ Ovale.conditions=
 	end,
 	EndCastTime = function(condition)
 		local name, rank, icon, cost, isFunnel, powerType, castTime = Ovale:GetSpellInfoOrNil(condition[1])
-		local actionCooldownStart, actionCooldownDuration, actionEnable = Ovale:GetComputedSpellCD(name)
+		local actionCooldownStart, actionCooldownDuration, actionEnable = Ovale:GetComputedSpellCD(condition[1])
 		local startCast = actionCooldownStart + actionCooldownDuration
 		if startCast<Ovale.currentTime then
 			startCast = Ovale.currentTime
@@ -645,7 +611,7 @@ Ovale.conditions=
 	end,
 	OtherDebuffExpires = function(condition)
 		Ovale:EnableOtherDebuffs()
-		local otherDebuff = Ovale.otherDebuffs[GetSpellInfo(condition[1])]
+		local otherDebuff = Ovale.otherDebuffs[condition[1]]
 		if otherDebuff then
 			local timeBefore = condition[2] or 0
 			local maxTime = condition[3] or 10
@@ -669,7 +635,7 @@ Ovale.conditions=
 	end,
 	OtherDebuffPresent = function(condition)
 		Ovale:EnableOtherDebuffs()
-		local otherDebuff = Ovale.otherDebuffs[GetSpellInfo(condition[1])]
+		local otherDebuff = Ovale.otherDebuffs[condition[1]]
 		if otherDebuff then
 		--	print("otherDebuff")
 			local maxTime = 0
@@ -829,7 +795,7 @@ Ovale.conditions=
 		return start, addTime(ending, -tempsMin)
 	end,
 	TargetInRange = function(condition)
-		return testbool(IsSpellInRange(Ovale:GetSpellInfoOrNil(condition[1]),getTarget(condition.target))==1,condition[2])
+		return testbool(IsSpellInRange(condition[1],getTarget(condition.target))==1,condition[2])
 	end,
 	TargetIsCasting = function(condition)
 		return testbool(UnitCastingInfo(getTarget(condition.target)), condition[1])
diff --git a/Ovale.lua b/Ovale.lua
index a5f10c5..039ea0f 100644
--- a/Ovale.lua
+++ b/Ovale.lua
@@ -41,7 +41,7 @@ Ovale.meleeHaste = 0
 Ovale.aura = { player = {}, target = {}}
 --allow to track the current target
 Ovale.targetGUID = nil
---spell info from the current script
+--spell info from the current script (by spellId)
 Ovale.spellInfo = {}
 --track when a buff was applied (used for the old eclipse mechanism, maybe this could be removed?)
 Ovale.buff = {}
@@ -372,11 +372,11 @@ function Ovale:OnInitialize()
 	self.AceConfigDialog = LibStub("AceConfigDialog-3.0");
 end

-function Ovale:GetOtherDebuffs(spellName)
-	if not self.otherDebuffs[spellName] then
-		self.otherDebuffs[spellName] = {}
+function Ovale:GetOtherDebuffs(spellId)
+	if not self.otherDebuffs[spellId] then
+		self.otherDebuffs[spellId] = {}
 	end
-	return self.otherDebuffs[spellName]
+	return self.otherDebuffs[spellId]
 end

 function Ovale:WithHaste(temps, hate)
@@ -411,14 +411,14 @@ function Ovale:HandleProfileChanges()
 end

 function Ovale:ChercherNomsBuffs()
-	self.MOONKIN_AURA = self:GetSpellInfoOrNil(24907)
-	self.RETRIBUTION_AURA = self:GetSpellInfoOrNil(7294)
-	self.WRATH_OF_AIR_TOTEM = self:GetSpellInfoOrNil(3738)
-	self.WINDFURY_TOTEM = self:GetSpellInfoOrNil(8512)
-	self.ICY_TALONS = self:GetSpellInfoOrNil(50880)
-	self.BLOODLUST = self:GetSpellInfoOrNil(2825)
-	self.HEROISM = self:GetSpellInfoOrNil(32182)
-	self.JUDGMENT_OF_THE_PURE = self:GetSpellInfoOrNil(54153)
+	self.MOONKIN_AURA = 24907
+	self.RETRIBUTION_AURA = 7294
+	self.WRATH_OF_AIR_TOTEM = 3738
+	self.WINDFURY_TOTEM = 8512
+	self.ICY_TALONS = 50880
+	self.BLOODLUST = 2825
+	self.HEROISM = 32182
+	self.JUDGMENT_OF_THE_PURE = 54153
 end

 function Ovale:FirstInit()
@@ -479,8 +479,11 @@ function Ovale:OnEnable()
     self:RegisterEvent("UPDATE_BINDINGS");
     self:RegisterEvent("UNIT_AURA");
     self:RegisterEvent("ACTIONBAR_PAGE_CHANGED")
-    self:RegisterEvent("UNIT_SPELLCAST_SENT")
-	self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
+    self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
+	self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
+	self:RegisterEvent("UNIT_SPELLCAST_START")
+	self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START")
+	self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP")
     self:RegisterEvent("PLAYER_TARGET_CHANGED")
 	self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
 	self:RegisterEvent("CHAT_MSG_ADDON")
@@ -506,7 +509,10 @@ function Ovale:OnDisable()
     self:UnregisterEvent("CHARACTER_POINTS_CHANGED")
     self:UnregisterEvent("UPDATE_BINDINGS")
     self:UnregisterEvent("UNIT_AURA")
-    self:UnregisterEvent("UNIT_SPELLCAST_SENT")
+    self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_START")
+	self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_STOP")
+    self:UnregisterEvent("UNIT_SPELLCAST_SUCCEEDED")
+	self:UnregisterEvent("UNIT_SPELLCAST_START")
     self:UnregisterEvent("PLAYER_TARGET_CHANGED")
     self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
     self:UnregisterEvent("CHAT_MSG_ADDON")
@@ -562,9 +568,11 @@ function Ovale:COMBAT_LOG_EVENT_UNFILTERED(event, ...)
 				or string.find(event, "SPELL_CAST_FAILED") == 1 then
 			local spellId, spellName = select(9, ...)
 			for i,v in ipairs(self.lastSpell) do
-				if v.name == spellName then
-					table.remove(self.lastSpell, i)
-					--self:Print("on supprime "..spellName.." a "..GetTime())
+				if v.spellId == spellId then
+					if not v.channeled then
+						table.remove(self.lastSpell, i)
+					end
+					--self:Print("on supprime "..spellId.." a "..GetTime())
 					--self:Print(UnitDebuff("target", "Etreinte de l'ombre"))
 					break
 				end
@@ -574,10 +582,10 @@ function Ovale:COMBAT_LOG_EVENT_UNFILTERED(event, ...)
 			--Track debuffs on units that are not the current target
 			if string.find(event, "SPELL_AURA_") == 1 then
 				local spellId, spellName, spellSchool, auraType = select(9, ...)
-				if auraType == "DEBUFF" and self.spellInfo[spellName] and self.spellInfo[spellName].duration then
-					local otherDebuff = self:GetOtherDebuffs(spellName)
+				if auraType == "DEBUFF" and self.spellInfo[spellId] and self.spellInfo[spellId].duration then
+					local otherDebuff = self:GetOtherDebuffs(spellId)
 					if event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_REFRESH" then
-						otherDebuff[destGUID] = Ovale.maintenant + self:WithHaste(self.spellInfo[spellName].duration, self.spellInfo[spellName].durationhaste)
+						otherDebuff[destGUID] = Ovale.maintenant + self:WithHaste(self.spellInfo[spellId].duration, self.spellInfo[spellId].durationhaste)
 					--	self:Print("ajout de "..spellName.." à "..destGUID)
 					elseif event == "SPELL_AURA_REMOVED" then
 						otherDebuff[destGUID] = nil
@@ -625,37 +633,37 @@ function Ovale:UNIT_AURA(event, unit)
 		local i=1;

 		while (true) do
-			local name, rank, iconTexture, count, debuffType, duration, expirationTime, source =  UnitBuff("player", i);
+			local name, rank, iconTexture, count, debuffType, duration, expirationTime, source, stealable, consolidate, spellId =  UnitBuff("player", i);
 			if (not name) then
 				break
 			end
-			if (not self.buff[name]) then
-				self.buff[name] = {}
+			if (not self.buff[spellId]) then
+				self.buff[spellId] = {}
 			end
-			self.buff[name].icon = iconTexture
-			self.buff[name].count = count
-			self.buff[name].duration = duration
-			self.buff[name].expirationTime = expirationTime
-			self.buff[name].source = source
-			if (not self.buff[name].present) then
-				self.buff[name].gain = Ovale.maintenant
+			self.buff[spellId].icon = iconTexture
+			self.buff[spellId].count = count
+			self.buff[spellId].duration = duration
+			self.buff[spellId].expirationTime = expirationTime
+			self.buff[spellId].source = source
+			if (not self.buff[spellId].present) then
+				self.buff[spellId].gain = Ovale.maintenant
 			end
-			self.buff[name].lastSeen = Ovale.maintenant
-			self.buff[name].present = true
+			self.buff[spellId].lastSeen = Ovale.maintenant
+			self.buff[spellId].present = true

 			--TODO: need to be updated to 4.0.0, altought I doubt computing haste is necessary
 			--because there is no longer any risk to clip DOTs
-			if (name == self.RETRIBUTION_AURA or name == self.MOONKIN_AURA) then
+			if (spellId == self.RETRIBUTION_AURA or spellId == self.MOONKIN_AURA) then
 				hateCommune = 3
-			elseif (name == self.WRATH_OF_AIR_TOTEM) then
+			elseif (spellId == self.WRATH_OF_AIR_TOTEM) then
 				hateSorts = 5
-			elseif (name == self.WINDFURY_TOTEM and hateCaC == 0) then
+			elseif (spellId == self.WINDFURY_TOTEM and hateCaC == 0) then
 				hateCaC = 16
-			elseif (name == self.ICY_TALONS) then
+			elseif (spellId == self.ICY_TALONS) then
 				hateCaC = 20
-			elseif (name == self.BLOODLUST or name == self.HEROISM) then
+			elseif (spellId == self.BLOODLUST or spellId == self.HEROISM) then
 				hateHero = 30
-			elseif (name == self.JUDGMENT_OF_THE_PURE) then
+			elseif (spellId == self.JUDGMENT_OF_THE_PURE) then
 				hateClasse = 15
 			end
 			i = i + 1;
@@ -686,12 +694,10 @@ function Ovale:GLYPH_UPDATED(event)
 	self.needCompile = true
 end

---Called if the player interrupted early his cast
---The spell is removed from the lastSpell table
-function Ovale:UNIT_SPELLCAST_INTERRUPTED(event, unit, name, rank)
+function Ovale:RemoveSpellFromList(spellId, lineId)
 	if unit=="player" then
 		for i,v in ipairs(self.lastSpell) do
-			if v.name == name then
+			if v.lineId == lineId then
 				table.remove(self.lastSpell, i)
 				--self:Print("on supprime "..name)
 				break
@@ -700,49 +706,51 @@ function Ovale:UNIT_SPELLCAST_INTERRUPTED(event, unit, name, rank)
 	end
 end

---Called when a spell finished its cast
-function Ovale:UNIT_SPELLCAST_SENT(event,unit,name,rank,target)
-	-- self:Print("UNIT_SPELLCAST_SENT"..event.." unit="..unit.." name="..name.." tank="..rank.." target="..target)
-	if unit=="player" then
-		--The spell is added to the lastSpell table
-		local newSpell = {}
-		newSpell.name = name
-		-- local spell, rank, displayName, icon, startTime, endTime = UnitCastingInfo("player")
-		local spell, rank, icon, cost, isFunnel, powerType, castTime, minRange, maxRange = GetSpellInfo(name)
-		newSpell.start = GetTime()
-		if spell then
-			newSpell.stop = newSpell.start + castTime/1000
-		else
-			newSpell.stop = newSpell.start
-		end
-		local si = self.spellInfo[name]
+--Called if the player interrupted early his cast
+--The spell is removed from the lastSpell table
+function Ovale:UNIT_SPELLCAST_INTERRUPTED(event, unit, name, rank, lineId, spellId)
+	self:RemoveSpellFromList(spellId, lineId)
+end
+
+function Ovale:UNIT_SPELLCAST_SUCCEEDED(event, unit, name, rank, lineId, spellId)
+--	self:Print("UNIT_SPELLCAST_SUCCEEDED "..event.." name="..name.." lineId="..lineId.." spellId="..spellId)
+end
+
+function Ovale:AddSpellToList(spellId, lineId, startTime, endTime, channeled)
+	local newSpell = {}
+	newSpell.spellId = spellId
+	newSpell.lineId = lineId
+	newSpell.start = startTime
+	newSpell.stop = endTime
+	newSpell.channeled = channeled

+	self.lastSpell[#self.lastSpell+1] = newSpell
+	--self:Print("on ajoute "..spellId..": ".. newSpell.start.." to "..newSpell.stop.." ("..self.maintenant..")")
+
+	if self.spellInfo[spellId] then
+		local si = self.spellInfo[spellId]
 		if si and si.buffnocd and UnitBuff("player", GetSpellInfo(si.buffnocd)) then
 			newSpell.nocd = true
 		else
 			newSpell.nocd = false
 		end
-		self.lastSpell[#self.lastSpell+1] = newSpell
-		-- self:Print("on ajoute "..name.." a ".. newSpell.start)
-	end
-
-	if unit=="player" and self.enCombat then
-		if self.spellInfo[name] then
-			--Increase or reset the counter that is used by the Counter function
-			if self.spellInfo[name].resetcounter then
-				self.counter[self.spellInfo[name].resetcounter] = 0
-			end
-			if self.spellInfo[name].inccounter then
-				local cname = self.spellInfo[name].inccounter
-				if not self.counter[cname] then
-					self.counter[cname] = 0
-				end
-				self.counter[cname] = self.counter[cname] + 1
+		--Increase or reset the counter that is used by the Counter function
+		if si.resetcounter then
+			self.counter[si.resetcounter] = 0
+		end
+		if si.inccounter then
+			local cname = si.inccounter
+			if not self.counter[cname] then
+				self.counter[cname] = 0
 			end
+			self.counter[cname] = self.counter[cname] + 1
 		end
-		if (not self.spellInfo[name] or not self.spellInfo[name].toggle) and self.scoreSpell[name] then
+	end
+
+	if self.enCombat then
+		if (not self.spellInfo[spellId] or not self.spellInfo[spellId].toggle) and self.scoreSpell[spellId] then
 			--Compute the player score
-			local scored = self.frame:GetScore(name)
+			local scored = self.frame:GetScore(spellId)
 			if scored~=nil then
 				self.score = self.score + scored
 				self.maxScore = self.maxScore + 1
@@ -758,6 +766,27 @@ function Ovale:UNIT_SPELLCAST_SENT(event,unit,name,rank,target)
 	end
 end

+function Ovale:UNIT_SPELLCAST_CHANNEL_START(event, unit, name, rank, lineId, spellId)
+	if unit=="player" then
+		local _,_,_,_,startTime, endTime = UnitChannelInfo("player")
+		self:AddSpellToList(spellId, lineId, startTime/1000, endTime/1000, true)
+	end
+end
+
+function Ovale:UNIT_SPELLCAST_CHANNEL_STOP(event, unit, name, rank, lineId, spellId)
+	self:RemoveSpellFromList(spellId, lineId)
+end
+
+--Called when a spell started its cast
+function Ovale:UNIT_SPELLCAST_START(event, unit, name, rank, lineId, spellId)
+	--self:Print("UNIT_SPELLCAST_START "..event.." name="..name.." lineId="..lineId.." spellId="..spellId)
+	if unit=="player" then
+		local spell, rank, icon, cost, isFunnel, powerType, castTime, minRange, maxRange = GetSpellInfo(spellId)
+		local startTime =  GetTime()
+		self:AddSpellToList(spellId, lineId, startTime, startTime + castTime/1000)
+	end
+end
+
 function Ovale:CHAT_MSG_ADDON(event, prefix, msg, type, author)
 	if prefix ~= "Ovale" then return end
 	if type ~= "RAID" and type~= "PARTY" then return end
@@ -793,36 +822,6 @@ function Ovale:PLAYER_REGEN_DISABLED()
 	self:UpdateVisibility()
 end

-function Ovale_GetNomAction(i)
-	local actionText = GetActionText(i);
-	local text;
-	if (actionText) then
-		text = "Macro "..actionText;
-	else
-		local type, id = GetActionInfo(i);
-		if (type=="spell") then
-			if (id~=0) then
-				local spellName, spellRank = GetSpellName(id, BOOKTYPE_SPELL);
-				text = "Sort ".. spellName;
-				if (spellRank and spellRank~="") then
-					text = text .. " ("..spellRank..")"
-				end
-			end
-		elseif (type =="item") then
-			local itemName = GetItemInfo(id)
-			text = "Objet "..itemName
-		else
-			if (type) then
-				text = type;
-				if (id) then
-					text = text.." "..id;
-				end
-			end
-		end
-	end
-	return text
-end
-
 function Ovale:ChercherShortcut(id)
 -- ACTIONBUTTON1..12 => principale (1..12, 13..24, 73..108)
 -- MULTIACTIONBAR1BUTTON1..12 => bas gauche (61..72)
@@ -858,52 +857,17 @@ function Ovale:GetSpellInfoOrNil(spell)
 	end
 end

-function Ovale:GetSpellIdByName(name)
-	if (not name) then
-		return nil
-	end
-	local link = GetSpellLink(name);
-	if (not link) then
-		-- self:Print(name.." introuvable");
-		return nil;
-	end
-	local a, b, spellId = string.find(link, "spell:(%d+)");
-	return tonumber(spellId);
-end
-
-function Ovale:GetSpellIdRangMax(spellId)
-	return self:GetSpellIdByName(GetSpellInfo(spellId))
-end
-
-function Ovale:GetSpellIdByNameAndRank(name,rank)
-	if (not name or not rank) then
-		return nil
-	end
-	local link = GetSpellLink(name.."("..rank..")");
-	if (not link) then
-		-- self:Print(name.."("..rank..")".." introuvable");
-		return nil;
-	end
-	local a, b, spellId = string.find(link, "spell:(%d+)");
-	return tonumber(spellId);
-end
-
 function Ovale:RemplirActionIndex(i)
 	self.shortCut[i] = self:ChercherShortcut(i)
 	local actionText = GetActionText(i);
 	if (actionText) then
 		self.actionMacro[actionText] = i
 	else
-		local type, id = GetActionInfo(i);
+		local type, spellId = GetActionInfo(i);
 		if (type=="spell") then
-			if (id~=0) then
-				local spellName, spellRank = GetSpellInfo(id) -- GetSpellBookItemName(id, BOOKTYPE_SPELL);
-				if spellName then --TODO: bug avec le mécanisme solaire/lunaire du druide
-					self.actionSort[spellName] = i
-				end
-			end
+			self.actionSort[spellId] = i
 		elseif (type =="item") then
-			self.actionObjet[id] = i
+			self.actionObjet[spellId] = i
 		end
 	end
 end
@@ -923,7 +887,7 @@ function Ovale:RemplirListeTalents()
 	for t=1, numTabs do
 		local numTalents = GetNumTalents(t);
 		for i=1, numTalents do
-			local nameTalent, icon, tier, column, currRank, maxRank= GetTalentInfo(t,i);
+			local nameTalent, icon, tier, column, currRank, maxRank = GetTalentInfo(t,i);
 			local link = GetTalentLink(t,i)
 			local a, b, talentId = string.find(link, "talent:(%d+)");
 			talentId = tonumber(talentId)
@@ -936,22 +900,6 @@ function Ovale:RemplirListeTalents()
 	end
 end

-function Ovale:ChercherBouton(sort)
-	if (not sort) then
-		return nil
-	end
-	local nom = GetSpellInfo(tonumber(sort))
-	for i=1,120 do
-		local type, id = GetActionInfo(i);
-		if (type=="spell") then
-			local spellName, spellRank = GetSpellName(id, BOOKTYPE_SPELL);
-			if (spellName == nom) then
-				return i
-			end
-		end
-	end
-end
-
 function Ovale:AddRune(time, type, value)
 	if value<0 then
 		for i=1,6 do
@@ -992,14 +940,13 @@ function Ovale:GetAura(target, filter, spellId, forceduration)
 	myAura.serial = Ovale.serial

 	local i = 1
-	local auraName, auraRank, auraIcon = self:GetSpellInfoOrNil(spellId)

 	while (true) do
-		local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable =  UnitAura(target, i, filter);
+		local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, thisSpellId =  UnitAura(target, i, filter);
 		if not name then
 			break
 		end
-		if (unitCaster=="player" or not myAura.mine) and name == auraName and icon==auraIcon then
+		if (unitCaster=="player" or not myAura.mine) and spellId == thisSpellId then
 			myAura.mine = (unitCaster == "player")
 			myAura.start = expirationTime - duration

@@ -1022,17 +969,17 @@ function Ovale:GetAura(target, filter, spellId, forceduration)
 	return myAura
 end

-function Ovale:GetCD(spellName)
-	if not spellName then
+function Ovale:GetCD(spellId)
+	if not spellId then
 		return nil
 	end

-	if self.spellInfo[spellName] and self.spellInfo[spellName].cd then
+	if self.spellInfo[spellId] and self.spellInfo[spellId].cd then
 		local cdname
-		if self.spellInfo[spellName].sharedcd then
-			cdname = self.spellInfo[spellName].sharedcd
+		if self.spellInfo[spellId].sharedcd then
+			cdname = self.spellInfo[spellId].sharedcd
 		else
-			cdname = spellName
+			cdname = spellId
 		end
 		if not self.state.cd[cdname] then
 			self.state.cd[cdname] = {}
@@ -1043,24 +990,24 @@ function Ovale:GetCD(spellName)
 	end
 end

--- Lance un sort dans le simulateur
--- spellName : le nom du sort
+-- Cast a spell in the simulator
+-- spellId : the spell id
 -- startCast : temps du cast
 -- endCast : fin du cast
 -- nextCast : temps auquel le prochain sort peut être lancé (>=endCast, avec le GCD)
 -- nocd : le sort ne déclenche pas son cooldown
-function Ovale:AddSpellToStack(spellName, startCast, endCast, nextCast, nocd)
-	if not spellName then
+function Ovale:AddSpellToStack(spellId, startCast, endCast, nextCast, nocd)
+	if not spellId then
 		return
 	end

-	local newSpellInfo = nil
-	newSpellInfo = self.spellInfo[spellName]
+	local newSpellInfo = self.spellInfo[spellId]

 	--On enregistre les infos sur le sort en cours
 	self.attenteFinCast = nextCast
-	self.currentSpellName = spellName
+	self.currentSpellId = spellId
 	self.startCast = startCast
+	self.endCast = endCast
 	--Temps actuel de la simulation : un peu après le dernier cast (ou maintenant si dans le passé)
 	if startCast>=self.maintenant then
 		self.currentTime = startCast+0.1
@@ -1069,13 +1016,13 @@ function Ovale:AddSpellToStack(spellName, startCast, endCast, nextCast, nocd)
 	end

 	if Ovale.trace then
-		Ovale:Print("add spell "..spellName.." at "..startCast.." currentTime = "..nextCast)
+		Ovale:Print("add spell "..spellId.." at "..startCast.." currentTime = "..self.currentTime.. " nextCast="..self.attenteFinCast)
 	end

 	--Coût du sort (uniquement si dans le futur, dans le passé l'énergie est déjà dépensée)
 	if endCast >= self.maintenant then
 		--Mana
-		local _, _, _, cost = GetSpellInfo(spellName)
+		local _, _, _, cost = GetSpellInfo(spellId)
 		if cost then
 			self.state.mana = self.state.mana - cost
 		end
@@ -1147,7 +1094,7 @@ function Ovale:AddSpellToStack(spellName, startCast, endCast, nextCast, nocd)
 	-- Effets du sort
 	if newSpellInfo then
 		-- Cooldown du sort
-		local cd = self:GetCD(spellName)
+		local cd = self:GetCD(spellId)
 		if cd then
 			cd.start = startCast
 			cd.duration = newSpellInfo.cd
@@ -1181,21 +1128,24 @@ function Ovale:AddSpellToStack(spellName, startCast, endCast, nextCast, nocd)
 		if newSpellInfo.aura then
 			for target, targetInfo in pairs(newSpellInfo.aura) do
 				for filter, filterInfo in pairs(targetInfo) do
-					for spell, spellData in pairs(filterInfo) do
-						local newAura = self:GetAura(target, filter, spell)
+					for auraSpellId, spellData in pairs(filterInfo) do
+						local newAura = self:GetAura(target, filter, auraSpellId)
 						newAura.mine = true
 						local duration = spellData
 						local stacks = duration
-						local auraSpellName = self:GetSpellInfoOrNil(spell)
 						--Optionnellement, on va regarder la durée du buff
-						if auraSpellName and self.spellInfo[auraSpellName] and self.spellInfo[auraSpellName].duration then
-							duration = self.spellInfo[auraSpellName].duration
+						if auraSpellId and self.spellInfo[auraSpellId] and self.spellInfo[auraSpellId].duration then
+							duration = self.spellInfo[auraSpellId].duration
 						end
-						if stacks<0 and newAura.ending then
+						if stacks=="refresh" then
+							if newAura.ending then
+								newAura.ending = endCast + duration
+							end
+						elseif stacks<0 and newAura.ending then
 							--if filter~="HELPFUL" or target~="player" or startCast>=Ovale.maintenant then
 								newAura.stacks = newAura.stacks + stacks
 								if Ovale.trace then
-									self:Print("removing aura "..auraSpellName.." because of ".. spellName)
+									self:Print("removing aura "..auraSpellId.." because of ".. spellId)
 								end
 								--Plus de stacks, on supprime l'aura
 								if newAura.stacks<=0 then
@@ -1212,8 +1162,8 @@ function Ovale:AddSpellToStack(spellName, startCast, endCast, nextCast, nocd)
 							newAura.stacks = 1
 						end
 						if Ovale.trace then
-							if auraSpellName then
-								self:Print(spellName.." adding "..stacks.." aura "..auraSpellName.." to "..target.." "..filter.." "..newAura.start..","..newAura.ending)
+							if auraSpellId then
+								self:Print(spellId.." adding "..stacks.." aura "..auraSpellId.." to "..target.." "..filter.." "..newAura.start..","..newAura.ending)
 							else
 								self:Print("adding nil aura")
 							end
@@ -1233,7 +1183,7 @@ end
 function Ovale:InitCalculerMeilleureAction()
 	self.serial = self.serial + 1
 	self.currentTime = Ovale.maintenant
-	self.currentSpellName = nil
+	self.currentSpellId = nil
 	self.attenteFinCast = Ovale.maintenant
 	self.state.combo = GetComboPoints("player")
 	self.state.mana = UnitPower("player")
@@ -1260,28 +1210,27 @@ function Ovale:InitCalculerMeilleureAction()
 		v.toggled = nil
 	end

-	if (Ovale.db.profile.apparence.latencyCorrection) then
+--	if (Ovale.db.profile.apparence.latencyCorrection) then
 		for i,v in ipairs(self.lastSpell) do
-			if not self.spellInfo[v.name] or not self.spellInfo[v.name].toggle then
+			if not self.spellInfo[v.spellId] or not self.spellInfo[v.spellId].toggle then
 				--[[local spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitCastingInfo("player")
 				if spell and spell == v.name and startTime/1000 - v.start < 0.5 and v.stop~=endTime/1000 then
 					print("ancien = "..v.stop)
 					v.stop = endTime/1000
 					print("changement de v.stop en "..v.stop.." "..v.start)
 				end]]
-
+				self:Log("self.maintenant = " ..self.maintenant.." spellId="..v.spellId.." v.stop="..v.stop)
 				if self.maintenant - v.stop<5 then
-					self:AddSpellToStack(v.name, v.start, v.stop, v.stop, v.nocd)
+					self:AddSpellToStack(v.spellId, v.start, v.stop, v.stop, v.nocd)
 				end
 			end
 		end

-		local spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitChannelInfo("player")
-		if (spell) then
-			self:AddSpellToStack(spell, startTime/1000, endTime/1000, endTime/1000)
-		end
-
-	else
+		--local spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitChannelInfo("player")
+		--if (spell) then
+		--	self:AddSpellToStack(spell, startTime/1000, endTime/1000, endTime/1000)
+		--end
+	--[[else
 		-- On attend que le sort courant soit fini
 		local spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitCastingInfo("player")
 		if (spell) then
@@ -1292,7 +1241,7 @@ function Ovale:InitCalculerMeilleureAction()
 				self:AddSpellToStack(spell, startTime/1000, endTime/1000, endTime/1000)
 			end
 		end
-	end
+	end]]
 end

 local function printTime(temps)
@@ -1303,10 +1252,10 @@ local function printTime(temps)
 	end
 end

-function Ovale:GetGCD(spellName)
-	if spellName and self.spellInfo[spellName] then
-		if self.spellInfo[spellName].haste == "spell" then
-			local cd = self.spellInfo[spellName].gcd
+function Ovale:GetGCD(spellId)
+	if spellId and self.spellInfo[spellId] then
+		if self.spellInfo[spellId].haste == "spell" then
+			local cd = self.spellInfo[spellId].gcd
 			if not cd then
 				cd = 1.5
 			end
@@ -1315,8 +1264,8 @@ function Ovale:GetGCD(spellName)
 				cd = 1
 			end
 			return cd
-		elseif self.spellInfo[spellName].gcd then
-			return self.spellInfo[spellName].gcd
+		elseif self.spellInfo[spellId].gcd then
+			return self.spellInfo[spellId].gcd
 		end
 	end

@@ -1335,19 +1284,20 @@ function Ovale:GetGCD(spellName)
 	end
 end

-function Ovale:GetComputedSpellCD(spellName)
+--Compute the spell Cooldown
+function Ovale:GetComputedSpellCD(spellId)
 	local actionCooldownStart, actionCooldownDuration, actionEnable
-	local cd = self:GetCD(spellName)
+	local cd = self:GetCD(spellId)
 	if cd and cd.start then
 		actionCooldownStart = cd.start
 		actionCooldownDuration = cd.duration
 		actionEnable = cd.enable
 	else
-		actionCooldownStart, actionCooldownDuration, actionEnable = GetSpellCooldown(spellName)
+		actionCooldownStart, actionCooldownDuration, actionEnable = GetSpellCooldown(spellId)
 		-- Les chevaliers de la mort ont des infos fausses sur le CD quand ils n'ont plus les runes
 		-- On force à 1,5s ou 1s en présence impie
 		if self.className=="DEATHKNIGHT" and actionCooldownDuration==10 and
-				(not self.spellInfo[spellName] or self.spellInfo[spellName].cd~=10) then
+				(not self.spellInfo[spellId] or self.spellInfo[spellId].cd~=10) then
 			local impie = GetSpellInfo(48265)
 			if impie and UnitBuff("player", impie) then
 				actionCooldownDuration=1
@@ -1355,8 +1305,8 @@ function Ovale:GetComputedSpellCD(spellName)
 				actionCooldownDuration=1.5
 			end
 		end
-		if self.spellInfo[spellName] and self.spellInfo[spellName].forcecd then
-			actionCooldownStart, actionCooldownDuration = GetSpellCooldown(GetSpellInfo(self.spellInfo[spellName].forcecd))
+		if self.spellInfo[spellId] and self.spellInfo[spellId].forcecd then
+			actionCooldownStart, actionCooldownDuration = GetSpellCooldown(self.spellInfo[spellId].forcecd)
 		end
 	end
 	return actionCooldownStart, actionCooldownDuration, actionEnable
@@ -1367,7 +1317,7 @@ function Ovale:GetActionInfo(element)
 		return nil
 	end

-	local spellName
+	local spellId = element.params[1]
 	local action
 	local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration,
 		actionUsable, actionShortcut, actionIsCurrent, actionEnable
@@ -1378,25 +1328,21 @@ function Ovale:GetActionInfo(element)
 	end

 	if (element.func == "Spell" ) then
-		spellName = self:GetSpellInfoOrNil(element.params[1])
-		if not spellName then
+		--Test spell availability
+		local spellName = self:GetSpellInfoOrNil(spellId)
+		if not self:GetSpellInfoOrNil(spellName) then
 			return nil
 		end
-		action = self.actionSort[spellName]
-		actionCooldownStart, actionCooldownDuration, actionEnable = self:GetComputedSpellCD(spellName)
+		--Get spell info
+		action = self.actionSort[spellId]
+		actionCooldownStart, actionCooldownDuration, actionEnable = self:GetComputedSpellCD(spellId)

 		if (not action or not GetActionTexture(action)) then
-			actionTexture = GetSpellTexture(spellName)
+			actionTexture = GetSpellTexture(spellId)
+			local spellName = GetSpellInfo(spellId)
 			actionInRange = IsSpellInRange(spellName, target)
-			actionUsable = IsUsableSpell(spellName)
+			actionUsable = IsUsableSpell(spellId)
 			actionShortcut = nil
-			local casting = UnitCastingInfo("player")
-			if (casting == spellName) then
-				actionIsCurrent = 1
-			else
-				actionIsCurrent = nil
-			end
-			-- not quite the same as IsCurrentAction. Why did they remove IsCurrentCast?
 		end
 	elseif (element.func=="Macro") then
 		action = self.actionMacro[element.params[1]]
@@ -1416,7 +1362,7 @@ function Ovale:GetActionInfo(element)
 			self:Print("Item "..nilstring(itemId))
 		end

-		spellName = GetItemSpell(itemId)
+		local spellName = GetItemSpell(itemId)
 		actionUsable = (spellName~=nil)

 		action = self.actionObjet[itemId]
@@ -1448,13 +1394,13 @@ function Ovale:GetActionInfo(element)
 		actionIsCurrent = IsCurrentAction(action)
 	end

-	local cd = self:GetCD(spellName)
+	local cd = self:GetCD(spellId)
 	if cd and cd.toggle then
 		actionIsCurrent = 1
 	end

 	return actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration,
-					actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellName, target, element.params.nored
+					actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, target, element.params.nored
 end

 local function subTime(time1, duration)
@@ -1495,7 +1441,7 @@ function Ovale:CalculerMeilleureAction(element)
 		if (element.func == "Spell" or element.func=="Macro" or element.func=="Item" or element.func=="Texture") then
 			local action
 			local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration,
-				actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellName = self:GetActionInfo(element)
+				actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId = self:GetActionInfo(element)

 			if (not actionTexture) then
 				if (Ovale.trace) then
@@ -1509,10 +1455,10 @@ function Ovale:CalculerMeilleureAction(element)
 				end
 				return nil
 			end
-			if spellName and self.spellInfo[spellName] and self.spellInfo[spellName].casttime then
-				element.castTime = self.spellInfo[spellName].casttime
-			elseif spellName then
-				local spell, rank, icon, cost, isFunnel, powerType, castTime = GetSpellInfo(spellName)
+			if spellId and self.spellInfo[spellId] and self.spellInfo[spellId].casttime then
+				element.castTime = self.spellInfo[spellId].casttime
+			elseif spellId then
+				local spell, rank, icon, cost, isFunnel, powerType, castTime = GetSpellInfo(spellId)
 				if castTime then
 					element.castTime = castTime/1000
 				else
@@ -1521,7 +1467,8 @@ function Ovale:CalculerMeilleureAction(element)
 			else
 				element.castTime = 0
 			end
-			if (spellName and self.spellInfo[spellName] and self.spellInfo[spellName].toggle and actionIsCurrent) then
+			--TODO: not useful anymore?
+			if (spellId and self.spellInfo[spellId] and self.spellInfo[spellId].toggle and actionIsCurrent) then
 				if (Ovale.trace) then
 					self:Print("Action "..element.params[1].." is current action")
 				end
@@ -1534,16 +1481,16 @@ function Ovale:CalculerMeilleureAction(element)
 				else
 					restant = actionCooldownDuration + actionCooldownStart
 				end
-
+				self:Log("restant = "..restant.." attenteFinCast="..nilstring(self.attenteFinCast))
 				if restant<self.attenteFinCast then
 					if -- spellName==self.currentSpellName or
-						not self.spellInfo[self.currentSpellName] or
-							not self.spellInfo[self.currentSpellName].canStopChannelling then
+						not self.spellInfo[self.currentSpellId] or
+							not self.spellInfo[self.currentSpellId].canStopChannelling then
 						restant = self.attenteFinCast
 					else
 						--TODO: pas exact, parce que si ce sort est reporté de par exemple 0,5s par un debuff
 						--ça tombera entre deux ticks
-						local ticks = self.spellInfo[self.currentSpellName].canStopChannelling
+						local ticks = self.spellInfo[self.currentSpellId].canStopChannelling
 						local tickLength = (self.attenteFinCast - self.startCast) / ticks
 						local tickTime = self.startCast + tickLength
 						if (Ovale.trace) then
@@ -1558,7 +1505,7 @@ function Ovale:CalculerMeilleureAction(element)
 							tickTime = tickTime + tickLength
 						end
 						if (Ovale.trace) then
-							self:Print(spellName.." restant = " .. restant)
+							self:Print(spellId.." restant = " .. restant)
 						end
 					end
 				end
@@ -1596,6 +1543,10 @@ function Ovale:CalculerMeilleureAction(element)
 		end
 	elseif element.type == "time" then
 		return element.value
+	elseif element.type == "after" then
+		local timeA = Ovale:CalculerMeilleureAction(element.time)
+		local startA, endA = Ovale:CalculerMeilleureAction(element.a)
+		return addTime(startA, timeA), addTime(endA, timeA)
 	elseif (element.type == "before") then
 		if (Ovale.trace) then
 			--self:Print(nilstring(element.time).."s before ["..element.nodeId.."]")
@@ -1938,11 +1889,11 @@ function Ovale:GetListValue(v)
 	return self.dropDowns[v] and self.dropDowns[v].value
 end

-function Ovale:GetSpellInfo(spell)
-	if (not self.spellInfo[spell]) then
-		self.spellInfo[spell] = { aura = {player = {}, target = {}} }
+function Ovale:GetSpellInfo(spellId)
+	if (not self.spellInfo[spellId]) then
+		self.spellInfo[spellId] = { aura = {player = {}, target = {}} }
 	end
-	return self.spellInfo[spell]
+	return self.spellInfo[spellId]
 end

 function Ovale:ResetSpellInfo()
diff --git a/Ovale.toc b/Ovale.toc
index 19b317d..0d64e20 100644
--- a/Ovale.toc
+++ b/Ovale.toc
@@ -3,7 +3,7 @@
 ## Notes: Show the icon of the next spell to cast
 ## Notes-frFR: Affiche l'icône du prochain sort à lancer
 ## Author: Sidoine
-## Version: 4.0.1
+## Version: 4.0.2
 ## OptionalDeps: Ace3, ButtonFacade, Recount, LibBabble-CreatureType-3.0
 ## SavedVariables: OvaleDB
 ## SavedVariablesPerCharacter: OvaleDBPC
diff --git a/OvaleCompile.lua b/OvaleCompile.lua
index cd71e4f..49c65cb 100644
--- a/OvaleCompile.lua
+++ b/OvaleCompile.lua
@@ -47,30 +47,30 @@ end

 local function ParseSpellAddDebuff(params)
 	local paramList = ParseParameters(params)
-	local spell = Ovale:GetSpellInfoOrNil(paramList[1])
-	if (spell) then
+	local spellId = paramList[1]
+	if spellId then
 		paramList[1] = nil
-		Ovale:GetSpellInfo(spell).aura.player.HARMFUL = paramList
+		Ovale:GetSpellInfo(spellId).aura.player.HARMFUL = paramList
 	end
 	return ""
 end

 local function ParseSpellAddBuff(params)
 	local paramList = ParseParameters(params)
-	local spell = Ovale:GetSpellInfoOrNil(paramList[1])
-	if (spell) then
+	local spellId = paramList[1]
+	if spellId then
 		paramList[1] = nil
-		Ovale:GetSpellInfo(spell).aura.player.HELPFUL = paramList
+		Ovale:GetSpellInfo(spellId).aura.player.HELPFUL = paramList
 	end
 	return ""
 end

 local function ParseSpellAddTargetDebuff(params)
 	local paramList = ParseParameters(params)
-	local spell = Ovale:GetSpellInfoOrNil(paramList[1])
-	if (spell) then
+	local spellId = paramList[1]
+	if spellId then
 		paramList[1] = nil
-		Ovale:GetSpellInfo(spell).aura.target.HARMFUL = paramList
+		Ovale:GetSpellInfo(spellId).aura.target.HARMFUL = paramList
 	end
 	return ""
 end
@@ -98,15 +98,15 @@ end

 local function ParseSpellInfo(params)
 	local paramList = ParseParameters(params)
-	local spell = Ovale:GetSpellInfoOrNil(paramList[1])
-	if (spell) then
+	local spellId = paramList[1]
+	if spellId then
 		if paramList.glyph and not HasGlyph(paramList.glyph) then
 			return ""
 		end
 		if paramList.talent and not HasTalent(paramList.talent) then
 			return ""
 		end
-		local spellInfo = Ovale:GetSpellInfo(spell)
+		local spellInfo = Ovale:GetSpellInfo(spellId)
 		for k,v in pairs(paramList) do
 			if k == "addduration" then
 				spellInfo.duration = spellInfo.duration + v
@@ -122,11 +122,9 @@ end

 local function ParseScoreSpells(params)
 	for v in string.gmatch(params, "(%d+)") do
-		v = tonumber(v)
-
-		local spell = Ovale:GetSpellInfoOrNil(v)
-		if spell then
-			Ovale.scoreSpell[spell] = true
+		local spellId = tonumber(v)
+		if spellId then
+			Ovale.scoreSpell[spellId] = true
 		else
 			Ovale:Print("unknown spell "..v)
 		end
@@ -153,6 +151,11 @@ local function ParseBefore(a,b)
 	return AddNode(newNode)
 end

+local function ParseAfter(a,b)
+	local newNode = {type="after", time=node[tonumber(a)], a=node[tonumber(b)]}
+	return AddNode(newNode)
+end
+
 local function ParseBetween(a,b)
 	local newNode = {type="between", a=node[tonumber(a)], b=node[tonumber(b)]}
 	return AddNode(newNode)
@@ -202,7 +205,7 @@ local function subtest(text, pattern, func)
 	return text
 end

-local function ParseAddListItem(list,item,text, default)
+local function ParseAddListItem(list, item, text, default)
 	local paramList = ParseParameters(params)
 	if (paramList.talent and not HasTalent(paramList.talent)) or
 		(paramList.glyph and not HasGlyph(paramList.glyph)) then
@@ -255,6 +258,7 @@ local function ParseAddIcon(params, text)
 		text = string.gsub(text, "(at least)%s+node(%d+)%s+node(%d+)", ParseCompare)
 		text = string.gsub(text, "(at most)%s+node(%d+)%s+node(%d+)", ParseCompare)
 		text = string.gsub(text, "node(%d+)%s+before%s+node(%d+)", ParseBefore)
+		text = string.gsub(text, "node(%d+)%s+after%s+node(%d+)", ParseAfter)

 		if (was == text) then
 			break
@@ -315,11 +319,11 @@ function Ovale:CompileInputs(text)
 end

 local function ParseCanStopChannelling(text)
-	local spell = Ovale:GetSpellInfoOrNil(text)
-	if (spell) then
-		Ovale:GetSpellInfo(spell).canStopChannelling = true
+	local spellId = tonumber(text)
+	if spellId then
+		Ovale:GetSpellInfo(spellId).canStopChannelling = true
 	else
-		Ovale:Print("CanStopChannelling with unknown spell "..text)
+		Ovale:Print("CanStopChannelling with unknown spell "..spellId)
 	end
 	return ""
 end
diff --git a/OvaleFrame.lua b/OvaleFrame.lua
index fad6ab5..1481e9c 100644
--- a/OvaleFrame.lua
+++ b/OvaleFrame.lua
@@ -111,31 +111,31 @@ do
 		Ovale.db.profile.Colors = colors
 	end

-	local function GetScore(self, spellName)
+	local function GetScore(self, spellId)
 		for k,action in pairs(self.actions) do
-			if action.spellName == spellName then
+			if action.spellId == spellId then
 				if not action.waitStart then
-					-- print("sort "..spellName.." parfait")
+					-- print("sort "..spellId.." parfait")
 					return 1
 				else
 					local lag = Ovale.maintenant - action.waitStart
 					if lag>5 then
-					-- 	print("sort "..spellName.." ignoré (>5s)")
+					-- 	print("sort "..spellId.." ignoré (>5s)")
 						return nil
 					elseif lag>1.5 then
-					-- 	print("sort "..spellName.." trop lent !")
+					-- 	print("sort "..spellId.." trop lent !")
 						return 0
 					elseif lag>0 then
-					-- 	print("sort "..spellName.." un peu lent "..lag)
+					-- 	print("sort "..spellId.." un peu lent "..lag)
 						return 1-lag/1.5
 					else
-					-- 	print("sort "..spellName.." juste bon")
+					-- 	print("sort "..spellId.." juste bon")
 						return 1
 					end
 				end
 			end
 		end
---		print("sort "..spellName.." incorrect")
+--		print("sort "..spellId.." incorrect")
 		return 0
 	end

@@ -158,13 +158,13 @@ do
 			local action = self.actions[k]

 			local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration,
-					actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellName, actionTarget, noRed = Ovale:GetActionInfo(element)
+					actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, actionTarget, noRed = Ovale:GetActionInfo(element)
 			if noRed then
 				start = actionCooldownStart + actionCooldownDuration
 			end

 			-- Dans le cas de canStopChannelling, on risque de demander d'interrompre le channelling courant, ce qui est stupide
-			if start and Ovale.currentSpellName and Ovale.attenteFinCast and spellName == Ovale.currentSpellName and start<Ovale.attenteFinCast then
+			if start and Ovale.currentSpellId and Ovale.attenteFinCast and spellId == Ovale.currentSpellId and start<Ovale.attenteFinCast then
 				start = Ovale.attenteFinCast
 			end

@@ -172,10 +172,10 @@ do
 				action.icons[1]:Update(element, nil)
 			else
 				action.icons[1]:Update(element, start, actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration,
-					actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellName, actionTarget)
+					actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, actionTarget)
 			end

-			action.spellName = spellName
+			action.spellId = spellId

 			if start == Ovale.maintenant and actionUsable then
 				if not action.waitStart then
@@ -201,13 +201,13 @@ do
 			if (node.params.size ~= "small" and not node.params.nocd and Ovale.db.profile.apparence.predictif) then
 				if start then
 					local castTime=0
-					if spellName then
-						local _, _, _, _, _, _, _castTime = GetSpellInfo(spellName)
+					if spellId then
+						local _, _, _, _, _, _, _castTime = GetSpellInfo(spellId)
 						if _castTime and _castTime>0 then
 							castTime = _castTime/1000
 						end
 					end
-					local gcd = Ovale:GetGCD(spellName)
+					local gcd = Ovale:GetGCD(spellId)
 					local nextCast
 					if (castTime>gcd) then
 						nextCast = start + castTime
@@ -217,7 +217,7 @@ do
 					if Ovale.trace then
 						Ovale:Print("****Second icon")
 					end
-					Ovale:AddSpellToStack(spellName, start, start + castTime, nextCast)
+					Ovale:AddSpellToStack(spellId, start, start + castTime, nextCast)
 					start, ending, priorite, element = Ovale:CalculerMeilleureAction(node)
 					action.icons[2]:Update(element, start, Ovale:GetActionInfo(element))
 				else
diff --git a/OvaleIcone.lua b/OvaleIcone.lua
index 06e4b47..858ef89 100644
--- a/OvaleIcone.lua
+++ b/OvaleIcone.lua
@@ -3,9 +3,9 @@ local L = LibStub("AceLocale-3.0"):GetLocale("Ovale")
 local RANGE_INDICATOR = "●";

 local function Update(self, element, minAttente, actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration,
-				actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellName, actionTarget)
+				actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, actionTarget)

-	self.spellName = spellName
+	self.spellId = spellId
 	if (minAttente~=nil and actionTexture) then

 		if (actionTexture~=self.actionCourante or self.ancienneAttente==nil or
@@ -163,13 +163,13 @@ function OvaleIcone_OnClick(self)
 end

 function OvaleIcone_OnEnter(self)
-	if self.help or next(Ovale.casesACocher) or next(Ovale.listes) or self.spellName then
+	if self.help or next(Ovale.casesACocher) or next(Ovale.listes) or self.spellId then
 		GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT")
 		if self.help then
 			GameTooltip:SetText(L[self.help])
 		end
-		if self.spellName then
-			GameTooltip:AddLine(self.spellName,0.5,1,0.75)
+		if self.spellId then
+			GameTooltip:AddLine(GetSpellInfo(self.spellId),0.5,1,0.75)
 		end
 		if next(Ovale.casesACocher) or next(Ovale.listes) then
 			GameTooltip:AddLine(L["Cliquer pour afficher/cacher les options"],1,1,1)
diff --git a/defaut/Chasseur.lua b/defaut/Chasseur.lua
index 81f8823..4ada0eb 100644
--- a/defaut/Chasseur.lua
+++ b/defaut/Chasseur.lua
@@ -44,24 +44,9 @@ Define(SILENCINGSHOT 34490)
 #Buffs
 Define(LOCKANDLOAD 56453)
 Define(FRENZYEFFECT 19615)
-Define(IMPROVEDSTEADYSHOT 53224)
 Define(MARKEDFORDEATH 88691)
 Define(FIRE 82926)

-#Talents
-Define(TALENTCHIMSHOT 2135)
-Define(TALENTEXPLOSHOT 2145)
-Define(TALENTTRACKING 1623)
-
-#Trackings
-Define(TRACKBEASTS 1494)
-Define(TRACKDEMONS 19878)
-Define(TRACKDRAGONKIN 19879)
-Define(TRACKELEMENTALS 19880)
-Define(TRACKGIANTS 19882)
-Define(TRACKHUMANOIDS 19883)
-Define(TRACKUNDEAD 19884)
-
 AddCheckBox(multi SpellName(MULTISHOT))
 ScoreSpells(FOCUSFIRE KILLCOMMAND ARCANESHOT KILLSHOT STEADYSHOT SERPENTSTING
 			CHIMERASHOT AIMEDSHOT
diff --git a/defaut/Demoniste.lua b/defaut/Demoniste.lua
index 2637dd2..3877e3e 100644
--- a/defaut/Demoniste.lua
+++ b/defaut/Demoniste.lua
@@ -27,9 +27,11 @@ Define(FELARMOR 28176)
 Define(FELFLAME 77799)
 Define(HANDOFGULDAN 71521)
 	SpellInfo(HANDOFGULDAN cd=12)
+	SpellAddTargetDebuff(HANDOFGULDAN IMMOLATE=refresh)
 Define(HAUNT 48181)
 	SpellInfo(HAUNT cd=8)
 Define(IMMOLATE 348)
+	SpellInfo(IMMOLATE duration=15)
 	SpellAddTargetDebuff(IMMOLATE IMMOLATE=15)
 	SpellAddBuff(IMMOLATE MOLTENCORE=-1)
 Define(INCINERATE 29722)
@@ -49,13 +51,11 @@ Define(UNSTABLEAFFLICTION 30108)


 #Buff
-Define(SHADOWEMBRACE 32386)
 Define(DECIMATION 63167)
 Define(MOLTENCORE 71165)
-Define(EMPOWEREDIMP 47221)
+Define(EMPOWEREDIMP 47283)

 #Talent
-Define(TALENTSHADOWEMBRACE 1763)

 AddListItem(curse elements SpellName(CURSEELEMENTS))
 AddListItem(curse tongues SpellName(CURSETONGUES))
@@ -75,7 +75,6 @@ AddIcon help=main mastery=1
 	if List(curse weakness) and TargetDebuffExpires(CURSEWEAKNESS 2) and TargetDeadIn(more 8) Spell(CURSEWEAKNESS)

 	if TargetDebuffExpires(HAUNT 1.5 mine=1) Spell(HAUNT)
-	if TalentPoints(TALENTSHADOWEMBRACE more 0) and TargetDebuffExpires(SHADOWEMBRACE 0) Spell(SHADOWBOLT)
 	if TargetDebuffExpires(UNSTABLEAFFLICTION 1.5 mine=1 haste=spell) and TargetDeadIn(more 8) Spell(UNSTABLEAFFLICTION)
 	if TargetDebuffExpires(CORRUPTION 0 mine=1) and TargetDebuffExpires(SEEDOFCORRUPTION 0 mine=1) and TargetDeadIn(more 9) Spell(CORRUPTION)
 	if TargetDebuffExpires(BANEOFDOOM 0 mine=1) and TargetDebuffExpires(BANEOFAGONY 0 mine=1)
@@ -103,13 +102,13 @@ AddIcon help=main mastery=2
 	if List(curse weakness) and TargetDebuffExpires(CURSEWEAKNESS 2) and TargetDeadIn(more 8) Spell(CURSEWEAKNESS)

 	if TargetDebuffExpires(IMMOLATE 2 mine=1 haste=spell) and TargetDeadIn(more 8) Spell(IMMOLATE)
+	if TargetDebuffPresent(IMMOLATE) Spell(HANDOFGULDAN)
 	if TargetDebuffExpires(CORRUPTION 0 mine=1) and TargetDebuffExpires(SEEDOFCORRUPTION 0 mine=1) and TargetDeadIn(more 9) Spell(CORRUPTION)
 	if TargetDebuffExpires(BANEOFDOOM 0 mine=1) and TargetDebuffExpires(BANEOFAGONY 0 mine=1)
 	{
 		if List(curse doom) and TargetDeadIn(more 60) Spell(BANEOFDOOM)
 		if TargetDeadIn(more 10) Spell(BANEOFAGONY)
 	}
-	Spell(HANDOFGULDAN)
 	if BuffPresent(DECIMATION) Spell(SOULFIRE)
 	if BuffPresent(MOLTENCORE) Spell(INCINERATE)
 	Spell(SHADOWBOLT)
@@ -132,7 +131,7 @@ AddIcon help=main mastery=3
 	if List(curse elements) and TargetDebuffExpires(CURSEELEMENTS 2) and TargetDeadIn(more 8) Spell(CURSEELEMENTS)
 	if List(curse weakness) and TargetDebuffExpires(CURSEWEAKNESS 2) and TargetDeadIn(more 8) Spell(CURSEWEAKNESS)

-	if TargetDebuffPresent(IMMOLATE mine=1)	Spell(CONFLAGRATE)
+	if 1s after TargetDebuffPresent(IMMOLATE mine=1)	Spell(CONFLAGRATE)
 	if TargetDebuffExpires(IMMOLATE 2 mine=1 haste=spell) and TargetDeadIn(more 8) Spell(IMMOLATE)
 	if TargetDebuffExpires(CORRUPTION 0 mine=1) and TargetDebuffExpires(SEEDOFCORRUPTION 0 mine=1) and TargetDeadIn(more 9) Spell(CORRUPTION)
 	if TargetDebuffExpires(BANEOFDOOM 0 mine=1) and TargetDebuffExpires(BANEOFAGONY 0 mine=1)
diff --git a/defaut/Druide.lua b/defaut/Druide.lua
index 5928703..a5211a0 100644
--- a/defaut/Druide.lua
+++ b/defaut/Druide.lua
@@ -52,8 +52,9 @@ Define(STARSURGE 78674) #moonkin 15 lunar+solar
 	SpellInfo(STARSURGE cd=15 starsurge=15)
 Define(SUNFIRE 93402)
 	SpellAddTargetDebuff(SUNFIRE SUNFIRE=18)
-Define(SURVIVALINSTINCTS wssss61336) #cat+bear surv cd
+Define(SURVIVALINSTINCTS 61336) #cat+bear surv cd
 Define(SWIPEBEAR 779) #bear aoe
+	SpellInfo(SWIPEBEAR cd=6)
 Define(SWIPECAT 62078) #cat aoe
 Define(TRASH 77758) #bear aoe bleed
 Define(TIGERSFURY 5217) #cat buff
@@ -155,7 +156,9 @@ AddIcon help=main mastery=2

 		if Mana(more 50) Spell(MAUL)
 		if CheckBoxOn(multi)
-			Spell(SWIPEBEAR)
+			Spell(SWIPEBEAR)
+		Spell(MANGLEBEAR)
+		Spell(LACERATE)
 	}

 	if Stance(3) # cat
diff --git a/defaut/Paladin.lua b/defaut/Paladin.lua
index f941e41..b5f0685 100644
--- a/defaut/Paladin.lua
+++ b/defaut/Paladin.lua
@@ -7,6 +7,8 @@ Define(CONSECRATE 26573)
 	SpellInfo(CONSECRATE cd=8)
 Define(CRUSADERSTRIKE 35395)
 	SpellInfo(CRUSADERSTRIKE cd=4)
+Define(DIVINEFAVOR 31842)
+	SpellInfo(DIVINEFAVOR cd=180)
 Define(DIVINEPLEA 54428)
 	SpellInfo(DIVINEPLEA cd=60)
 	SpellAddBuff(DIVINEPLEA DIVINEPLEA=15)
@@ -36,12 +38,30 @@ Define(ZEALOTRY 85696)

 #Buff
 Define(THEARTOFWAR 59578)
+Define(JUDGEMENTSOFTHEPURE 53655)

 ScoreSpells(SHIELDOFTHERIGHTEOUS JUDGEMENT AVENGERSSHIELD HAMMEROFTHERIGHTEOUS CONSECRATE HOLYWRATH
 	ZEALOTRY  INQUISITION TEMPLARSVERDICT DIVINESTORM EXORCISM HAMMEROFWRATH JUDGEMENT CRUSADERSTRIKE)

 AddCheckBox(aoe L(AOE))

+AddIcon help=main mastery=1
+{
+	if HolyPower(more 0) and BuffExpires(INQUISITION) Spell(INQUISITION)
+	if ManaPercent(less 90) Spell(DIVINEPLEA)
+	if BuffExpires(JUDGEMENTSOFTHEPURE 2) Spell(JUDGEMENT)
+	Spell(HOLYSHOCK)
+	Spell(EXORCISM)
+}
+
+AddIcon help=cd mastery=1
+{
+	Spell(AVENGINGWRATH)
+	Spell(DIVINEFAVOR)
+	Item(Trinket0Slot usable=1)
+    Item(Trinket1Slot usable=1)
+}
+
 AddIcon help=main mastery=2
 {
 	if BuffExpires(RIGHTEOUSFURY) Spell(RIGHTEOUSFURY)