-
-
Notifications
You must be signed in to change notification settings - Fork 988
/
map.lua
265 lines (245 loc) · 10.8 KB
/
map.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
257
258
259
260
261
262
263
264
265
--[========[Map module]========]
print("Loading map module...")
function wesnoth.map.split_terrain_code(code)
return table.unpack(code:split('^', {remove_empty = false}))
end
function wesnoth.map.read_location(...)
local x, y = ...
if y == nil then
if type(x.x) == 'number' and type(x.y) == 'number' then
x, y = x.x, x.y
elseif type(x[1]) == 'number' and type(x[2]) == 'number' then
x, y = table.unpack(x)
else
return nil, 0
end
return {x = x, y = y}, 1
elseif type(x) == 'number' or type(y) == 'number' then
return {x = x, y = y}, 2
end
return nil, 0
end
if wesnoth.kernel_type() ~= "Application Lua Kernel" then
-- possible terrain string inputs:
-- A A^ A^B ^ ^B
-- implied mode:
-- both base both overlay overlay
function wesnoth.map.replace_base(code)
local base, overlay = wesnoth.map.split_terrain_code(code)
if base == nil then -- ^ or ^B
-- There's no base to replace with, so do nothing
return ''
else
-- Use the specified base but ignore the overlay
return base .. '^'
end
end
function wesnoth.map.replace_overlay(code)
local base, overlay = wesnoth.map.split_terrain_code(code)
if overlay == nil or overlay == '' then -- A or A^
-- No overlay was specified, so we want to clear the overlay without touching the base
return '^'
else
-- An overlay was specified, so use that and ignore the base
return '^' .. overlay
end
end
function wesnoth.map.replace_both(code)
local base, overlay = wesnoth.map.split_terrain_code(code)
if base == '' then -- ^ or ^B
-- There's no way to find a base to replace with in this case.
-- Could use the existing base, but that's not really replacing both, is it?
error('replace_both: no base terrain specified')
elseif overlay == '' then -- A^
-- This would normally mean replace base while preserving overlay,
-- but we actually want to replace base and clear overlay.
return base
else
-- It's already going to replace both, so return unchanged
return code
end
end
end
if wesnoth.kernel_type() == "Game Lua Kernel" then
local hex_mt = {__metatable = 'terrain hex reference'}
function hex_mt.__index(self, key)
if key == 'fogged' then
return self:fogged_for(wesnoth.current.side)
elseif key == 'shrouded' then
return self:shrouded_for(wesnoth.current.side)
elseif key == 'team_label' then
local label = self:label_for(wesnoth.current.side)
if label then return label.text end
return nil
elseif key == 'global_label' then
local label = self:label_for(nil)
if label then return label.text end
return nil
elseif key == 'label' then
return self.team_label or self.global_label
elseif key == 'terrain' then
return wesnoth.current.map[self]
elseif key == 'base_terrain' then
return self.terrain:split('^')[1]
elseif key == 'overlay_terrain' then
return self.terrain:split('^', {remove_empty=false})[2]
elseif key == 'info' then
return wesnoth.get_terrain_info(wesnoth.current.map[self])
elseif key == 1 then
return self.x
elseif key == 2 then
return self.y
elseif #key > 0 and key[0] ~= '_' then
return hex_mt[key]
end
end
function hex_mt.__newindex(self, key, val)
if key == 'fogged' then
self:set_fogged(wesnoth.current.side, val)
elseif key == 'shrouded' then
self:set_shrouded(wesnoth.current.side, val)
elseif key == 'team_label' or key == 'global_label' or key == 'label' then
local cfg
if type(val) == 'string' or (type(val) == 'userdata' and getmetatable(val) == 'translatable string') then
cfg = {x = self.x, y = self.y, text = val}
else
cfg = wml.parsed(val)
cfg.x, cfg.y = self.x, self.y
end
if key == 'team_label' then
cfg.side = wesnoth.current.side
cfg.team_name = wesnoth.sides[wesnoth.current.side].team_name
elseif key == 'global_label' then
cfg.side = 0
cfg.team_name = nil
elseif cfg.side == nil and cfg.team_name == nil then
-- If side or team name explicitly specified, use that, otherwise use current side and no team
cfg.side = wesnoth.current.side
cfg.team_name = nil
end
wesnoth.map.add_label(cfg)
elseif key == 'terrain' then
wesnoth.current.map[self] = val
elseif key == 'base_terrain' then
wesnoth.current.map[self] = wesnoth.map.replace_base(val)
elseif key == 'overlay_terrain' then
wesnoth.current.map[self] = wesnoth.map.replace_overlay(val)
elseif key == 1 then
self.x = val
elseif key == 2 then
self.y = val
elseif key == 'info' then
error('hex.info is read-only', 1)
end
end
function hex_mt:fogged_for(side)
return wesnoth.map.is_fogged(side, self.x, self.y)
end
function hex_mt:shrouded_for(side)
return wesnoth.map.is_shrouded(side, self.x, self.y)
end
function hex_mt:set_fogged(side, val)
if val then
wesnoth.map.place_shroud(side, {val})
else
wesnoth.map.remove_shroud(side, {val})
end
end
function hex_mt:set_fogged(side, val)
if val then
wesnoth.map.place_fog(side, {val})
else
wesnoth.map.remove_fog(side, {val})
end
end
function hex_mt:label_for(who)
return wesnoth.map.get_label(self.x, self.y, who)
end
function hex_mt:matches(filter)
return wesnoth.map.matches(self.x, self.y, filter)
end
function wesnoth.map.get(x, y)
if not x or not y then error('Missing coordinate') end
if type(x) ~= 'number' or type(y) ~= 'number' then
error('Coordinate must be a number')
end
return setmetatable({x = x, y = y}, hex_mt)
end
local find_locations = wesnoth.map.find
function wesnoth.map.find(cfg)
local hexes = find_locations(cfg)
for i = 1, #hexes do
hexes[i] = wesnoth.map.get(hexes[i][1], hexes[i][2])
end
return hexes
end
wesnoth.terrain_mask = wesnoth.deprecate_api('wesnoth.terrain_mask', 'wesnoth.current.map:terrain_mask', 1, nil, function(...)
wesnoth.current.map:terrain_mask(...)
end)
wesnoth.get_terrain = wesnoth.deprecate_api('wesnoth.get_terrain', 'wesnoth.current.map[loc]', 1, nil, function(x, y)
local loc = wesnoth.read_location(x, y)
if loc == nil then error('get_terrain: expected location') end
return wesnoth.current.map[loc]
end)
wesnoth.set_terrain = wesnoth.deprecate_api('wesnoth.set_terrain', 'wesnoth.current.map[loc]=', 1, nil, function(...)
local loc, n = wesnoth.read_location(...)
if n == 0 then error('set_terrain: expected location') end
local new_ter, mode, replace_if_failed = select(n + 1, ...)
if new_ter == '' or type(new_ter) ~= 'string' then error('set_terrain: expected terrain string') end
if replace_if_failed then
mode = mode or 'both'
new_ter = wesnoth.map.replace_if_failed(new_ter, mode, true)
elseif mode == 'both' or mode == 'base' or mode == 'overlay' then
new_ter = wesnoth.map['replace_' .. mode](new_ter)
else
error('set_terrain: invalid mode')
end
wesnoth.current.map[loc] = new_ter
end)
wesnoth.get_map_size = wesnoth.deprecate_api('wesnoth.get_map_size', 'wesnoth.current.map.playable_width,playable_height,border_size', 1, nil, function()
local m = wesnoth.current.map
return m.playable_width, m.playable_height, m.border_size
end)
wesnoth.special_locations = wesnoth.deprecate_api('wesnoth.special_locations', 'wesnoth.current.map:special_locations', 1, nil, setmetatable({}, {
__index = function(_, k) return wesnoth.current.map.special_locations[k] end,
__newindex = function(_, k, v) wesnoth.current.map.special_locations[k] = v end,
__len = function(_)
local n = 0
for k,v in pairs(wesnoth.current.map.special_locations) do
n = n + 1
end
return n
end,
__pairs = function(_) return pairs(wesnoth.current.map.special_locations) end,
}), 'Note: the length operator has been removed')
wesnoth.place_shroud = wesnoth.deprecate_api('wesnoth.place_shroud', 'wesnoth.map.place_shroud', 1, nil, wesnoth.map.place_shroud)
wesnoth.remove_shroud = wesnoth.deprecate_api('wesnoth.remove_shroud', 'wesnoth.map.remove_shroud', 1, nil, wesnoth.map.remove_shroud)
wesnoth.is_shrouded = wesnoth.deprecate_api('wesnoth.is_shrouded', 'wesnoth.map.is_shrouded', 1, nil, wesnoth.map.is_shrouded)
wesnoth.add_fog = wesnoth.deprecate_api('wesnoth.add_fog', 'wesnoth.map.place_fog', 1, nil, wesnoth.map.place_fog)
wesnoth.remove_fog = wesnoth.deprecate_api('wesnoth.remove_fog', 'wesnoth.map.remove_fog', 1, nil, wesnoth.map.remove_fog)
wesnoth.is_fogged = wesnoth.deprecate_api('wesnoth.is_fogged', 'wesnoth.map.is_fogged', 1, nil, wesnoth.map.is_fogged)
wesnoth.get_village_owner = wesnoth.deprecate_api('wesnoth.get_village_owner', 'wesnoth.map.get_owner', 1, nil, wesnoth.map.get_owner)
wesnoth.set_village_owner = wesnoth.deprecate_api('wesnoth.set_village_owner', 'wesnoth.map.set_owner', 1, nil, wesnoth.map.set_owner)
wesnoth.label = wesnoth.deprecate_api('wesnoth.label', 'wesnoth.map.add_label', 1, nil, wesnoth.map.add_label)
wesnoth.add_time_area = wesnoth.deprecate_api('wesnoth.add_time_area', 'wesnoth.map.place_area', 1, nil, wesnoth.map.place_area)
wesnoth.remove_time_area = wesnoth.deprecate_api('wesnoth.remove_time_area', 'wesnoth.map.remove_area', 1, nil, wesnoth.map.remove_area)
wesnoth.get_locations = wesnoth.deprecate_api('wesnoth.get_locations', 'wesnoth.map.find', 1, nil, wesnoth.map.find)
wesnoth.get_villages = wesnoth.deprecate_api('wesnoth.get_locations', 'wesnoth.map.find', 1, nil, function(cfg)
return wesnoth.map.find{gives_income = true, wml.tag["and"](cfg)}
end)
wesnoth.match_location = wesnoth.deprecate_api('wesnoth.match_location', 'wesnoth.map.matches', 1, nil, wesnoth.map.matches)
end
if wesnoth.kernel_type() == "Mapgen Lua Kernel" then
-- More map module stuff
wesnoth.create_filter = wesnoth.deprecate_api('wesnoth.create_filter', 'wesnoth.map.filter', 1, nil, wesnoth.map.filter)
wesnoth.create_map = wesnoth.deprecate_api('wesnoth.create_map', 'wesnoth.map.create', 1, nil, wesnoth.map.create)
wesnoth.default_generate_height_map = wesnoth.deprecate_api('wesnoth.default_generate_height_map', 'wesnoth.map.generate_height_map', 1, nil, wesnoth.map.generate_height_map)
wesnoth.generate_default_map = wesnoth.deprecate_api('wesnoth.generate_default_map', 'wesnoth.map.generate', 1, nil, wesnoth.map.generate)
-- These were originally only on the map metatable, so the deprecated versions also need to be in the map module
wesnoth.map.get_locations = wesnoth.deprecate_api('map:get_locations', 'map:find', 1, nil, wesnoth.map.find)
wesnoth.map.get_tiles_radius = wesnoth.deprecate_api('map:get_tiles_radius', 'map:find_in_radius', 1, nil, function(map, locs, filter, radius)
return wesnoth.map.find_in_radius(map, locs, radius, filter)
end, 'The filter is now the last parameter, instead of the radius')
end
wesnoth.map.tiles_adjacent = wesnoth.deprecate_api('wesnoth.map.tiles_adjacent', 'wesnoth.map.are_hexes_adjacent', 1, nil, wesnoth.map.are_hexes_adjacent)
wesnoth.map.get_adjacent_tiles = wesnoth.deprecate_api('wesnoth.map.get_adjacent_tiles', 'wesnoth.map.get_adjacent_hexes', 1, nil, wesnoth.map.get_adjacent_hexes)