Johnny C. Lam [10-15-13 - 01:24]
diff --git a/Ovale.toc b/Ovale.toc
index 294f457..69042a2 100644
--- a/Ovale.toc
+++ b/Ovale.toc
@@ -44,6 +44,7 @@ OvaleRecount.lua
OvaleSkada.lua
OvaleSpellBook.lua
OvaleStance.lua
+OvaleTimeSpan.lua
#
OvaleDamageTaken.lua
OvalePaperDoll.lua
diff --git a/OvaleBestAction.lua b/OvaleBestAction.lua
index 5bfdec3..06b1fde 100644
--- a/OvaleBestAction.lua
+++ b/OvaleBestAction.lua
@@ -22,6 +22,7 @@ local OvalePower = Ovale.OvalePower
local OvaleSpellBook = Ovale.OvaleSpellBook
local OvaleStance = Ovale.OvaleStance
local OvaleState = Ovale.OvaleState
+local OvaleTimeSpan = Ovale.OvaleTimeSpan
local floor = math.floor
local ipairs = ipairs
@@ -31,6 +32,11 @@ local select = select
local strfind = string.find
local tonumber = tonumber
local tostring = tostring
+local Complement = OvaleTimeSpan.Complement
+local HasTime = OvaleTimeSpan.HasTime
+local Intersect = OvaleTimeSpan.Intersect
+local Measure = OvaleTimeSpan.Measure
+local Union = OvaleTimeSpan.Union
local API_GetActionCooldown = GetActionCooldown
local API_GetActionTexture = GetActionTexture
local API_GetItemIcon = GetItemIcon
@@ -52,50 +58,6 @@ local self_serial = 0
--</private-static-properties>
--<private-static-methods>
-local function addTime(time1, duration)
- if not time1 then
- return nil
- else
- return time1 + duration
- end
-end
-
-local function isBeforeEqual(time1, time2)
- return time1 and (not time2 or time1<=time2)
-end
-
-local function isBefore(time1, time2)
- return time1 and (not time2 or time1<time2)
-end
-
-local function isAfterEqual(time1, time2)
- return not time1 or (time2 and time1>=time2)
-end
-
-local function isAfter(time1, time2)
- return not time1 or (time2 and time1>time2)
-end
-
-local function minTime(time1, time2)
- if isBefore(time1, time2) then
- return time1
- else
- return time2
- end
-end
-
-local function isBetween(checkTime, startTime, endTime)
- return isBeforeEqual(startTime, checkTime) and isAfterEqual(endTime, checkTime)
-end
-
-local function maxTime(time1, time2)
- if isAfter(time1, time2) then
- return time1
- else
- return time2
- end
-end
-
local function PutValue(element, value, origin, rate)
if not element.result then
element.result = { type = "value" }
@@ -111,36 +73,16 @@ local function ComputeAnd(element, atTime)
Ovale:Logf("%s [%d]", element.type, element.nodeId)
local self = OvaleBestAction
local startA, endA = self:ComputeBool(element.a, atTime)
- if not startA then
- Ovale:Logf("%s return nil [%d]", element.type, element.nodeId)
- return nil
- end
- if startA == endA then
- Ovale:Logf("%s return startA=endA [%d]", element.type, element.nodeId)
- return nil
- end
- local startB, endB, prioriteB, elementB
- if element.type == "if" then
- startB, endB, prioriteB, elementB = self:Compute(element.b, atTime)
- else
- startB, endB, prioriteB, elementB = self:ComputeBool(element.b, atTime)
- end
- -- If the "then" clause is a "wait" node, then only wait if the conditions are true.
- if elementB and elementB.wait and not isBetween(atTime, startA, endA) then
- elementB.wait = nil
- end
- if isAfter(startB, endA) or isAfter(startA, endB) then
- Ovale:Logf("%s return nil [%d]", element.type, element.nodeId)
+ -- Short-circuit evaluation of left argument to AND.
+ if Measure(startA, endA) == 0 then
+ Ovale:Logf("%s return timespan with measure 0 [%d]", element.type, element.nodeId)
return nil
end
- if isBefore(startB, startA) then
- startB = startA
- end
- if isAfter(endB, endA) then
- endB = endA
- end
- Ovale:Logf("%s return %s, %s [%d]", element.type, startB, endB, element.nodeId)
- return startB, endB, prioriteB, elementB
+ local startB, endB = self:ComputeBool(element.b, atTime)
+ -- Take intersection of (startA, endA) and (startB, endB).
+ startA, endA = Intersect(startA, endA, startB, endB)
+ Ovale:Logf("%s returns %s, %s [%d]", element.type, startA, endA, element.nodeId)
+ return startA, endA
end
local function ComputeArithmetic(element, atTime)
@@ -149,13 +91,9 @@ local function ComputeArithmetic(element, atTime)
local startB, endB, _, elementB = self:Compute(element.b, atTime)
-- Take intersection of (startA, endA) and (startB, endB)
- if isBefore(startA, startB) then
- startA = startB
- end
- if isAfter(endA, endB) then
- endA = endB
- end
- if not isBefore(startA, endA) then
+ startA, endA = Intersect(startA, endA, startB, endB)
+ if Measure(startA, endA) == 0 then
+ Ovale:Logf("%s return timespan with measure 0 [%d]", element.type, element.nodeId)
return nil
end
@@ -251,13 +189,8 @@ local function ComputeCompare(element, atTime)
local startB, endB, _, elementB = self:Compute(element.b, atTime)
-- Take intersection of (startA, endA) and (startB, endB)
- if isBefore(startA, startB) then
- startA = startB
- end
- if isAfter(endA, endB) then
- endA = endB
- end
- if not isBefore(startA, endA) then
+ startA, endA = Intersect(startA, endA, startB, endB)
+ if Measure(startA, endA) == 0 then
return nil
end
@@ -273,8 +206,9 @@ local function ComputeCompare(element, atTime)
local x = elementB and elementB.value or 0
local y = elementB and elementB.origin or 0
local z = elementB and elementB.rate or 0
+ local operator = element.operator
- Ovale:Logf("%f+(t-%f)*%f %s %f+(t-%f)*%f [%d]", a, b, c, element.operator, x, y, z, element.nodeId)
+ Ovale:Logf("%f+(t-%f)*%f %s %f+(t-%f)*%f [%d]", a, b, c, operator, x, y, z, element.nodeId)
--[[
A(t) = B(t)
@@ -286,34 +220,30 @@ local function ComputeCompare(element, atTime)
local A = a - b*c
local B = x - y*z
if c == z then
- if (element.operator == "==" and A == B)
- or (element.operator == "<" and A < B)
- or (element.operator == "<=" and A <= B)
- or (element.operator == ">" and A > B)
- or (element.operator == ">=" and A >= B) then
- return startA, endA
+ if not ((operator == "==" and A == B)
+ or (operator == "<" and A < B)
+ or (operator == "<=" and A <= B)
+ or (operator == ">" and A > B)
+ or (operator == ">=" and A >= B)) then
+ startA, endA = nil, nil
end
else
local t = (B - A)/(c - z)
- if (c > z and element.operator == "<")
- or (c > z and element.operator == "<=")
- or (c < z and element.operator == ">")
- or (c < z and element.operator == ">=") then
- -- (startA, endA) intersect (-inf, t)
- endA = minTime(endA, t)
- end
- if (c < z and element.operator == "<")
- or (c < z and element.operator == "<=")
- or (c > z and element.operator == ">")
- or (c > z and element.operator == ">=") then
- -- (startA, endA) intersect (t, inf)
- startA = maxTime(startA, t)
+ if (c > z and operator == "<")
+ or (c > z and operator == "<=")
+ or (c < z and operator == ">")
+ or (c < z and operator == ">=") then
+ startA, endA = Intersect(startA, endA, 0, t)
end
- if isBefore(startA, endA) then
- return startA, endA
+ if (c < z and operator == "<")
+ or (c < z and operator == "<=")
+ or (c > z and operator == ">")
+ or (c > z and operator == ">=") then
+ startA, endA = Intersect(startA, endA, t, math.huge)
end
end
- return nil
+ Ovale:Logf("compare %s returns %s, %s [%d]", operator, startA, endA, element.nodeId)
+ return startA, endA
end
local function ComputeCustomFunction(element, atTime)
@@ -364,7 +294,9 @@ local function ComputeFunction(element, atTime)
end
if actionEnable and actionEnable > 0 then
- local start
+ local start, ending = 0, math.huge
+ local priority = element.params.priority or OVALE_DEFAULT_PRIORITY
+
if actionCooldownDuration and actionCooldownStart and actionCooldownStart > 0 then
start = actionCooldownDuration + actionCooldownStart
else
@@ -394,8 +326,7 @@ local function ComputeFunction(element, atTime)
end
end
Ovale:Logf("Action %s can start at %f", element.params[1], start)
- local priority = element.params.priority or OVALE_DEFAULT_PRIORITY
- return start, nil, priority, element
+ return start, ending, priority, element
else
Ovale:Logf("Action %s not enabled", element.params[1])
end
@@ -436,13 +367,9 @@ local function ComputeGroup(element, atTime)
for k, v in ipairs(element.nodes) do
local start, ending, priority, newElement = self:Compute(v, atTime)
-
- if start and start < atTime then
- start = atTime
- end
-
- if start and (not ending or start <= ending) then
- -- The node has a valid time interval.
+ -- We only care about actions that are available at time t > atTime.
+ start, ending = Intersect(start, ending, atTime, math.huge)
+ if Measure(start, ending) > 0 then
local castTime
if newElement then
castTime = newElement.castTime
@@ -459,17 +386,17 @@ local function ComputeGroup(element, atTime)
Ovale:Errorf("Internal error: bestPriority=nil and priority=%d", priority)
return nil
elseif priority and priority > bestPriority then
- -- If the new spell has a higher priority than the previous one, then choose the
+ -- If the new spell has a higher priority than the best one found, then choose the
-- higher priority spell if its cast is pushed back too far by the lower priority one.
if newElement and newElement.params and newElement.params.wait then
- if start and start - bestStart < newElement.params.wait then
+ if start - bestStart < newElement.params.wait then
replace = true
end
elseif start - bestStart < bestCastTime * 0.75 then
replace = true
end
elseif priority and priority < bestPriority then
- -- If the new spell has a lower priority than the previous one, then choose the
+ -- If the new spell has a lower priority than the best one found, then choose the
-- lower priority spell only if it doesn't push back the cast of the higher priority
-- one by too much.
if bestElement and bestElement.params and bestElement.params.wait then
@@ -481,12 +408,11 @@ local function ComputeGroup(element, atTime)
end
else
-- If the spells have the same priority, then pick the one with an earlier cast time.
- -- TODO: why have a 0.01 second threshold here?
if bestElement and bestElement.params and bestElement.params.wait then
if bestStart - start > bestElement.params.wait then
replace = true
end
- elseif bestStart - start > 0.01 then
+ elseif bestStart > start then
replace = true
end
end
@@ -504,7 +430,7 @@ local function ComputeGroup(element, atTime)
end
if not bestStart then
- Ovale:Log("group return nil")
+ Ovale:Logf("group return nil [%d]", element.nodeId)
return nil
end
@@ -513,107 +439,83 @@ local function ComputeGroup(element, atTime)
if bestElement.params then
id = bestElement.params[1]
end
- Ovale:Logf("group best action %s remains %s, %s [%d]", id, bestStart, bestEnding, element.nodeId)
+ Ovale:Logf("group best action %s remains %f, %f [%d]", id, bestStart, bestEnding, element.nodeId)
else
- Ovale:Logf("group no best action returns %s, %s [%d]", bestStart, bestEnding, element.nodeId)
+ Ovale:Logf("group no best action returns %f, %f [%d]", bestStart, bestEnding, element.nodeId)
end
return bestStart, bestEnding, bestPriority, bestElement
end
-local function ComputeLua(element, atTime)
- local ret = loadstring(element.lua)()
- Ovale:Logf("lua %s", ret)
- return 0, nil, OVALE_DEFAULT_PRIORITY, PutValue(element, ret, 0, 0)
-end
-
-local function ComputeNot(element, atTime)
+local function ComputeIf(element, atTime)
+ Ovale:Logf("%s [%d]", element.type, element.nodeId)
local self = OvaleBestAction
+
local startA, endA = self:ComputeBool(element.a, atTime)
- --[[
- NOT start < t < ending ==> 0 < t < start OR ending < t < infinity
- NOT start < t < infinity ==> 0 < t < start
- NOT nil ==> 0 < t < infinity
- ]]--
- if startA and endA then
- -- TODO: This is not quite right since we ignore 0 < t < startA.
- return endA, nil
- elseif startA then
- return 0, startA
+ -- "unless A B" is equivalent to "if (not A) B", so take the complement of A.
+ if element.type == "unless" then
+ startA, endA = Complement(startA, endA, atTime)
+ end
+ -- Short-circuit evaluation of left argument to AND.
+ if Measure(startA, endA) == 0 then
+ Ovale:Logf("%s return timespan with measure 0 [%d]", element.type, element.nodeId)
+ return nil
+ end
+
+ local startB, endB, priorityB, elementB = self:Compute(element.b, atTime)
+ -- If the "then" clause is a "wait" node, then only wait if the conditions are true.
+ if elementB and elementB.wait and not HasTime(startA, endA, atTime) then
+ elementB.wait = nil
+ end
+ -- Take intersection of A and B.
+ startB, endB = Intersect(startA, endA, startB, endB)
+ if Measure(startB, endB) == 0 then
+ Ovale:Logf("%s return nil [%d]", element.type, element.nodeId)
else
- return 0, nil
+ Ovale:Logf("%s return %f, %f [%d]", element.type, startB, endB, element.nodeId)
end
+ return startB, endB, priorityB, elementB
end
-local function ComputeOr(element, atTime)
- Ovale:Log(element.type)
+local function ComputeLua(element, atTime)
+ local ret = loadstring(element.lua)()
+ Ovale:Logf("lua %s [%d]", ret, element.nodeId)
+ return 0, math.huge, OVALE_DEFAULT_PRIORITY, PutValue(element, ret, 0, 0)
+end
+
+local function ComputeNot(element, atTime)
+ Ovale:Logf("%s [%d]", element.type, element.nodeId)
local self = OvaleBestAction
local startA, endA = self:ComputeBool(element.a, atTime)
- local startB, endB = self:ComputeBool(element.b, atTime)
-
- if isBefore(endA, atTime) then
- return startB, endB
- elseif isBefore(endB, atTime) then
- return startA, endA
- end
- if isBefore(endA, startB) then
- return startA, endA
- elseif isBefore(endB, startA) then
- return startB, endB
- end
- if isBefore(startA, startB) then
- startB = startA
- end
- if isAfter(endA, endB) then
- endB = endA
- end
- return startB, endB
+ startA, endA = Complement(startA, endA, atTime)
+ Ovale:Logf("%s returns %s, %s [%d]", element.type, startA, endA, element.nodeId)
+ return startA, endA
end
-local function ComputeUnless(element, atTime)
+local function ComputeOr(element, atTime)
Ovale:Logf("%s [%d]", element.type, element.nodeId)
local self = OvaleBestAction
local startA, endA = self:ComputeBool(element.a, atTime)
- local startB, endB, prioriteB, elementB = self:Compute(element.b, atTime)
- -- If the "then" clause is a "wait" node, then only wait if the conditions are false.
- if elementB and elementB.wait and isBetween(atTime, startA, endA) then
- elementB.wait = nil
- end
- -- unless {t: startA < t < endA} then {t: startB < t < endB}
- -- if not {t: startA < t < endA} then {t: startB < t < endB}
- -- if {t: t < startA} or {t: t > endA} then {t: startB < t < endB}
- -- {t: t < startA and startB < t < endB} or {t: startB < t < endB and endA < t}
- if isBeforeEqual(startA, startB) and isAfterEqual(endA, endB) then
- Ovale:Logf("%s return nil [%d]", element.type, element.nodeId)
- return nil
- end
- if isAfterEqual(startA, startB) and isBefore(endA, endB) then
- Ovale:Logf("%s return %s, %s [%d]", element.type, endA, endB, element.nodeId)
- return endA, endB, prioriteB, elementB
- end
- if isAfter(startA, startB) and isBefore(startA, endB) then
- endB = startA
- end
- if isAfter(endA, startB) and isBefore(endA, endB) then
- startB = endA
- end
- Ovale:Logf("%s return %s, %s [%d]", element.type, startB, endB, element.nodeId)
- return startB, endB, prioriteB, elementB
+ local startB, endB = self:ComputeBool(element.b, atTime)
+ -- Take union of (startA, endA) and (startB, endB)
+ startA, endA = Union(startA, endA, startB, endB)
+ Ovale:Logf("%s returns %s, %s [%d]", element.type, startA, endA, element.nodeId)
+ return startA, endA
end
local function ComputeValue(element, atTime)
Ovale:Logf("value %s", element.value)
- return 0, nil, OVALE_DEFAULT_PRIORITY, element
+ return 0, math.huge, OVALE_DEFAULT_PRIORITY, element
end
local function ComputeWait(element, atTime)
Ovale:Logf("%s [%d]", element.type, element.nodeId)
local self = OvaleBestAction
- local startA, endA, prioriteA, elementA = self:Compute(element.a, atTime)
+ local startA, endA, priorityA, elementA = self:Compute(element.a, atTime)
if elementA then
elementA.wait = true
- Ovale:Logf("%s return %s, %s [%d]", element.type, startA, endA, element.nodeId)
+ Ovale:Logf("%s return %f, %f [%d]", element.type, startA, endA, element.nodeId)
end
- return startA, endA, prioriteA, elementA
+ return startA, endA, priorityA, elementA
end
--</private-static-methods>
@@ -626,11 +528,11 @@ local OVALE_COMPUTE_VISITOR =
["customfunction"] = ComputeCustomFunction,
["function"] = ComputeFunction,
["group"] = ComputeGroup,
- ["if"] = ComputeAnd,
+ ["if"] = ComputeIf,
["lua"] = ComputeLua,
["not"] = ComputeNot,
["or"] = ComputeOr,
- ["unless"] = ComputeUnless,
+ ["unless"] = ComputeIf,
["value"] = ComputeValue,
["wait"] = ComputeWait,
}
@@ -649,16 +551,12 @@ function OvaleBestAction:GetActionInfo(element)
end
local spellId = element.params[1]
+ local target = element.params.target or OvaleCondition.defaultTarget
local action
local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration,
actionUsable, actionShortcut, actionIsCurrent, actionEnable
- local target = element.params.target
- if (not target) then
- target = OvaleCondition.defaultTarget
- end
-
- if (element.func == "spell" ) then
+ if (element.func == "spell") then
action = OvaleActionBar:GetForSpell(spellId)
if not OvaleSpellBook:IsKnownSpell(spellId) and not action then
Ovale:Logf("Spell %s not learnt", spellId)
@@ -774,7 +672,7 @@ function OvaleBestAction:ComputeBool(element, atTime)
if element and element.type == "value" and element.value == 0 and element.rate == 0 then
return nil
else
- return start, ending, priority, element
+ return start, ending
end
end
--</public-static-methods>
diff --git a/OvaleCondition.lua b/OvaleCondition.lua
index e0535cd..471841c 100644
--- a/OvaleCondition.lua
+++ b/OvaleCondition.lua
@@ -138,47 +138,24 @@ local function TimeWithHaste(time1, haste)
end
end
--- Return time1 + duration.
-local function AddToTime(time1, duration)
- if not time1 or not duration then
- -- time1 or duration is infinite.
- return nil
- else
- return time1 + duration
- end
-end
-
--- Return time2 - time1
-local function DiffTime(time1, time2)
- if not time1 then
- -- time1 is infinite, so return the lowest possible time (zero).
- return 0
- elseif not time2 then
- -- time2 is infinite.
- return nil
- else
- return time2 - time1
- end
-end
-
local function Compare(a, comparison, b)
if not comparison then
- return 0, nil, a, 0, 0 -- this is not a compare, returns the value a
+ return 0, math.huge, a, 0, 0 -- this is not a compare, returns the value a
elseif comparison == "more" then
- if (not b or (a~=nil and a>b)) then
- return 0
+ if not b or (a and a > b) then
+ return 0, math.huge
else
return nil
end
elseif comparison == "equal" then
if b == a then
- return 0
+ return 0, math.huge
else
return nil
end
elseif comparison == "less" then
- if (not a or (b~=nil and a<b)) then
- return 0
+ if not a or (b and a < b) then
+ return 0, math.huge
else
return nil
end
@@ -188,15 +165,15 @@ local function Compare(a, comparison, b)
end
local function TestBoolean(a, condition)
- if (condition == "yes" or not condition) then
- if (a) then
- return 0
+ if condition == "yes" or not condition then
+ if a then
+ return 0, math.huge
else
return nil
end
else
- if (not a) then
- return 0
+ if not a then
+ return 0, math.huge
else
return nil
end
@@ -207,25 +184,22 @@ local function TestValue(comparator, limit, value, atTime, rate)
if not value or not atTime then
return nil
elseif not comparator then
- return 0, nil, value, atTime, rate
+ return 0, math.huge, value, atTime, rate
else
- if rate == 0 then
- if comparator == "more" then
- if value > limit then return 0 else return nil end
- elseif comparator == "less" then
- if value < limit then return 0 else return nil end
- else
- Ovale:Errorf("Unknown operator %s", comparator)
- return nil
- end
+ local start, ending = 0, math.huge
+ if comparator == "more" and rate == 0 then
+ if value <= limit then return nil end
+ elseif comparator == "less" and rate == 0 then
+ if value >= limit then return nil end
elseif (comparator == "more" and rate > 0) or (comparator == "less" and rate < 0) then
- return (limit - value) / rate + atTime
+ start = (limit - value)/rate + atTime
elseif (comparator == "more" and rate < 0) or (comparator == "less" and rate > 0) then
- return 0, (limit - value) / rate + atTime
+ ending = (limit - value)/rate + atTime
else
Ovale:Errorf("Unknown operator %s", comparator)
return nil
end
+ return start, ending
end
end
@@ -471,18 +445,16 @@ OvaleCondition.defaultTarget = "target"
or operations.
The endpoint of a time interval must be between 0 and infinity, where
- infinity is represented by "nil". Time is a value such as returned by
+ infinity is represented by math.huge. Time is a value such as returned by
the API function GetTime().
Examples:
- (1) (0, nil) means the condition is always true. This can be shortened
- to just return 0.
+ (1) (0, math.huge) means the condition is always true.
- (2) (nil, nil) means the condition is always false. This can be shortened
- to just return nil.
+ (2) nil is the empty set and means the condition is always false.
- (3) (0, nil, constant, 0, 0) means the condition has a constant value.
+ (3) (0, math.huge, constant, 0, 0) means the condition has a constant value.
(4) (start, ending, ending - start, start, -1) means the condition has a
value of f(t) = ending - t, at time t between start and ending. This
@@ -569,7 +541,7 @@ OvaleCondition.conditions.buffattackpower = function(condition)
if start and ending and start <= ending then
return start, ending, attackPower, start, 0
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.debuffattackpower = OvaleCondition.conditions.buffattackpower
@@ -594,7 +566,7 @@ OvaleCondition.conditions.buffrangedattackpower = function(condition)
if start and ending and start <= ending then
return start, ending, rangedAttackPower, start, 0
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.debuffrangedattackpower = OvaleCondition.conditions.buffrangedattackpower
@@ -618,7 +590,7 @@ OvaleCondition.conditions.buffcombopoints = function(condition)
if start and ending and start <= ending then
return start, ending, comboPoints, start, 0
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.debuffcombopoints = OvaleCondition.conditions.buffcombopoints
@@ -644,7 +616,7 @@ OvaleCondition.conditions.buffdamagemultiplier = function(condition)
if start and ending and start <= ending then
return start, ending, baseDamageMultiplier * damageMultiplier, start, 0
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.debuffdamagemultiplier = OvaleCondition.conditions.buffdamagemultiplier
@@ -674,7 +646,7 @@ OvaleCondition.conditions.buffmeleecritchance = function(condition)
if start and ending and start <= ending then
return start, ending, critChance, start, 0
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.debuffmeleecritchance = OvaleCondition.conditions.buffmeleecritchance
@@ -705,7 +677,7 @@ OvaleCondition.conditions.buffrangedcritchance = function(condition)
if start and ending and start <= ending then
return start, ending, critChance, start, 0
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.debuffrangedcritchance = OvaleCondition.conditions.buffrangedcritchance
@@ -735,7 +707,7 @@ OvaleCondition.conditions.buffspellcritchance = function(condition)
if start and ending and start <= ending then
return start, ending, critChance, start, 0
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.debuffspellcritchance = OvaleCondition.conditions.buffspellcritchance
@@ -759,7 +731,7 @@ OvaleCondition.conditions.buffmastery = function(condition)
if start and ending and start <= ending then
return start, ending, masteryEffect, start, 0
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.debuffmastery = OvaleCondition.conditions.buffmastery
@@ -783,7 +755,7 @@ OvaleCondition.conditions.buffspellpower = function(condition)
if start and ending and start <= ending then
return start, ending, spellBonusDamage, start, 0
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.debuffspellpower = OvaleCondition.conditions.buffspellpower
@@ -807,7 +779,7 @@ OvaleCondition.conditions.buffspellhaste = function(condition)
if start and ending and start <= ending then
return start, ending, spellHaste, start, 0
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.debuffspellhaste = OvaleCondition.conditions.buffspellhaste
@@ -856,7 +828,8 @@ OvaleCondition.conditions.debuffcount = OvaleCondition.conditions.buffcount
OvaleCondition.conditions.buffduration = function(condition)
local start, ending = GetAura(condition)
start = start or 0
- return Compare(DiffTime(start, ending), condition[2], condition[3])
+ ending = ending or math.huge
+ return Compare(ending - start, condition[2], condition[3])
end
OvaleCondition.conditions.debuffduration = OvaleCondition.conditions.buffduration
@@ -887,10 +860,10 @@ OvaleCondition.conditions.buffexpires = function(condition)
local start, ending = GetAura(condition)
local timeBefore = TimeWithHaste(condition[2], condition.haste)
if not start then
- ending = 0
+ return 0, math.huge
end
Ovale:Logf("timeBefore = %s, ending = %s", timeBefore, ending)
- return AddToTime(ending, -timeBefore)
+ return ending - timeBefore, math.huge
end
OvaleCondition.conditions.debuffexpires = OvaleCondition.conditions.buffexpires
@@ -915,7 +888,7 @@ OvaleCondition.conditions.buffremains = function(condition)
if start and ending and start <= ending then
return start, ending, ending - start, start, -1
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.debuffremains = OvaleCondition.conditions.buffremains
@@ -929,7 +902,7 @@ OvaleCondition.conditions.buffgain = function(condition)
Ovale:Error("not implemented")
if true then return nil end
local gain = select(4, GetAura(condition)) or 0
- return 0, nil, 0, 0, 1
+ return 0, math.huge, 0, 0, 1
end
OvaleCondition.conditions.debuffgain = OvaleCondition.conditions.buffgain
@@ -962,7 +935,7 @@ OvaleCondition.conditions.buffpresent = function(condition)
return nil
end
local timeBefore = TimeWithHaste(condition[2], condition.haste)
- return start, AddToTime(ending, -timeBefore)
+ return start, ending - timeBefore
end
OvaleCondition.conditions.debuffpresent = OvaleCondition.conditions.buffpresent
@@ -987,6 +960,7 @@ OvaleCondition.conditions.debuffpresent = OvaleCondition.conditions.buffpresent
OvaleCondition.conditions.buffstacks = function(condition)
local start, ending, stacks = GetAura(condition)
start = start or 0
+ ending = ending or math.huge
stacks = stacks or 0
return start, ending, stacks, 0, 0
end
@@ -1023,22 +997,16 @@ OvaleCondition.conditions.burningembers = function(condition)
return TestValue(condition[1], condition[2], OvaleState.state.burningembers, OvaleState.currentTime, OvaleState.powerRate.burningembers)
end
- -- Check if the player can cast (cooldown is down)
- -- 1: spellId
- -- returns: bool
+--- Check if the player can cast the given spell (not on cooldown).
+-- @name CanCast
+-- @paramsig boolean
+-- @param id The spell ID to check.
+-- @return True if the spell cast be cast; otherwise, false.
+
OvaleCondition.conditions.cancast = function(condition)
local spellId = condition[1]
local actionCooldownStart, actionCooldownDuration = OvaleState:GetComputedSpellCD(spellId)
- local startCast = actionCooldownStart + actionCooldownDuration
- if startCast < OvaleState.currentTime then
- startCast = OvaleState.currentTime
- end
- --TODO why + castTime?
- local castTime
- if spellId then
- castTime = select(7, API_GetSpellInfo(spellId))
- end
- return startCast + castTime/1000
+ return actionCooldownStart + actionCooldownDuration, math.huge
end
--- Test if the target is casting the given spell.
@@ -1171,7 +1139,7 @@ OvaleCondition.conditions.checkboxoff = function(condition)
return nil
end
end
- return 0
+ return 0, math.huge
end
--- Test if all of the listed checkboxes are on.
@@ -1191,7 +1159,7 @@ OvaleCondition.conditions.checkboxon = function(condition)
return nil
end
end
- return 0
+ return 0, math.huge
end
--- Get the current amount of stored Chi for monks.
@@ -1225,8 +1193,8 @@ end
-- if target.Class(PRIEST) Spell(cheap_shot)
OvaleCondition.conditions.class = function(condition)
- local loc, noloc = API_UnitClass(GetTarget(condition))
- return TestBoolean(noloc == condition[1], condition[2])
+ local class, classToken = API_UnitClass(GetTarget(condition))
+ return TestBoolean(classToken == condition[1], condition[2])
end
--- Test whether the target's classification matches the given classification.
@@ -1247,17 +1215,17 @@ end
OvaleCondition.conditions.classification = function(condition)
local classification
local target = GetTarget(condition)
- if API_UnitLevel(target) == -1 then
+ if API_UnitLevel(target) < 0 then
classification = "worldboss"
else
- classification = API_UnitClassification(target);
- if (classification == "rareelite") then
+ classification = API_UnitClassification(target)
+ if classification == "rareelite" then
classification = "elite"
- elseif (classification == "rare") then
+ elseif classification == "rare" then
classification = "normal"
end
end
- return TestBoolean(condition[1]==classification, condition[2])
+ return TestBoolean(classification == condition[1], condition[2])
end
--- Get the number of combo points on the currently selected target for a feral druid or a rogue.
@@ -1311,7 +1279,8 @@ end
-- Spell(hibernate)
OvaleCondition.conditions.creaturefamily = function(condition)
- return TestBoolean(API_UnitCreatureFamily(GetTarget(condition)) == LBCT[condition[1]], condition[2])
+ local family = API_UnitCreatureFamily(GetTarget(condition))
+ return TestBoolean(family == LBCT[condition[1]], condition[2])
end
--- Test if the target is any of the listed creature types.
@@ -1330,9 +1299,9 @@ end
OvaleCondition.conditions.creaturetype = function(condition)
local creatureType = API_UnitCreatureType(GetTarget(condition))
- for _,v in pairs(condition) do
- if (creatureType == LBCT[v]) then
- return 0
+ for _, v in pairs(condition) do
+ if creatureType == LBCT[v] then
+ return 0, math.huge
end
end
return nil
@@ -1352,7 +1321,7 @@ OvaleCondition.conditions.critdamage = function(condition)
-- TODO: Need to account for increased crit effect from meta-gems.
local critFactor = 2
local start, ending, value, origin, rate = OvaleCondition.conditions.damage(condition)
- return start, ending, critFactor * value, critFactor * origin, critFactor * rate
+ return start, ending, critFactor * value, origin, critFactor * rate
end
--- Get the current estimated damage of a spell on the target.
@@ -1377,7 +1346,7 @@ OvaleCondition.conditions.damage = function(condition)
local spellId = condition[1]
local value, origin, rate = ComputeFunctionParam(spellId, "damage")
if value then
- return 0, nil, value, origin, rate
+ return 0, math.huge, value, origin, rate
else
local ap = OvalePaperDoll.stat.attackPower
local sp = OvalePaperDoll.stat.spellBonusDamage
@@ -1385,7 +1354,7 @@ OvaleCondition.conditions.damage = function(condition)
local oh = OvalePaperDoll.stat.offHandWeaponDamage
local bdm = OvalePaperDoll.stat.baseDamageMultiplier
local dm = OvaleState:GetDamageMultiplier(spellId)
- return 0, nil, OvaleData:GetDamage(spellId, ap, sp, mh, oh, combo) * bdm * dm, 0, 0
+ return 0, math.huge, OvaleData:GetDamage(spellId, ap, sp, mh, oh, combo) * bdm * dm, 0, 0
end
end
@@ -1404,7 +1373,7 @@ OvaleCondition.conditions.damagemultiplier = function(condition)
local spellId = condition[1]
local bdm = OvalePaperDoll.stat.baseDamageMultiplier
local dm = OvaleState:GetDamageMultiplier(spellId)
- return 0, nil, bdm * dm, 0, 0
+ return 0, math.huge, bdm * dm, 0, 0
end
--- Get the damage taken by the player in the previous time interval.
@@ -1424,7 +1393,7 @@ OvaleCondition.conditions.damagetaken = function(condition)
if interval > 0 then
damage = OvaleDamageTaken:GetRecentDamage(interval)
end
- return 0, nil, damage, 0, 0
+ return 0, math.huge, damage, 0, 0
end
OvaleCondition.conditions.incomingdamage = OvaleCondition.conditions.damagetaken
@@ -1867,7 +1836,7 @@ end
OvaleCondition.conditions.itemcooldown = function(condition)
local actionCooldownStart, actionCooldownDuration, actionEnable = API_GetItemCooldown(condition[1])
- return 0, nil, actionCooldownDuration, actionCooldownStart, -1
+ return 0, math.huge, actionCooldownDuration, actionCooldownStart, -1
end
--- Get the current number of the given item in the player's inventory.
@@ -2085,7 +2054,7 @@ OvaleCondition.conditions.lastestimateddamage = function(condition)
local combo = OvaleFuture:GetLastSpellInfo(guid, spellId, "comboPoints") or 1
local bdm = OvaleFuture:GetLastSpellInfo(guid, spellId, "baseDamageMultiplier") or 1
local dm = OvaleFuture:GetLastSpellInfo(guid, spellId, "damageMultiplier") or 1
- return 0, nil, OvaleData:GetDamage(spellId, ap, sp, mh, oh, combo) * bdm * dm, 0, 0
+ return 0, math.huge, OvaleData:GetDamage(spellId, ap, sp, mh, oh, combo) * bdm * dm, 0, 0
end
OvaleCondition.conditions.lastspellestimateddamage = OvaleCondition.conditions.lastestimateddamage
@@ -2305,7 +2274,7 @@ OvaleCondition.conditions.lastspellrangedcritchance = OvaleCondition.conditions.
-- @see NextSwing
OvaleCondition.conditions.lastswing = function(condition)
- return 0, nil, 0, OvaleSwing:GetLast(condition[1]), 1
+ return 0, math.huge, 0, OvaleSwing:GetLast(condition[1]), 1
end
--- Get the most recent estimate of roundtrip latency in milliseconds.
@@ -2320,7 +2289,7 @@ end
-- if Latency(more 1000) Spell(sinister_strike)
OvaleCondition.conditions.latency = function(condition)
- return 0, nil, OvaleLatency:GetLatency() * 1000, 0, 0
+ return 0, math.huge, OvaleLatency:GetLatency() * 1000, 0, 0
end
--- Get the level of the target.
@@ -2358,9 +2327,9 @@ end
-- if List(opt_curse coe) Spell(curse_of_the_elements)
OvaleCondition.conditions.list = function(condition)
- if (condition[1]) then
- if (Ovale:GetListValue(condition[1]) == condition[2]) then
- return 0
+ if condition[1] then
+ if Ovale:GetListValue(condition[1]) == condition[2] then
+ return 0, math.huge
end
end
return nil
@@ -2692,7 +2661,7 @@ end
-- @see LastSwing
OvaleCondition.conditions.nextswing = function(condition)
- return 0, nil, 0, OvaleSwing:GetNext(condition[1]), 0, -1
+ return 0, math.huge, OvaleSwing:GetNext(condition[1]), 0, -1
end
--- Get the number of seconds until the next tick of a periodic aura on the target.
@@ -2716,7 +2685,7 @@ OvaleCondition.conditions.nexttick = function(condition)
while ending - tick > OvaleState.currentTime do
ending = ending - tick
end
- return 0, nil, 0, ending, -1
+ return 0, math.huge, 0, ending, -1
end
return nil
end
@@ -2740,10 +2709,10 @@ OvaleCondition.conditions.otherdebuffexpires = function(condition)
local start, ending = GetAuraOnAnyTarget(condition, "target")
local timeBefore = TimeWithHaste(condition[2], condition.haste)
if not start then
- ending = 0
+ return nil
end
Ovale:Logf("timeBefore = %s, ending = %s", timeBefore, ending)
- return AddToTime(ending, -timeBefore)
+ return ending - timeBefore, math.huge
end
OvaleCondition.conditions.otherbuffexpires = OvaleCondition.conditions.otherdebuffexpires
@@ -2768,7 +2737,7 @@ OvaleCondition.conditions.otherdebuffpresent = function(condition)
return nil
end
local timeBefore = TimeWithHaste(condition[2], condition.haste)
- return start, AddToTime(ending, -timeBefore)
+ return start, ending - timeBefore
end
OvaleCondition.conditions.otherbuffpresent = OvaleCondition.conditions.otherdebuffpresent
@@ -2790,7 +2759,7 @@ OvaleCondition.conditions.otherdebuffremains = function(condition)
if start and ending and start <= ending then
return start, ending, ending - start, start, -1
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.otherbuffremains = OvaleCondition.conditions.otherdebuffremains
@@ -2807,7 +2776,7 @@ OvaleCondition.conditions.otherbuffremains = OvaleCondition.conditions.otherdebu
OvaleCondition.conditions.powercost = function(condition)
local cost = select(4, API_GetSpellInfo(condition[1])) or 0
- return 0, nil, cost, 0, 0
+ return 0, math.huge, cost, 0, 0
end
OvaleCondition.conditions.energycost = OvaleCondition.conditions.powercost
OvaleCondition.conditions.focuscost = OvaleCondition.conditions.powercost
@@ -2966,7 +2935,7 @@ OvaleCondition.conditions.remainingcasttime = function(condition)
if not endTime then
return nil
end
- return 0, nil, 0, endTime/1000, -1
+ return 0, math.huge, 0, endTime/1000, -1
end
--- Test if the current rune count meets the minimum rune requirements set out in the parameters.
@@ -3003,7 +2972,7 @@ end
-- Spell(obliterate)
OvaleCondition.conditions.runecount = function(condition)
- return 0, nil, GetRuneCount(condition[1], condition.death)
+ return 0, math.huge, GetRuneCount(condition[1], condition.death)
end
--- Get the number of seconds before the rune conditions are met.
@@ -3031,7 +3000,7 @@ OvaleCondition.conditions.runescooldown = function(condition)
if ret < OvaleState.maintenant then
ret = OvaleState.maintenant
end
- return 0, nil, 0, ret, -1
+ return 0, math.huge, 0, ret, -1
end
--- Get the current amount of runic power for death knights.
@@ -3194,9 +3163,9 @@ OvaleCondition.spellbookConditions.spellcharges = true
OvaleCondition.conditions.spellchargecooldown = function(condition)
local charges, maxCharges, cooldownStart, cooldownDuration = API_GetSpellCharges(condition[1])
if charges < maxCharges then
- return 0, nil, cooldownDuration, cooldownStart, -1
+ return 0, math.huge, cooldownDuration, cooldownStart, -1
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.spellbookConditions.spellchargecooldown = true
@@ -3215,15 +3184,15 @@ OvaleCondition.conditions.spellcooldown = function(condition)
if type(spellId) == "string" then
local sharedCd = OvaleState.state.cd[spellId]
if sharedCd then
- return 0, nil, sharedCd.duration, sharedCd.start, -1
+ return 0, math.huge, sharedCd.duration, sharedCd.start, -1
else
return nil
end
elseif not OvaleSpellBook:IsKnownSpell(spellId) then
- return 0, nil, 0, OvaleState.currentTime + 3600, -1
+ return 0, math.huge, 0, OvaleState.currentTime + 3600, -1
else
local actionCooldownStart, actionCooldownDuration, actionEnable = OvaleState:GetComputedSpellCD(spellId)
- return 0, nil, actionCooldownDuration, actionCooldownStart, -1
+ return 0, math.huge, actionCooldownDuration, actionCooldownStart, -1
end
end
-- OvaleCondition.spellbookConditions.spellcooldown = true / may be a sharedcd
@@ -3244,7 +3213,7 @@ OvaleCondition.conditions.spelldata = function(condition)
if si then
local ret = si[condition[2]]
if ret then
- return 0, nil, ret, 0, 0
+ return 0, math.huge, ret, 0, 0
end
end
return nil
@@ -3293,7 +3262,7 @@ OvaleCondition.conditions.staggerremains = function(condition)
local stagger = API_UnitStagger(target)
return start, ending, 0, ending, -1 * stagger / (ending - start)
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
@@ -3307,7 +3276,7 @@ end
OvaleCondition.conditions.stance = function(condition)
if OvaleStance:IsStance(condition[1]) then
- return 0
+ return 0, math.huge
else
return nil
end
@@ -3448,7 +3417,7 @@ end
-- @return The number of added ticks.
OvaleCondition.conditions.ticksadded = function(condition)
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
--- Get the remaining number of ticks of a periodic aura on a target.
@@ -3472,9 +3441,9 @@ OvaleCondition.conditions.ticksremain = function(condition)
local start, ending = GetAura(condition, self_auraFound)
local tick = self_auraFound.tick
if ending and tick and tick > 0 then
- return 0, nil, 1, ending, -1/tick
+ return 0, math.huge, 1, ending, -1/tick
end
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
--- Get the number of seconds between ticks of a periodic aura on a target.
@@ -3534,7 +3503,7 @@ end
OvaleCondition.conditions.timetodie = function(condition)
local timeToDie = TimeToDie(GetTarget(condition))
- return 0, nil, timeToDie, OvaleState.maintenant, -1
+ return 0, math.huge, timeToDie, OvaleState.maintenant, -1
end
OvaleCondition.conditions.deadin = OvaleCondition.conditions.timetodie
@@ -3556,9 +3525,9 @@ OvaleCondition.conditions.timetohealthpercent = function(condition)
local healthPercent = health / maxHealth * 100
if healthPercent >= percent then
local t = timeToDie * (healthPercent - percent) / healthPercent
- return 0, nil, t, OvaleState.maintenant, -1
+ return 0, math.huge, t, OvaleState.maintenant, -1
end
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
OvaleCondition.conditions.timetolifepercent = OvaleCondition.conditions.timetohealthpercent
@@ -3578,12 +3547,12 @@ OvaleCondition.conditions.timetopowerfor = function(condition)
if currentPower < cost then
if powerRate > 0 then
local t = OvaleState.currentTime + (cost - currentPower) / powerRate
- return 0, nil, 0, t, -1
+ return 0, math.huge, 0, t, -1
else
- return 0, nil, OvaleState.currentTime + 3600, 0, 0
+ return 0, math.huge, OvaleState.currentTime + 3600, 0, 0
end
else
- return 0, nil, 0, 0, 0
+ return 0, math.huge, 0, 0, 0
end
end
OvaleCondition.conditions.timetoenergyfor = OvaleCondition.conditions.timetopowerfor
@@ -3603,7 +3572,7 @@ OvaleCondition.spellbookConditions.timetopowerfor = true
OvaleCondition.conditions.timetomaxenergy = function(condition)
local maxEnergy = OvalePower.maxPower.energy or 0
local t = OvaleState.currentTime + (maxEnergy - OvaleState.state.energy) / OvaleState.powerRate.energy
- return 0, nil, 0, t, -1
+ return 0, math.huge, 0, t, -1
end
--- Get the time scaled by the specified haste type, defaulting to spell haste.
@@ -3621,7 +3590,7 @@ end
OvaleCondition.conditions.timewithhaste = function(condition)
haste = condition.haste or "spell"
- return 0, nil, TimeWithHaste(condition[1], haste), 0, 0
+ return 0, math.huge, TimeWithHaste(condition[1], haste), 0, 0
end
--- Test if the totem for shamans, the ghoul for death knights, or the statue for monks has expired.
@@ -3640,18 +3609,19 @@ end
-- if TotemPresent(water totem=healing_stream_totem) and TotemExpires(water 3) Spell(totemic_recall)
OvaleCondition.conditions.totemexpires = function(condition)
- if type(condition[1]) ~= "number" then
- condition[1] = OVALE_TOTEMTYPE[condition[1]]
+ local totemId = condition[1]
+ local seconds = condition[2] or 0
+ if type(totemId) ~= "number" then
+ totemId = OVALE_TOTEMTYPE[totemId]
end
-
- local haveTotem, totemName, startTime, duration = API_GetTotemInfo(condition[1])
+ local haveTotem, totemName, startTime, duration = API_GetTotemInfo(totemId)
if not startTime then
- return 0
+ return 0, math.huge
end
if condition.totem and OvaleSpellBook:GetSpellName(condition.totem) ~= totemName then
- return 0
+ return 0, math.huge
end
- return AddToTime(startTime + duration, -(condition[2] or 0))
+ return startTime + duration - seconds, math.huge
end
--- Test if the totem for shamans, the ghoul for death knights, or the statue for monks is present.
@@ -3668,11 +3638,11 @@ end
-- if TotemPresent(water totem=healing_stream_totem) and TotemExpires(water 3) Spell(totemic_recall)
OvaleCondition.conditions.totempresent = function(condition)
- if type(condition[1]) ~= "number" then
- condition[1] = OVALE_TOTEMTYPE[condition[1]]
+ local totemId = condition[1]
+ if type(totemId) ~= "number" then
+ totemId = OVALE_TOTEMTYPE[totemId]
end
-
- local haveTotem, totemName, startTime, duration = API_GetTotemInfo(condition[1])
+ local haveTotem, totemName, startTime, duration = API_GetTotemInfo(totemId)
if not startTime then
return nil
end
@@ -3705,7 +3675,7 @@ end
-- @return A boolean value.
OvaleCondition.conditions["true"] = function(condition)
- return 0, nil
+ return TestBoolean(true)
end
--- Test if the weapon imbue on the given weapon has expired or will expire after a given number of seconds.
@@ -3723,23 +3693,23 @@ OvaleCondition.conditions.weaponenchantexpires = function(condition)
local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = API_GetWeaponEnchantInfo()
if (condition[1] == "mainhand") then
if (not hasMainHandEnchant) then
- return 0
+ return 0, math.huge
end
mainHandExpiration = mainHandExpiration/1000
if ((condition[2] or 0) >= mainHandExpiration) then
- return 0
+ return 0, math.huge
else
- return OvaleState.maintenant + mainHandExpiration - (condition[2] or 60)
+ return OvaleState.maintenant + mainHandExpiration - (condition[2] or 60), math.huge
end
else
if (not hasOffHandEnchant) then
- return 0
+ return 0, math.huge
end
offHandExpiration = offHandExpiration/1000
if ((condition[2] or 0) >= offHandExpiration) then
- return 0
+ return 0, math.huge
else
- return OvaleState.maintenant + offHandExpiration - (condition[2] or 60)
+ return OvaleState.maintenant + offHandExpiration - (condition[2] or 60), math.huge
end
end
end
@@ -3764,6 +3734,6 @@ OvaleCondition.conditions.weapondamage = function(condition)
else -- if hand == "mainhand" or hand == "main" then
damage = OvalePaperDoll.stat.mainHandWeaponDamage
end
- return 0, nil, damage, 0, 0
+ return 0, math.huge, damage, 0, 0
end
--</public-static-properties>
diff --git a/OvaleTimeSpan.lua b/OvaleTimeSpan.lua
new file mode 100644
index 0000000..acb1e19
--- /dev/null
+++ b/OvaleTimeSpan.lua
@@ -0,0 +1,96 @@
+--[[--------------------------------------------------------------------
+ Ovale Spell Priority
+ Copyright (C) 2013 Johnny C. Lam
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License in the LICENSE
+ file accompanying this program.
+--]]--------------------------------------------------------------------
+
+--[[
+ Time spans are continuous open intervals (start, ending) that are subsets of (0, infinity).
+
+ Infinity is represented by math.huge.
+ Point sets are considered empty.
+ "nil" time spans are considered empty.
+--]]
+
+local _, Ovale = ...
+local OvaleTimeSpan = {}
+Ovale.OvaleTimeSpan = OvaleTimeSpan
+
+--<public-static-methods>
+function OvaleTimeSpan.Complement(startA, endA, atTime)
+ -- The complement of an interval is actually the union of two intervals.
+ -- If the point of interest (atTime) lies in the left interval, then return it.
+ -- Otherwise, return the right interval.
+ if not startA or not endA then
+ return 0, math.huge
+ elseif 0 < startA and atTime <= startA then
+ return 0, startA
+ else
+ return endA, math.huge
+ end
+end
+
+function OvaleTimeSpan.HasTime(start, ending, atTime)
+ if not start or not ending then
+ return nil
+ else
+ return start <= atTime and atTime <= ending
+ end
+end
+
+function OvaleTimeSpan.Intersect(startA, endA, startB, endB)
+ -- If either (startA, endA) or (startB, endB) are the empty set, then return the empty set.
+ if not startA or not endA or not startB or not endB then
+ return nil
+ end
+ -- If the two time spans don't overlap, then return the empty set.
+ if endB <= startA or endA <= startB then
+ return nil
+ end
+ -- Take the rightmost left endpoint.
+ if startA < startB then
+ startA = startB
+ end
+ -- Take the leftmost right endpoint.
+ if endA > endB then
+ endA = endB
+ end
+ -- Sanity check that it's a valid time span, otherwise, return the empty set.
+ if startA >= endA then
+ return nil
+ end
+ return startA, endA
+end
+
+function OvaleTimeSpan.Measure(startA, endA)
+ if not startA or not endA then
+ return 0
+ elseif startA >= endA then
+ return 0
+ else
+ return endA - startA
+ end
+end
+
+function OvaleTimeSpan.Union(startA, endA, startB, endB)
+ -- TODO: this assumes that (startA, endA) and (startB, endB) overlap.
+ -- If either (startA, endA) or (startB, endB) are the empty set, then return the other time span.
+ if not startA or not endA then
+ return startB, endB
+ elseif not startB or not endB then
+ return startA, endA
+ end
+ -- Take the leftmost left endpoint.
+ if startA > startB then
+ startA = startB
+ end
+ -- Take the rightmost right endpoint.
+ if endA < endB then
+ endA = endB
+ end
+ return startA, endA
+end
+--</public-static-methods>
diff --git a/compiler.pl b/compiler.pl
index f843410..23315b3 100644
--- a/compiler.pl
+++ b/compiler.pl
@@ -98,6 +98,7 @@ $sp{Ovale}{OvalePool} = true;
$sp{Ovale}{OvalePoolGC} = true;
$sp{Ovale}{OvaleSkada} = true;
$sp{Ovale}{OvaleState} = true;
+$sp{Ovale}{OvaleTimeSpan} = true;
$sp{OvaleQueue}{Front} = true;
$sp{OvaleQueue}{FrontToBackIterator} = true;
@@ -106,6 +107,12 @@ $sp{OvaleQueue}{InsertFront} = true;
$sp{OvaleQueue}{NewDeque} = true;
$sp{OvaleQueue}{RemoveFront} = true;
+$sp{OvaleTimeSpan}{Complement} = true;
+$sp{OvaleTimeSpan}{HasTime} = true;
+$sp{OvaleTimeSpan}{Intersect} = true;
+$sp{OvaleTimeSpan}{Measure} = true;
+$sp{OvaleTimeSpan}{Union} = true;
+
opendir(DIR, ".");
while (defined($r = readdir(DIR)))
{