Difference between revisions of "LuaAPI/wesnoth/map"
Dwarftough (talk | contribs) (→wesnoth.map.iter: place_label doesn't exist, that's at least a working snippet (I hope)) |
|||
Line 4: | Line 4: | ||
This module contains functions for working with the game map. Some of the functions can be called as methods of the map itself. In 1.15.11, there exists only one map in the game context, which can be accessed as [[LuaAPI/types/map|'''wesnoth.current.map''']], while in the map generation context, a map can be created with [[#wesnoth.map.create]] or [[#wesnoth.map.generate]]. In future, it may become possible to create maps on the fly or read them from disk. | This module contains functions for working with the game map. Some of the functions can be called as methods of the map itself. In 1.15.11, there exists only one map in the game context, which can be accessed as [[LuaAPI/types/map|'''wesnoth.current.map''']], while in the map generation context, a map can be created with [[#wesnoth.map.create]] or [[#wesnoth.map.generate]]. In future, it may become possible to create maps on the fly or read them from disk. | ||
+ | |||
+ | == Functions == | ||
=== wesnoth.map.find === | === wesnoth.map.find === |
Revision as of 17:53, 18 April 2024
Contents
- 1 Functions
- 1.1 wesnoth.map.find
- 1.2 wesnoth.map.get
- 1.3 wesnoth.map.matches
- 1.4 wesnoth.map.on_board
- 1.5 wesnoth.map.on_border
- 1.6 wesnoth.map.iter
- 1.7 wesnoth.map.read_location
- 1.8 wesnoth.map.split_terrain_code
- 1.9 wesnoth.map.make_bitmap
- 1.10 wesnoth.map.parse_bitmap
- 1.11 wesnoth.map.terrain_mask
- 1.12 wesnoth.map.add_label
- 1.13 wesnoth.map.remove_label
- 1.14 wesnoth.map.get_label
- 1.15 wesnoth.map.place_area
- 1.16 wesnoth.map.remove_area
- 1.17 wesnoth.map.get_area
- 1.18 wesnoth.map.set_owner
- 1.19 wesnoth.map.get_owner
- 1.20 wesnoth.map.create
- 1.21 wesnoth.map.generate
- 1.22 wesnoth.map.generate_height_map
- 1.23 wesnoth.map.get_direction
- 1.24 wesnoth.map.get_relative_dir
- 1.25 wesnoth.map.rotate_right_around_center
- 1.26 wesnoth.map.get_adjacent_hexes
- 1.27 wesnoth.map.get_hexes_in_radius
- 1.28 wesnoth.map.are_hexes_adjacent
- 1.29 wesnoth.map.distance_between
(Version 1.15.11 and later only)
This module contains functions for working with the game map. Some of the functions can be called as methods of the map itself. In 1.15.11, there exists only one map in the game context, which can be accessed as wesnoth.current.map, while in the map generation context, a map can be created with #wesnoth.map.create or #wesnoth.map.generate. In future, it may become possible to create maps on the fly or read them from disk.
Functions
wesnoth.map.find
- ♟ wesnoth.map.find(filter config) → list of hex references
- ♟ wesnoth.map.find(filter config, [reference_unit]) → list of hex references
- ⌖ wesnoth.map.find(map, filter userdata, [list of locations]) → list of locations
- ⌖ wesnoth.map.find_in_radius(map, center, radius, filter userdata) → list of locations
Returns a table containing all the locations matching the given filter. Locations are stored as a hex reference which has x and y keys along with a variety of other functions. See StandardLocationFilter for details about location filters. If a unit is passed, it can be referenced from the filter via the $teleport_unit variable, as well as in WFL formulas used in the filter.
Note: In older versions of Wesnoth, locations returned from a filter were stored as simple pairs, {x,y}
. For compatibility purposes, accessing a location this way (as loc[1]
and loc[2]
) is still supported.
-- replace all grass terrains by roads
for i,loc in ipairs(wesnoth.map.find{terrain = "Gg"}) do
wesnoth.current.map[loc] = "Rr"
end
The mapgen form of this function uses a different format for the filter which is somewhat experimental. An example of its use:
local map = wesnoth.map.create(18,18,"Gg")
-- Assume there is some generation code here, so the map is no longer just grass
local F, f = wesnoth.map.filter, wesnoth.map.filter_tags
-- Find all elvish villages
local elf_villages = map:find(F(f.terrain('*^Ve')))
-- Find all great trees within 7 tiles of an elvish keep
local elf_keeps = map:find(F(f.terrain('Kv')))
local nearby_trees = map:find_in_radius(elf_keeps, 7, F(f.terrain('*^Fet')))
Possible filter tags for this function are: terrain, all, any, none, notall, adjacent, find_in, radius, x, y, is_loc, formula.
wesnoth.map.get
- ♟ wesnoth.map.get(location) → hex reference
Constructs a hex reference for the specified location.
wesnoth.map.matches
- ♟ wesnoth.map.matches(location, filter config, [reference_unit]) → boolean
- ♟ hex:matches(filter config, [reference_unit]) → boolean
- ⌖ map:matches(location, filter userdata) → boolean
Returns true if the given location passes the filter. The location can be passed either as two separate x and y parameters or as an object with x and y keys (such as a hex reference or a unit). If a reference_unit is passed, it can be referenced from the filter via the $teleport_unit variable, as well as in WFL formulas used in the filter.
local b = wesnoth.map.matches(x, y, {
terrain = "Ww",
wml.tag.filter_adjacent_location{terrain = "Ds,*^Bw*"}
})
wesnoth.map.on_board
- ♟⌖ wesnoth.map.on_board(map, location, [include border?]) → boolean
- ♟⌖ map:on_board(location, [include border?]) → boolean
Tests if the specified location is on the map. The final parameter determines whether to count the inaccessible map border tiles as being on the map. It defaults to false.
wesnoth.map.on_border
Tests if the specified location is on the map's border.
wesnoth.map.iter
- ♟⌖ wesnoth.map.iter(map, [include border?]) → iterator ⇒ x, y, terrain code
- ♟⌖ map:iter([include border?) → iterator ⇒ x, y, terrain code
Iterate over the entire map, possibly excluding the border tiles. For example:
for x, y in wesnoth.current.map:iter() do
wesnoth.map.add_label{x=x, y=y, text=string.format("%d,%d", x, y)}
end
wesnoth.map.read_location
- wesnoth.read_location(...) → location or nil, number of arguments processed
Extracts a location from the front of a variadic parameter list. The purpose of this is to make it easy for custom user-defined functions to handle locations in the same way as the built-in API functions do. It returns the location (if it was able to find one) and the number of arguments processed, which can be:
- 0 if nothing resembling a location was found.
- 1 if a location-like object was found. A location-like object can be either an array of two integers or an object that has numeric x and y keys. Note that a unit userdata satisfies the second criteria, so if a unit is found, its location will be returned.
- 2 if the first two arguments in the list were integers. In this case, they will be taken as the x and y coordinates.
Usage example
Imagine a function foo with the following signature:
- foo(bar : string, [home : location], mode : string, [target : location], moo : boolean) → boolean
Using read_location it could be implemented as follows:
function foo(...)
-- First argument goes in bar
local bar = ...
-- Read location starting at the second argument
local home, n = wesnoth.map.read_location(select(2, ...))
-- note: n will be 0 if a location wasn't found at that position
-- This could be an error, or it could be handled as an optional parameter
-- Next argument after that goes in mode
local mode = select(n + 2, ...)
-- Then read a location into target
local target, m = wesnoth.map.read_location(select(n + 2, ...))
-- Finally, read a parameter into moo
local moo = select(m + n + 2, ...)
-- Do stuff with all these parameters
return true
end
With that code, all the following invocations of foo work:
foo('a', 'b', true) -- both optional locations omitted
foo('a', 1, 2, 'q', 5, 6, false) -- locations given as separate integer parameters
foo('a', 'm', {1, 7}, true) -- first location omitted, second given as 2-element array
foo('a', some_unit, 'z', {x = 5, y = 10}, false) -- a unit also functions as a location
foo('a', 7, 12, 'q', my_leader, true) -- mixing different forms also works
wesnoth.map.split_terrain_code
- wesnoth.map.split_terrain_code(code) → base, overlay
Splits a terrain code into a base and an overlay. If the terrain code did not contain a ^, then the overlay will be nil. The returned overlay or base can be an empty string if the code begins or ends with a ^, respectively. Splitting the string '^' will result in two empty strings.
wesnoth.map.make_bitmap
- ♟ wesnoth.map.make_bitmap(array of locations) → shroud data bitmap
Constructs a shroud data string such that the locations in the array are unshrouded and all other locations are shrouded. The string will be the minimum size required to fit all the locations.
wesnoth.map.parse_bitmap
- ♟ wesnoth.map.parse_bitmap(shroud data bitmap) → array of locations
Parses a shroud data string and returns a list of the locations that are unshrouded.
wesnoth.map.terrain_mask
- ♟⌖ wesnoth.map.terrain_mask(map, pivot, mask, [options])
- ♟⌖ map:terrain_mask(pivot, mask, [options])
Overlays a terrain mask on the map. Possible options:
- is_odd - if true, then the mask is interpreted as if it was cut out from an odd map location.
- ignore_special_locations - if true, then special locations on the mask won't be added to the map.
- rules - an array of rules. See TerrainMaskWML for the rule format. This is an array of tables, each of which has the content of a [rule] tag.
wesnoth.map.add_label
- ♟ wesnoth.map.add_label(options)
Adds a label to the map. Takes the same options as the [label] WML tag.
wesnoth.map.remove_label
- ♟ wesnoth.map.remove_label(location)
Removes a label from the map. Normally this removes a global label, but you can also remove team labels with an extra team_name parameter, for example:
-- Removes the label on (3,12) owned by team 'rebels'
wesnoth.map.remove_label{x = 3, y = 12, team_name = 'rebels'}
wesnoth.map.get_label
- ♟ wesnoth.map.get_label(location, [side or team_name]) → label info
Get the full label info for a label on the specified location. With one argument, it returns a global label; otherwise, it returns a label belonging to the specified team. Passing a side (either a side number or a side userdata) uses that side's team. The returned table contains all the possible options that can be passed to add_label.
wesnoth.map.place_area
- ♟ wesnoth.map.place_area(filter)
Add a new named area to the map. The filter is a StandardLocationFilter, but it can also contain an id key and [time] tags. In order to remove the area later, an id must be provided. An area with no [time] tags does not affect the schedule.
wesnoth.map.remove_area
- ♟ wesnoth.map.remove_area(id)
Remove the area with the given ID.
wesnoth.map.get_area
- ♟ wesnoth.map.get_area(id or location) → area schedule
Get the named area with the specified ID, or the area that is active on the specified location (if any). This will return nil if no area is found in either case.
The returned object is a userdata object similar to wesnoth.current.schedule, with the following differences:
- schedule.liminal_bonus → nil
This key is not supported on area schedules.
- schedule.id ↔ id
Check or alter the ID of the named area.
- schedule.hexes ↔ array of locations
Get the list of locations the area affects, or assign a new list of locations. The list may be empty, in which case the area has no effect on time of day and cannot be matched by a location filter.
wesnoth.map.set_owner
- ♟ wesnoth.map.set_owner(location, side number)
Set the owner of a village hex. If the specified hex is not a village, this has no effect. Set the owner to 0 to leave it owned by no-one.
wesnoth.map.get_owner
- ♟ wesnoth.map.get_owner(location) → side number
Get the owner of a village hex. If the specified hex is not a village, or if it is an unclaimed village, this returns 0.
wesnoth.map.create
Create a new map, either filled with a given terrain or read from a string.
wesnoth.map.generate
- ⌖ wesnoth.map.generate(width, height, options) → map
Generate a map using the default generator. The following options are supported:
- nplayers
- nvillages
- iterations
- hill_size
- castle_size
- island_size
- island_off_center
- max_lakes
- link_castles
- seed
wesnoth.map.generate_height_map
- ⌖ wesnoth.map.generate_height_map(width, height, options) → array of heights
Generates a height map such as that used by the default generator. The following options are supported:
- iterations
- hill_size
- island_size
- center_x
- center_y
- flip_format
- seed
wesnoth.map.get_direction
- wesnoth.map.get_direction(from, dir, [steps]) → location
Calculates the hex reached by travelling in the specified direction, which should be a string such as "ne" or "s". It will also honor direction modifiers (the prefix - and postfix :cw or :ccw). The optional third parameter steps is number of steps to travel in specified direction. Negative steps is supported to travel in the opposite direction.
wesnoth.map.get_relative_dir
- wesnoth.map.get_relative_dir(from, to) → direction
Calculates the direction from one hex to another. Possible returns are strings "n", "ne", "nw", "s", "se", "sw" or "". The empty string means no direction, which happens if from and to are same.
wesnoth.map.rotate_right_around_center
- wesnoth.map.rotate_right_around_center(loc, center, angle) → location
Calculates the hex obtained from rotating the specified location around the specified center by the specified angle. The angle is an integer in the range 1..6.
wesnoth.map.get_adjacent_hexes
- wesnoth.map.get_adjacent_hexes(loc) → n, ne, se, s, sw, nw
Return all hexes adjacent to the specified hex, as six separate return values. This doesn't check whether the hexes are on the map.
local a, b, c, d, e, f = wesnoth.map.get_adjacent_hexes(3, 3)
local a_x = a[1]
local a_y = a[2]
wesnoth.map.get_hexes_in_radius
- wesnoth.map.get_hexes_in_radius(center, radius) → list of locations
Return all hexes within the given radius, as an array of pairs. This doesn't check whether the hexes are on the map.
wesnoth.map.are_hexes_adjacent
- wesnoth.map.are_hexes_adjacent(loc1, loc2) → boolean
Tests if two hexes are adjacent.
wesnoth.map.distance_between
- wesnoth.map.distance_between(loc1, loc2) → integer
Calculates the distance between two hexes. The distance is the number of hexes you would need to travel across to get from the start point to the end point.
local my_distance = wesnoth.map.distance_between({10, 10}, {20, 20})