forked from Sidoine/Ovale
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Condition.lua
256 lines (215 loc) · 7.78 KB
/
Condition.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
--[[--------------------------------------------------------------------
Copyright (C) 2012, 2013 Sidoine De Wispelaere.
Copyright (C) 2012, 2013, 2014, 2015 Johnny C. Lam.
See the file LICENSE.txt for copying permission.
--]]--------------------------------------------------------------------
--[[----------------------------------------------------------------------------
Script conditions.
A script condition must have a name that is lowercase.
A script condition can return in two different ways:
(1) start, ending
This returns a time interval representing when the condition is true
and is used by conditions that return only a time interval.
(2) start, ending, value, origin, rate
This returns a function f(t) = value + (t - origin) * rate that is
valid for start < t < ending. This return method is used by
conditions that return a value that is used in numerical comparisons
or operations.
The endpoint of a time interval must be between 0 and infinity, where
infinity is represented by INFINITY (math.huge). Time is a value such as
returned by the API function GetTime().
Examples:
(1) (0, INFINITY) means the condition is always true.
(2) nil is the empty set and means the condition is always false.
(3) (0, INFINITY, 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
basically returns how much time is left within the time interval.
--]]----------------------------------------------------------------------------
local OVALE, Ovale = ...
local OvaleCondition = Ovale:NewModule("OvaleCondition")
Ovale.OvaleCondition = OvaleCondition
--<private-static-properties>
-- Forward declarations for module dependencies.
local OvaleState = nil
local type = type
local wipe = wipe
local INFINITY = math.huge
-- Table of script conditions.
local self_condition = {}
-- List of script conditions that refer to a castable spell from the player's spellbook.
local self_spellBookCondition = {}
do
-- Spell(spellId) can be used as a condition instead of an action.
self_spellBookCondition["spell"] = true
end
--</private-static-properties>
--<public-static-properties>
OvaleCondition.Compare = nil
OvaleCondition.ParseCondition = nil
OvaleCondition.ParseRuneCondition = nil
OvaleCondition.TestBoolean = nil
OvaleCondition.TestValue = nil
OvaleCondition.COMPARATOR = {
atLeast = true,
atMost = true,
equal = true,
less = true,
more = true,
}
--</public-static-properties>
--<public-static-methods>
function OvaleCondition:OnInitialize()
-- Resolve module dependencies.
OvaleState = Ovale.OvaleState
end
function OvaleCondition:OnEnable()
OvaleState:RegisterState(self, self.statePrototype)
end
function OvaleCondition:OnDisable()
OvaleState:UnregisterState(self)
end
function OvaleCondition:RegisterCondition(name, isSpellBookCondition, func, arg)
if arg then
if type(func) == "string" then
func = arg[func]
end
self_condition[name] = function(...) func(arg, ...) end
else
self_condition[name] = func
end
if isSpellBookCondition then
self_spellBookCondition[name] = true
end
end
function OvaleCondition:UnregisterCondition(name)
self_condition[name] = nil
end
function OvaleCondition:IsCondition(name)
return (self_condition[name] ~= nil)
end
function OvaleCondition:IsSpellBookCondition(name)
return (self_spellBookCondition[name] ~= nil)
end
function OvaleCondition:EvaluateCondition(name, positionalParams, namedParams, state, atTime)
return self_condition[name](positionalParams, namedParams, state, atTime)
end
OvaleCondition.ParseCondition = function(positionalParams, namedParams, state, defaultTarget)
local target = namedParams.target or defaultTarget or "player"
-- Side-effect: set namedParams.target to the correct value if not present.
namedParams.target = namedParams.target or target
if target == "target" then
target = state.defaultTarget
end
local filter
if namedParams.filter then
if namedParams.filter == "debuff" then
filter = "HARMFUL"
elseif namedParams.filter == "buff" then
filter = "HELPFUL"
end
end
local mine = true
if namedParams.any and namedParams.any == 1 then
mine = false
else
-- Legacy parameter "mine"; no longer documented.
if not namedParams.any and namedParams.mine and namedParams.mine ~= 1 then
mine = false
end
end
return target, filter, mine
end
-- Returns whether "a" matches "yesno".
OvaleCondition.TestBoolean = function(a, yesno)
if not yesno or yesno == "yes" then
if a then
return 0, INFINITY
end
else
if not a then
return 0, INFINITY
end
end
return nil
end
-- Returns either an "Ovale value" or a boolean, depending on whether "comparator" is given.
-- An "Ovale value" is a quintuplet (start, ending, value, origin, rate) that determines a
-- linear function A(t) = value + (t - origin)*rate, with domain (start, ending).
OvaleCondition.TestValue = function(start, ending, value, origin, rate, comparator, limit)
--[[
A(t) = limit
value + (t - origin)*rate = limit
(t - origin)*rate = limit - value
--]]
if not value or not origin or not rate then
return nil
end
start = start or 0
ending = ending or INFINITY
if not comparator then
if start < ending then
return start, ending, value, origin, rate
else
return 0, INFINITY, 0, 0, 0
end
elseif not OvaleCondition.COMPARATOR[comparator] then
OvaleCondition:Error("unknown comparator %s", comparator)
elseif not limit then
OvaleCondition:Error("comparator %s missing limit", comparator)
elseif rate == 0 then
if (comparator == "less" and value < limit)
or (comparator == "atMost" and value <= limit)
or (comparator == "equal" and value == limit)
or (comparator == "atLeast" and value >= limit)
or (comparator == "more" and value > limit) then
return start, ending
end
elseif (comparator == "less" and rate > 0)
or (comparator == "atMost" and rate > 0)
or (comparator == "atLeast" and rate < 0)
or (comparator == "more" and rate < 0) then
local t = (limit - value)/rate + origin
ending = (ending < t) and ending or t
return start, ending
elseif (comparator == "less" and rate < 0)
or (comparator == "atMost" and rate < 0)
or (comparator == "atLeast" and rate > 0)
or (comparator == "more" and rate > 0) then
local t = (limit - value)/rate + origin
start = (start > t) and start or t
return start, INFINITY
end
return nil
end
OvaleCondition.Compare = function(value, comparator, limit)
return OvaleCondition.TestValue(0, INFINITY, value, 0, 0, comparator, limit)
end
--</public-static-methods>
--[[----------------------------------------------------------------------------
State machine for simulator.
--]]----------------------------------------------------------------------------
--<public-static-properties>
OvaleCondition.statePrototype = {}
--</public-static-properties>
--<private-static-properties>
local statePrototype = OvaleCondition.statePrototype
--</private-static-properties>
--<state-properties>
--[[
The default target referenced when the "target" parameter is used in a condition.
This is to support setting a different target in an AddIcon "target" parameter,
e.g., target=focus, while re-using the same script.
--]]
statePrototype.defaultTarget = nil
--</state-properties>
--<public-static-methods>
-- Initialize the state.
function OvaleCondition:InitializeState(state)
state.defaultTarget = "target"
end
-- Release state resources prior to removing from the simulator.
function OvaleCondition:CleanState(state)
state.defaultTarget = nil
end
--</public-static-methods>