From c851318445a160347322f64a75942299c8b0140e Mon Sep 17 00:00:00 2001 From: "Johnny C. Lam" Date: Tue, 26 Nov 2013 14:04:35 +0000 Subject: [PATCH] Simplify casting spells in the simulator. - Push more state into the simulator. This is a step towards allowing multiple simulators managed by Ovale. - Remove OvaleState.now and replace with direct calls to API_GetTime(). Places that were using OvaleState.now were really needing the current time, and the client already caches the current time for API_GetTime() for the duration of a frame. - Re-arrange parameters to ApplySpell*() methods to simplify casting spells in the simulator. git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@1205 d5049fe3-3747-40f7-a4b5-f36d6801af5f --- OvaleAura.lua | 8 +- OvaleBestAction.lua | 21 ++--- OvaleComboPoints.lua | 2 +- OvaleCooldown.lua | 2 +- OvaleEclipse.lua | 2 +- OvaleFrame.lua | 41 ++++------ OvaleFuture.lua | 8 +- OvaleIcone.lua | 30 ++++---- OvalePaperDoll.lua | 3 +- OvalePower.lua | 2 +- OvaleRunes.lua | 4 +- OvaleState.lua | 145 +++++++++++++++++++++-------------- conditions/AfterWhiteHit.lua | 4 +- conditions/Health.lua | 38 ++++----- conditions/WeaponEnchantExpires.lua | 7 +- 15 files changed, 172 insertions(+), 145 deletions(-) diff --git a/OvaleAura.lua b/OvaleAura.lua index 97d04e7..8b2d2a0 100644 --- a/OvaleAura.lua +++ b/OvaleAura.lua @@ -613,7 +613,7 @@ function OvaleAura:ResetState(state) end -- Apply the effects of the spell on the player's state, assuming the spellcast completes. -function OvaleAura:ApplySpellAfterCast(state, spellId, startCast, endCast, nextCast, isChanneled, nocd, targetGUID, spellcast) +function OvaleAura:ApplySpellAfterCast(state, spellId, targetGUID, startCast, endCast, nextCast, isChanneled, nocd, spellcast) local si = OvaleData.spellInfo[spellId] -- Apply the auras on the player. if si and si.aura and si.aura.player then @@ -622,11 +622,11 @@ function OvaleAura:ApplySpellAfterCast(state, spellId, startCast, endCast, nextC end -- Apply the effects of the spell on the target's state when it lands on the target. -function OvaleAura:ApplySpellOnHit(state, spellId, startCast, endCast, nextCast, isChanneled, nocd, targetGUID, spellcast) +function OvaleAura:ApplySpellOnHit(state, spellId, targetGUID, startCast, endCast, nextCast, isChanneled, nocd, spellcast) local si = OvaleData.spellInfo[spellId] -- Apply the auras on the target. if si and si.aura and si.aura.target then - state:ApplySpellAuras(spellId, startCast, endCast, isChanneled, targetGUID, si.aura.target, spellcast) + state:ApplySpellAuras(spellId, targetGUID, startCast, endCast, isChanneled, si.aura.target, spellcast) end end -- @@ -636,7 +636,7 @@ do local statePrototype = OvaleAura.statePrototype -- Apply the auras caused by the given spell in the simulator. - statePrototype.ApplySpellAuras = function(state, spellId, startCast, endCast, isChanneled, guid, auraList, spellcast) + statePrototype.ApplySpellAuras = function(state, spellId, guid, startCast, endCast, isChanneled, auraList, spellcast) local target = OvaleGUID:GetUnitId(guid) for filter, filterInfo in pairs(auraList) do for auraId, spellData in pairs(filterInfo) do diff --git a/OvaleBestAction.lua b/OvaleBestAction.lua index c77bdce..0dfb37d 100644 --- a/OvaleBestAction.lua +++ b/OvaleBestAction.lua @@ -45,6 +45,7 @@ local Intersect = OvaleTimeSpan.Intersect local IntersectInterval = OvaleTimeSpan.IntersectInterval local Measure = OvaleTimeSpan.Measure local Union = OvaleTimeSpan.Union +local API_GetTime = GetTime local API_GetActionCooldown = GetActionCooldown local API_GetActionTexture = GetActionTexture local API_GetItemIcon = GetItemIcon @@ -124,14 +125,14 @@ local function ComputeAction(element) start = state.currentTime end - Ovale:Logf("start=%f nextCast=%s [%d]", start, OvaleState.nextCast, element.nodeId) + Ovale:Logf("start=%f nextCast=%s [%d]", start, state.nextCast, element.nodeId) -- If the action is available before the end of the current spellcast, then wait until we can first cast the action. - if start < OvaleState.nextCast then - local si = OvaleState.currentSpellId and OvaleData.spellInfo[OvaleState.currentSpellId] + if start < state.nextCast then + local si = state.currentSpellId and OvaleData.spellInfo[state.currentSpellId] if not (si and si.canStopChannelling) then -- not a channelled spell, or a channelled spell that cannot be interrupted - start = OvaleState.nextCast + start = state.nextCast else -- This is a channelled spell that can be interrupted, so wait till the next tick. -- "canStopChannelling=N" means that there are N total ticks in the channelled spell. @@ -144,8 +145,8 @@ local function ComputeAction(element) scaling = 1 end numTicks = floor(si.canStopChannelling * scaling + 0.5) - local tick = (OvaleState.nextCast - OvaleState.startCast) / numTicks - local tickTime = OvaleState.startCast + tick + local tick = (state.nextCast - state.startCast) / numTicks + local tickTime = state.startCast + tick Ovale:Logf("%s start=%f", spellId, start) for i = 1, numTicks do if start <= tickTime then @@ -717,9 +718,9 @@ function OvaleBestAction:OnInitialize() OvaleState = Ovale.OvaleState end -function OvaleBestAction:StartNewAction() - OvaleState:Reset() - OvaleFuture:ApplyInFlightSpells() +function OvaleBestAction:StartNewAction(state) + OvaleState:Reset(state) + OvaleFuture:ApplyInFlightSpells(state) self_serial = self_serial + 1 end @@ -819,7 +820,7 @@ function OvaleBestAction:GetActionInfo(element) local texture = element.params[1] actionTexture = "Interface\\Icons\\" .. texture actionInRange = nil - actionCooldownStart = OvaleState.now + actionCooldownStart = API_GetTime() actionCooldownDuration = 0 actionEnable = 1 actionUsable = true diff --git a/OvaleComboPoints.lua b/OvaleComboPoints.lua index 5b3fb75..4faae32 100644 --- a/OvaleComboPoints.lua +++ b/OvaleComboPoints.lua @@ -129,7 +129,7 @@ function OvaleComboPoints:ResetState(state) end -- Apply the effects of the spell on the player's state, assuming the spellcast completes. -function OvaleComboPoints:ApplySpellAfterCast(state, spellId, startCast, endCast, nextCast, isChanneled, nocd, targetGUID, spellcast) +function OvaleComboPoints:ApplySpellAfterCast(state, spellId, targetGUID, startCast, endCast, nextCast, isChanneled, nocd, spellcast) local si = OvaleData.spellInfo[spellId] if si and si.combo then local cost = si.combo diff --git a/OvaleCooldown.lua b/OvaleCooldown.lua index edcbd4b..6d0ed57 100644 --- a/OvaleCooldown.lua +++ b/OvaleCooldown.lua @@ -113,7 +113,7 @@ function OvaleCooldown:ResetState(state) end -- Apply the effects of the spell on the player's state, assuming the spellcast completes. -function OvaleCooldown:ApplySpellAfterCast(state, spellId, startCast, endCast, nextCast, isChanneled, nocd, targetGUID, spellcast) +function OvaleCooldown:ApplySpellAfterCast(state, spellId, targetGUID, startCast, endCast, nextCast, isChanneled, nocd, spellcast) local si = OvaleData.spellInfo[spellId] if si then local cd = state:GetCD(spellId) diff --git a/OvaleEclipse.lua b/OvaleEclipse.lua index 71d9467..3e7ff6f 100644 --- a/OvaleEclipse.lua +++ b/OvaleEclipse.lua @@ -144,7 +144,7 @@ function OvaleEclipse:ResetState(state) end -- Apply the effects of the spell on the player's state, assuming the spellcast completes. -function OvaleEclipse:ApplySpellAfterCast(state, spellId, startCast, endCast, nextCast, isChanneled, nocd, targetGUID, spellcast) +function OvaleEclipse:ApplySpellAfterCast(state, spellId, targetGUID, startCast, endCast, nextCast, isChanneled, nocd, spellcast) local si = OvaleData.spellInfo[spellId] if si and si.eclipse then local eclipse = state.eclipse diff --git a/OvaleFrame.lua b/OvaleFrame.lua index a6974a0..46a528a 100644 --- a/OvaleFrame.lua +++ b/OvaleFrame.lua @@ -138,7 +138,8 @@ do -- print("sort "..spellId.." parfait") return 1 else - local lag = OvaleState.now - action.waitStart + local now = API_GetTime() + local lag = now - action.waitStart if lag>5 then -- print("sort "..spellId.." ignoré (>5s)") return nil @@ -173,8 +174,8 @@ do self.lastUpdate = now - OvaleState:StartNewFrame() local state = OvaleState.state + OvaleState:StartNewFrame(state) for k,node in pairs(OvaleCompile.masterNodes) do local target if node.params and node.params.target then @@ -186,7 +187,7 @@ do if forceRefresh or Ovale.refreshNeeded[target] or Ovale.refreshNeeded["player"] or Ovale.refreshNeeded["pet"] then Ovale:Logf("****Master Node %d", k) - OvaleBestAction:StartNewAction() + OvaleBestAction:StartNewAction(state) local timeSpan, _, element = OvaleBestAction:Compute(node) local start = NextTime(timeSpan, state.currentTime) if start then @@ -206,7 +207,7 @@ do end local value if element.value and element.origin and element.rate then - value = element.value + (OvaleState.now - element.origin) * element.rate + value = element.value + (now - element.origin) * element.rate end icons[1]:SetValue(value, actionTexture) if #icons > 1 then @@ -222,10 +223,10 @@ do end end -- Dans le cas de canStopChannelling, on risque de demander d'interrompre le channelling courant, ce qui est stupide - if start and OvaleState.currentSpellId and OvaleState.nextCast and spellId == OvaleState.currentSpellId and start < OvaleState.nextCast then - start = OvaleState.nextCast + if start and state.currentSpellId and state.nextCast and spellId == state.currentSpellId and start < state.nextCast then + start = state.nextCast end - if (node.params.nocd and start~=nil and OvaleState.now1 then @@ -256,29 +257,15 @@ do if (node.params.size ~= "small" and not node.params.nocd and profile.apparence.predictif) then if start then - local castTime=0 - if spellId then - local _, _, _, _, _, _, _castTime = API_GetSpellInfo(spellId) - if _castTime and _castTime>0 then - castTime = _castTime/1000 - end - end - local gcd = OvaleCooldown:GetGCD(spellId) - local nextCast - if (castTime>gcd) then - nextCast = start + castTime - else - nextCast = start + gcd - end Ovale:Logf("****Second icon %f", start) local spellTarget if element then spellTarget = element.params.target end - if spellTarget == "target" or not spellTarget then - spellTarget = target + if not spellTarget or spellTarget == "target" then + spellTarget = OvaleCondition.defaultTarget end - OvaleState:ApplySpell(spellId, start, start + castTime, nextCast, false, false, OvaleGUID:GetGUID(spellTarget)) + OvaleState:ApplySpell(state, spellId, OvaleGUID:GetGUID(spellTarget)) timeSpan, _, element = OvaleBestAction:Compute(node) start = NextTime(timeSpan, state.currentTime) icons[2]:Update(element, start, OvaleBestAction:GetActionInfo(element)) diff --git a/OvaleFuture.lua b/OvaleFuture.lua index 45e9e7a..a529320 100644 --- a/OvaleFuture.lua +++ b/OvaleFuture.lua @@ -492,8 +492,8 @@ end -- Apply the effects of spells that are being cast or are in flight, allowing us to -- ignore lag or missile travel time. -function OvaleFuture:ApplyInFlightSpells() - local now = OvaleState.now +function OvaleFuture:ApplyInFlightSpells(state) + local now = API_GetTime() local index = 0 while true do index = index + 1 @@ -502,7 +502,7 @@ function OvaleFuture:ApplyInFlightSpells() local spellcast = self_activeSpellcast[index] Ovale:Logf("now = %f, spellId = %d, endCast = %f", now, spellcast.spellId, spellcast.stop) if now - spellcast.stop < 5 then - OvaleState:ApplySpell(spellcast.spellId, spellcast.start, spellcast.stop, spellcast.stop, spellcast.channeled, spellcast.nocd, spellcast.target, spellcast) + OvaleState:ApplySpell(state, spellcast.spellId, spellcast.target, spellcast.start, spellcast.stop, spellcast.stop, spellcast.channeled, spellcast.nocd, spellcast) else tremove(self_activeSpellcast, index) self_pool:Release(spellcast) @@ -585,7 +585,7 @@ function OvaleFuture:ResetState(state) end -- Apply the effects of the spell at the start of the spellcast. -function OvaleFuture:ApplySpellStartCast(state, spellId, startCast, endCast, nextCast, isChanneled, nocd, targetGUID, spellcast) +function OvaleFuture:ApplySpellStartCast(state, spellId, targetGUID, startCast, endCast, nextCast, isChanneled, nocd, spellcast) local si = OvaleData.spellInfo[spellId] if si then -- Increment and reset spell counters. diff --git a/OvaleIcone.lua b/OvaleIcone.lua index 8ead071..1c66742 100644 --- a/OvaleIcone.lua +++ b/OvaleIcone.lua @@ -23,6 +23,7 @@ local pairs = pairs local strfind = string.find local strsub = string.sub local tostring = tostring +local API_GetTime = GetTime -- -- @@ -53,23 +54,24 @@ end local function Update(self, element, minAttente, actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration, actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, actionTarget) - self.spellId = spellId self.value = nil + local now = API_GetTime() + local state = OvaleState.state local profile = OvaleOptions:GetProfile() if (minAttente~=nil and actionTexture) then if (actionTexture~=self.actionCourante or self.ancienneAttente==nil or - (minAttente~=OvaleState.now and minAttente>self.ancienneAttente+0.01) or + (minAttente~=now and minAttente>self.ancienneAttente+0.01) or (minAttente < self.finAction-0.01)) then if (actionTexture~=self.actionCourante or self.ancienneAttente==nil or - (minAttente~=OvaleState.now and minAttente>self.ancienneAttente+0.01)) then - self.debutAction = OvaleState.now + (minAttente~=now and minAttente>self.ancienneAttente+0.01)) then + self.debutAction = now end self.actionCourante = actionTexture self.finAction = minAttente - if (minAttente == OvaleState.now) then + if (minAttente == now) then self.cd:Hide() else self.lastSound = nil @@ -80,7 +82,7 @@ local function Update(self, element, minAttente, actionTexture, actionInRange, a end end - if not profile.apparence.flashIcon and minAttente<=OvaleState.now then + if not profile.apparence.flashIcon and minAttente<=now then self.cd:Hide() end @@ -98,21 +100,21 @@ local function Update(self, element, minAttente, actionTexture, actionInRange, a local red if minAttente > actionCooldownStart + actionCooldownDuration + 0.01 - and minAttente > OvaleState.now - and minAttente > OvaleState.nextCast then + and minAttente > now + and minAttente > state.nextCast then self.icone:SetVertexColor(0.75,0.2,0.2) red = true else self.icone:SetVertexColor(1,1,1) end - --if (minAttente==OvaleState.now) then + --if (minAttente==now) then --self.cd:Hide() --end if element.params.sound and not self.lastSound then local delay = element.params.soundtime or 0.5 - if OvaleState.now>=minAttente - delay then + if now>=minAttente - delay then self.lastSound = element.params.sound -- print("Play" .. self.lastSound) PlaySoundFile(self.lastSound) @@ -120,10 +122,10 @@ local function Update(self, element, minAttente, actionTexture, actionInRange, a end -- La latence - if minAttente>OvaleState.now and profile.apparence.highlightIcon and not red then + if minAttente>now and profile.apparence.highlightIcon and not red then local lag = 0.6 local newShouldClick - if minAttente OvaleState.now) then - self.remains:SetFormattedText("%.1f", minAttente - OvaleState.now) + if ((profile.apparence.numeric or self.params.text == "always") and minAttente > now) then + self.remains:SetFormattedText("%.1f", minAttente - now) self.remains:Show() else self.remains:Hide() diff --git a/OvalePaperDoll.lua b/OvalePaperDoll.lua index d308d64..aa2cbd7 100644 --- a/OvalePaperDoll.lua +++ b/OvalePaperDoll.lua @@ -500,7 +500,8 @@ end function OvalePaperDoll:ResetState(state) state.level = self.level state.specialization = self.specialization - if state.snapshot and state.snapshot.snapshotTime < OvaleState.now then + local now = API_GetTime() + if state.snapshot and state.snapshot.snapshotTime < now then state.snapshot:ReleaseReference() state.snapshot = nil end diff --git a/OvalePower.lua b/OvalePower.lua index 9a68488..dded77d 100644 --- a/OvalePower.lua +++ b/OvalePower.lua @@ -243,7 +243,7 @@ function OvalePower:ResetState(state) end -- Apply the effects of the spell on the player's state, assuming the spellcast completes. -function OvalePower:ApplySpellAfterCast(state, spellId, startCast, endCast, nextCast, isChanneled, nocd, targetGUID, spellcast) +function OvalePower:ApplySpellAfterCast(state, spellId, targetGUID, startCast, endCast, nextCast, isChanneled, nocd, spellcast) local si = OvaleData.spellInfo[spellId] -- Update power using information from GetSpellInfo() if there is no SpellInfo() for the spell's cost. diff --git a/OvaleRunes.lua b/OvaleRunes.lua index 720e1f7..a21f9c2 100644 --- a/OvaleRunes.lua +++ b/OvaleRunes.lua @@ -204,13 +204,13 @@ function OvaleRunes:ResetState(state) end -- Apply the effects of the spell on the player's state, assuming the spellcast completes. -function OvaleRunes:ApplySpellAfterCast(state, spellId, startCast, endCast, nextCast, isChanneled, nocd, targetGUID, spellcast) +function OvaleRunes:ApplySpellAfterCast(state, spellId, targetGUID, startCast, endCast, nextCast, isChanneled, nocd, spellcast) local si = OvaleData.spellInfo[spellId] if si then for i, name in ipairs(RUNE_NAME) do local count = si[name] or 0 while count > 0 do - local attime = isChanneled and startCast or endCast + local atTime = isChanneled and startCast or endCast state:ConsumeRune(atTime, name) count = count - 1 end diff --git a/OvaleState.lua b/OvaleState.lua index a62fb8c..cc4dcfa 100644 --- a/OvaleState.lua +++ b/OvaleState.lua @@ -28,30 +28,13 @@ local API_GetTime = GetTime local self_statePrototype = {} local self_stateModules = OvaleQueue:NewQueue("OvaleState_stateModules") - --- Whether the state of the simulator has been initialized. -local self_stateIsInitialized = false -- -- --- The spell being cast. -OvaleState.currentSpellId = nil -OvaleState.now = nil -OvaleState.nextCast = nil -OvaleState.startCast = nil -OvaleState.endCast = nil -OvaleState.isChanneling = nil -OvaleState.lastSpellId = nil - -- The state for the simulator. -OvaleState.state = { - currentTime = nil, -} +OvaleState.state = {} -- --- --- - -- function OvaleState:OnInitialize() -- Resolve module dependencies. @@ -59,6 +42,15 @@ function OvaleState:OnInitialize() OvaleFuture = Ovale.OvaleFuture end +function OvaleState:OnEnable() + self:RegisterState(self, self.statePrototype) +end + +function OvaleState:OnDisable() + self:UnregisterState(self) +end + + function OvaleState:RegisterState(addon, statePrototype) self_stateModules:Insert(addon) self_statePrototype[addon] = statePrototype @@ -95,29 +87,14 @@ function OvaleState:InvokeMethod(methodName, ...) end end -function OvaleState:StartNewFrame() - if not self_stateIsInitialized then - self:InitializeState() +function OvaleState:StartNewFrame(state) + if not state.isInitialized then + self:InvokeMethod("InitializeState", state) end - self.now = API_GetTime() -end - -function OvaleState:InitializeState() - self:InvokeMethod("InitializeState", self.state) - self_stateIsInitialized = true end -function OvaleState:Reset() - local state = self.state - state.currentTime = self.now - Ovale:Logf("Reset state with current time = %f", state.currentTime) - - self.lastSpellId = OvaleFuture.lastSpellcast and OvaleFuture.lastSpellcast.spellId - self.currentSpellId = nil - self.isChanneling = false - self.nextCast = self.now - - self:InvokeMethod("ResetState", self.state) +function OvaleState:Reset(state) + self:InvokeMethod("ResetState", state) end --[[ @@ -125,38 +102,50 @@ end Parameters: spellId The ID of the spell to cast. + targetGUID The GUID of the target of the spellcast. startCast The time at the start of the spellcast. endCast The time at the end of the spellcast. nextCast The earliest time at which the next spell can be cast (nextCast >= endCast). isChanneled The spell is a channeled spell. nocd The spell's cooldown is not triggered. - targetGUID The GUID of the target of the spellcast. spellcast (optional) Table of spellcast information, including a snapshot of player's stats. --]] -function OvaleState:ApplySpell(...) - local spellId, startCast, endCast, nextCast, isChanneled, nocd, targetGUID, spellcast = ... +function OvaleState:ApplySpell(state, ...) + local spellId, targetGUID, startCast, endCast, nextCast, isChanneled, nocd, spellcast = ... if not spellId or not targetGUID then return end + -- Handle missing start/end/next cast times. + if not startCast or not endCast or not nextCast then + local castTime = 0 + local castTime = select(7, API_GetSpellInfo(spellId)) + castTime = castTime and (castTime / 1000) or 0 + local gcd = OvaleCooldown:GetGCD(spellId) + + startCast = startCast or state.nextCast + endCast = endCast or (startCast + castTime) + nextCast = (castTime > gcd) and endCast or (startCast + gcd) + end + -- Update the latest spell cast in the simulator. - local state = self.state - self.nextCast = nextCast - self.currentSpellId = spellId - self.startCast = startCast - self.endCast = endCast - self.isChanneling = isChanneled - self.lastSpellId = spellId + state.currentSpellId = spellId + state.startCast = startCast + state.endCast = endCast + state.nextCast = nextCast + state.isChanneling = isChanneled + state.lastSpellId = spellId -- Set the current time in the simulator to a little after the start of the current cast, -- or to now if in the past. - if startCast >= self.now then + local now = API_GetTime() + if startCast >= now then state.currentTime = startCast + 0.1 else - state.currentTime = self.now + state.currentTime = now end - Ovale:Logf("Apply spell %d at %f currentTime=%f nextCast=%f endCast=%f targetGUID=%s", spellId, startCast, state.currentTime, self.nextCast, endCast, targetGUID) + Ovale:Logf("Apply spell %d at %f currentTime=%f nextCast=%f endCast=%f targetGUID=%s", spellId, startCast, state.currentTime, nextCast, endCast, targetGUID) --[[ Apply the effects of the spellcast in three phases. @@ -165,13 +154,57 @@ function OvaleState:ApplySpell(...) 3. Effects when the spellcast hits the target. --]] -- If the spellcast has already started, then the effects have already occurred. - if startCast >= OvaleState.now then - self:InvokeMethod("ApplySpellStartCast", self.state, ...) + if startCast >= now then + self:InvokeMethod("ApplySpellStartCast", state, ...) end -- If the spellcast has already ended, then the effects have already occurred. - if endCast > OvaleState.now then - self:InvokeMethod("ApplySpellAfterCast", self.state, ...) + if endCast > now then + self:InvokeMethod("ApplySpellAfterCast", state, ...) end - self:InvokeMethod("ApplySpellOnHit", self.state, ...) + self:InvokeMethod("ApplySpellOnHit", state, ...) +end +-- + +--[[---------------------------------------------------------------------------- + State machine for simulator. +--]]---------------------------------------------------------------------------- + +-- +OvaleState.statePrototype = { + -- Whether the state of the simulator has been initialized. + isInitialized = nil, + -- The current time in the simulator. + currentTime = nil, + -- The spell being cast in the simulator. + currentSpellId = nil, + -- The starting cast time of the spell being cast in the simulator. + startCast = nil, + -- The ending cast time of the spell being cast in the simulator. + endCast = nil, + -- The time at which the next GCD spell can be cast in the simulator. + nextCast = nil, + -- Whether the player is channeling a spell in the simulator at the current time. + isChanneling = nil, + -- The previous spell cast in the simulator. + lastSpellId = nil, +} +-- + +-- +-- Initialize the state. +function OvaleState:InitializeState(state) + state.isInitialized = true +end + +-- Reset the state to the current conditions. +function OvaleState:ResetState(state) + local now = API_GetTime() + state.currentTime = now + Ovale:Logf("Reset state with current time = %f", state.currentTime) + + state.lastSpellId = OvaleFuture.lastSpellcast and OvaleFuture.lastSpellcast.spellId + state.currentSpellId = nil + state.isChanneling = false + state.nextCast = now end -- diff --git a/conditions/AfterWhiteHit.lua b/conditions/AfterWhiteHit.lua index 597b3ef..48352b8 100644 --- a/conditions/AfterWhiteHit.lua +++ b/conditions/AfterWhiteHit.lua @@ -12,9 +12,9 @@ local _, Ovale = ... do local OvaleCondition = Ovale.OvaleCondition - local OvaleState = Ovale.OvaleState local OvaleSwing = Ovale.OvaleSwing + local API_GetTime = GetTime local TestValue = OvaleCondition.TestValue -- Test if a white hit just occured @@ -25,7 +25,7 @@ do local seconds, comparator, limit = condition[1], condition[2], condition[3] local start = OvaleSwing.starttime local ending = start + OvaleSwing.duration - local now = OvaleState.now + local now = API_GetTime() local value if now - start < seconds then value = 0 diff --git a/conditions/Health.lua b/conditions/Health.lua index e28272b..f84fac4 100644 --- a/conditions/Health.lua +++ b/conditions/Health.lua @@ -13,9 +13,9 @@ local _, Ovale = ... do local OvaleCondition = Ovale.OvaleCondition local OvaleGUID = Ovale.OvaleGUID - local OvaleState = Ovale.OvaleState local floor = math.floor + local API_GetTime = GetTime local API_UnitHealth = UnitHealth local API_UnitHealthMax = UnitHealthMax local Compare = OvaleCondition.Compare @@ -31,6 +31,7 @@ do --[[ Returns: Estimated number of seconds before the specified unit reaches zero health + The current time Unit's current health Unit's maximum health --]] @@ -50,6 +51,7 @@ do local timeToDie local health = API_UnitHealth(unitId) or 0 local maxHealth = API_UnitHealthMax(unitId) or 1 + local currentTime = API_GetTime() -- Clamp maxHealth to always be at least 1. if maxHealth < health then @@ -65,7 +67,7 @@ do Ovale:Log("Training Dummy, return in the future") timeToDie = math.huge else - local now = floor(OvaleState.now) + local now = floor(currentTime) if (not lastTTDTime[unitId] or lastTTDTime[unitId] < now) and lastTTDguid[unitId] then lastTTDTime[unitId] = now local mod10, prevHealth @@ -94,7 +96,7 @@ do -- Return time to die in the far-off future (one week). timeToDie = 3600 * 24 * 7 end - return timeToDie, health, maxHealth + return timeToDie, currentTime, health, maxHealth end --- Get the current amount of health points of the target. @@ -115,14 +117,14 @@ do local function Health(condition) local comparator, limit = condition[1], condition[2] local target = ParseCondition(condition) - local timeToDie, health, maxHealth = EstimatedTimeToDie(target) + local timeToDie, now, health, maxHealth = EstimatedTimeToDie(target) if not timeToDie then return nil elseif timeToDie == 0 then return Compare(0, comparator, limit) end - local value, origin, rate = health, OvaleState.now, -1 * health / timeToDie - local start, ending = OvaleState.now, math.huge + local value, origin, rate = health, now, -1 * health / timeToDie + local start, ending = now, math.huge return TestValue(start, ending, value, origin, rate, comparator, limit) end @@ -147,13 +149,13 @@ do local function HealthMissing(condition) local comparator, limit = condition[1], condition[2] local target = ParseCondition(condition) - local timeToDie, health, maxHealth = EstimatedTimeToDie(target) + local timeToDie, now, health, maxHealth = EstimatedTimeToDie(target) if not timeToDie or timeToDie == 0 then return nil end local missing = maxHealth - health - local value, origin, rate = missing, OvaleState.now, health / timeToDie - local start, ending = OvaleState.now, math.huge + local value, origin, rate = missing, now, health / timeToDie + local start, ending = now, math.huge return TestValue(start, ending, value, origin, rate, comparator, limit) end @@ -178,15 +180,15 @@ do local function HealthPercent(condition) local comparator, limit = condition[1], condition[2] local target = ParseCondition(condition) - local timeToDie, health, maxHealth = EstimatedTimeToDie(target) + local timeToDie, now, health, maxHealth = EstimatedTimeToDie(target) if not timeToDie then return nil elseif timeToDie == 0 then return Compare(0, comparator, limit) end local healthPercent = health / maxHealth * 100 - local value, origin, rate = healthPercent, OvaleState.now, -1 * healthPercent / timeToDie - local start, ending = OvaleState.now, math.huge + local value, origin, rate = healthPercent, now, -1 * healthPercent / timeToDie + local start, ending = now, math.huge return TestValue(start, ending, value, origin, rate, comparator, limit) end @@ -233,9 +235,9 @@ do local function TimeToDie(condition) local comparator, limit = condition[1], condition[2] local target = ParseCondition(condition) - local timeToDie = EstimatedTimeToDie(target) - local value, origin, rate = timeToDie, OvaleState.now, -1 - local start, ending = OvaleState.now, OvaleState.now + timeToDie + local timeToDie, now = EstimatedTimeToDie(target) + local value, origin, rate = timeToDie, now, -1 + local start, ending = now, now + timeToDie return TestValue(start, ending, value, origin, rate, comparator, limit) end @@ -260,12 +262,12 @@ do local function TimeToHealthPercent(condition) local percent, comparator, limit = condition[1], condition[2], condition[3] local target = ParseCondition(condition) - local timeToDie, health, maxHealth = EstimatedTimeToDie(target) + local timeToDie, now, health, maxHealth = EstimatedTimeToDie(target) local healthPercent = health / maxHealth * 100 if healthPercent >= percent then local t = timeToDie * (healthPercent - percent) / healthPercent - local value, origin, rate = t, OvaleState.now, -1 - local start, ending = OvaleState.now, OvaleState.now + t + local value, origin, rate = t, now, -1 + local start, ending = now, now + t return TestValue(start, ending, value, origin, rate, comparator, limit) end return Compare(0, comparator, limit) diff --git a/conditions/WeaponEnchantExpires.lua b/conditions/WeaponEnchantExpires.lua index d4c9fdc..861acc2 100644 --- a/conditions/WeaponEnchantExpires.lua +++ b/conditions/WeaponEnchantExpires.lua @@ -12,8 +12,8 @@ local _, Ovale = ... do local OvaleCondition = Ovale.OvaleCondition - local OvaleState = Ovale.OvaleState + local API_GetTime = GetTime local API_GetWeaponEnchantInfo = GetWeaponEnchantInfo --- Test if the weapon imbue on the given weapon has expired or will expire after a given number of seconds. @@ -31,18 +31,19 @@ do local hand, seconds = condition[1], condition[2] seconds = seconds or 0 local hasMainHandEnchant, mainHandExpiration, _, hasOffHandEnchant, offHandExpiration = API_GetWeaponEnchantInfo() + local now = API_GetTime() if hand == "mainhand" or hand == "main" then if not hasMainHandEnchant then return 0, math.huge end mainHandExpiration = mainHandExpiration / 1000 - return OvaleState.now + mainHandExpiration - seconds, math.huge + return now + mainHandExpiration - seconds, math.huge else if not hasOffHandEnchant then return 0, math.huge end offHandExpiration = offHandExpiration / 1000 - return OvaleState.now + offHandExpiration - seconds, math.huge + return now + offHandExpiration - seconds, math.huge end end -- 1.7.9.5