-
-
Notifications
You must be signed in to change notification settings - Fork 988
/
set_variable.lua
166 lines (139 loc) · 4.62 KB
/
set_variable.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
local helper = wesnoth.require "helper"
function wesnoth.wml_actions.set_variable(cfg, variables)
local name = cfg.name or wml.error "trying to set a variable with an empty name"
if variables == nil then variables = wml.variables end
if cfg.value ~= nil then -- check for nil because user may try to set a variable as false
variables[name] = cfg.value
end
if cfg.literal ~= nil then
variables[name] = wml.shallow_literal(cfg).literal
end
if cfg.to_variable then
variables[name] = variables[cfg.to_variable]
end
if cfg.suffix then
variables[name] = (variables[name] or '') .. (cfg.suffix or '')
end
if cfg.prefix then
variables[name] = (cfg.prefix or '') .. (variables[name] or '')
end
if cfg.add then
variables[name] = (tonumber(variables[name]) or 0) + (tonumber(cfg.add) or 0)
end
if cfg.sub then
variables[name] = (tonumber(variables[name]) or 0) - (tonumber(cfg.sub) or 0)
end
if cfg.multiply then
variables[name] = (tonumber(variables[name]) or 0) * (tonumber(cfg.multiply) or 0)
end
if cfg.divide then
local divide = tonumber(cfg.divide) or 0
if divide == 0 then wml.error("division by zero on variable " .. name) end
variables[name] = (tonumber(variables[name]) or 0) / divide
end
if cfg.modulo then
local modulo = tonumber(cfg.modulo) or 0
if modulo == 0 then wml.error("division by zero on variable " .. name) end
variables[name] = (tonumber(variables[name]) or 0) % modulo
end
if cfg.abs then
variables[name] = math.abs(tonumber(variables[name]) or 0)
end
if cfg.root then
local root = tonumber(cfg.root)
local root_fcn
if cfg.root == "square" then
root = 2
root_fcn = math.sqrt
else
if cfg.root == "cube" then
root = 3
end
root_fcn = function(n) return n ^ (1 / root) end
end
local radicand = tonumber(variables[name]) or 0
if radicand < 0 and root % 2 == 0 then
if root == 2 then
wml.error("square root of negative number on variable " .. name)
else
wml.error(string.format("%dth root of negative number on variable %s", root, name))
end
end
variables[name] = root_fcn(radicand)
end
if cfg.power then
variables[name] = (tonumber(variables[name]) or 0) ^ (tonumber(cfg.power) or 0)
end
if cfg.round then
local var = tonumber(variables[name] or 0)
local round_val = cfg.round
if round_val == "ceil" then
variables[name] = math.ceil(var)
elseif round_val == "floor" then
variables[name] = math.floor(var)
elseif round_val == "trunc" then
-- Storing to a variable first because modf returns two values,
-- and I'm not sure if set_variable will complain about the extra parameter
local new_val = math.modf(var)
variables[name] = new_val
else
local decimals = math.modf(tonumber(round_val) or 0)
local value = var * (10 ^ decimals)
value = helper.round(value)
value = value * (10 ^ -decimals)
variables[name] = value
end
end
-- unlike the other math operations, ipart and fpart do not act on
-- the value already contained in the variable
-- but on the value assigned to the respective key
if cfg.ipart then
local ivalue = math.modf(tonumber(cfg.ipart) or 0)
variables[name] = ivalue
end
if cfg.fpart then
local ivalue, fvalue = math.modf(tonumber(cfg.fpart) or 0)
variables[name] = fvalue
end
if cfg.string_length ~= nil then
variables[name] = string.len(tostring(cfg.string_length))
end
if cfg.time then
if cfg.time == "stamp" then
variables[name] = wesnoth.get_time_stamp()
end
end
if cfg.rand then
variables[name] = helper.rand(tostring(cfg.rand))
end
if cfg.formula then
local fcn = wesnoth.compile_formula(cfg.formula)
variables[name] = fcn(variables[name])
end
local join_child = wml.get_child(cfg, "join")
if join_child then
local array_name = join_child.variable or wml.error "missing variable= attribute in [join]"
local separator = join_child.separator
local key_name = join_child.key or "value"
local remove_empty = join_child.remove_empty
local string_to_join = ''
for i, element in ipairs(wml.array_variables[array_name]) do
if element[key_name] ~= nil or (not remove_empty) then
if #string_to_join > 0 then
string_to_join = string_to_join .. separator
end
local elem = element[key_name]
if type(elem) == 'boolean' then
-- Use yes/no instead of true/false for booleans
elem = elem and 'yes' or 'no'
elseif getmetatable(elem) ~= 'translatable string' then
-- Not entirely sure if this branch is necessary, since it probably only triggers for numbers
-- It certainly can't hurt, though.
elem = tostring(elem)
end
string_to_join = string_to_join .. elem
end
end
variables[name] = string_to_join
end
end