add tag [random_placement]
and use it to implement SCATTER_IMAGE,SCATTER_EMBELLISHMENTS and SCATTER_UNITS
This commit is contained in:
parent
9aa6722622
commit
dc786dc181
3 changed files with 112 additions and 126 deletions
|
@ -31,42 +31,21 @@
|
|||
#
|
||||
# This call will scatter 20 copies of a pine-tree graphic over grassland:
|
||||
#! {SCATTER_IMAGE (terrain=Gg) 20 scenery/pine1.png}
|
||||
[store_locations]
|
||||
{FILTER}
|
||||
variable=random_placement_locations
|
||||
[/store_locations]
|
||||
|
||||
{VARIABLE REPEAT_i 0}
|
||||
|
||||
[while]
|
||||
[variable]
|
||||
name=REPEAT_i
|
||||
less_than={NUMBER}
|
||||
[/variable]
|
||||
[variable]
|
||||
name=random_placement_locations.length
|
||||
greater_than=0
|
||||
[/variable]
|
||||
|
||||
[do]
|
||||
[set_variable]
|
||||
name=random_subscript
|
||||
rand="0..$($random_placement_locations.length - 1)"
|
||||
[/set_variable]
|
||||
|
||||
[random_placement]
|
||||
num_items={NUMBER}
|
||||
variable=random_placement_location
|
||||
allow_less=yes
|
||||
[filter]
|
||||
{FILTER}
|
||||
[/filter]
|
||||
[command]
|
||||
[item]
|
||||
image={IMAGE}
|
||||
x,y=$random_placement_locations[$random_subscript].x,$random_placement_locations[$random_subscript].y
|
||||
x,y=$random_placement_location.x,$random_placement_location.y
|
||||
[/item]
|
||||
|
||||
{CLEAR_VARIABLE random_placement_locations[$random_subscript]}
|
||||
{VARIABLE_OP REPEAT_i add 1}
|
||||
[/do]
|
||||
[/while]
|
||||
|
||||
{CLEAR_VARIABLE REPEAT_i}
|
||||
{CLEAR_VARIABLE random_subscript}
|
||||
{CLEAR_VARIABLE random_placement_locations}
|
||||
[/command]
|
||||
[/random_placement]
|
||||
{CLEAR_VARIABLE random_placement_location}
|
||||
#enddef
|
||||
|
||||
#define SCATTER_EMBELLISHMENTS TERRAINLIST EMBELLISHMENT_NAME PERCENTAGE
|
||||
|
@ -75,39 +54,20 @@
|
|||
#
|
||||
# For example, this will add flowers to 5% of all grassland:
|
||||
#! {SCATTER_EMBELLISHMENTS G* ^Efm 5}
|
||||
[store_locations]
|
||||
terrain={TERRAINLIST}
|
||||
variable=terrain_variation_locations
|
||||
[/store_locations]
|
||||
|
||||
{VARIABLE terrain_variations_to_place {PERCENTAGE}}
|
||||
|
||||
# TODO: change back to 100.0 once it no longer causes a crash
|
||||
{VARIABLE_OP terrain_variations_to_place divide 100.0}
|
||||
|
||||
{VARIABLE_OP terrain_variations_to_place multiply $terrain_variation_locations.length}
|
||||
{VARIABLE_OP terrain_variations_to_place round ceil}
|
||||
|
||||
[while]
|
||||
[variable]
|
||||
name=terrain_variations_to_place
|
||||
greater_than=0
|
||||
[/variable]
|
||||
|
||||
[do]
|
||||
{VARIABLE_OP terrain_variation_i rand "0..$($terrain_variation_locations.length - 1)"}
|
||||
|
||||
[random_placement]
|
||||
num_items="size * ({PERCENTAGE} / 100)"
|
||||
variable=random_placement_location
|
||||
allow_less=yes
|
||||
[filter]
|
||||
terrain={TERRAINLIST}
|
||||
[/filter]
|
||||
[command]
|
||||
[terrain]
|
||||
x,y=$terrain_variation_locations[$terrain_variation_i].x,$terrain_variation_locations[$terrain_variation_i].y
|
||||
x,y=$random_placement_location.x,$random_placement_location.y
|
||||
terrain={EMBELLISHMENT_NAME}
|
||||
layer=overlay
|
||||
[/terrain]
|
||||
|
||||
{VARIABLE_OP terrain_variations_to_place sub 1}
|
||||
|
||||
{CLEAR_VARIABLE terrain_variation_locations[$terrain_variation_i]}
|
||||
[/do]
|
||||
[/while]
|
||||
|
||||
{CLEAR_VARIABLE terrain_variation_locations,terrain_variations_to_place,terrain_variation_i}
|
||||
[/command]
|
||||
[/random_placement]
|
||||
{CLEAR_VARIABLE random_placement_location}
|
||||
#enddef
|
||||
|
|
|
@ -462,15 +462,6 @@
|
|||
#! {TRAIT_LOYAL}
|
||||
#! [/modifications]
|
||||
#! )}
|
||||
|
||||
[store_locations]
|
||||
{FILTER}
|
||||
|
||||
# Exclude border hexes
|
||||
include_borders=no
|
||||
variable=possible_unit_locations
|
||||
[/store_locations]
|
||||
|
||||
[set_variables]
|
||||
name=unit_type_table
|
||||
|
||||
|
@ -482,65 +473,27 @@
|
|||
[/set_variables]
|
||||
|
||||
{VARIABLE unit_type_table_i 0}
|
||||
{VARIABLE units_to_place {NUMBER}}
|
||||
|
||||
[while]
|
||||
[variable]
|
||||
name=units_to_place
|
||||
greater_than=0
|
||||
[/variable]
|
||||
|
||||
[do]
|
||||
[set_variable]
|
||||
name=random_subscript
|
||||
rand=1..$possible_unit_locations.length
|
||||
[/set_variable]
|
||||
{VARIABLE_OP random_subscript sub 1}
|
||||
|
||||
[random_placement]
|
||||
num_items={NUMBER}
|
||||
variable=random_placement_location
|
||||
allow_less=yes
|
||||
radius={PADDING_RADIUS}
|
||||
[filter]
|
||||
{FILTER}
|
||||
include_borders=no
|
||||
[/filter]
|
||||
[command]
|
||||
[unit]
|
||||
type=$unit_type_table[$unit_type_table_i].type
|
||||
x,y=$possible_unit_locations[$random_subscript].x,$possible_unit_locations[$random_subscript].y
|
||||
x,y=$random_placement_location.x,$random_placement_location.y
|
||||
{UNIT_WML}
|
||||
[/unit]
|
||||
{VARIABLE unit_type_table_i $(($unit_type_table_i + 1) % $unit_type_table.length)}
|
||||
[/command]
|
||||
[/random_placement]
|
||||
|
||||
[store_locations]
|
||||
find_in=possible_unit_locations
|
||||
[not]
|
||||
x,y=$possible_unit_locations[$random_subscript].x,$possible_unit_locations[$random_subscript].y
|
||||
radius={PADDING_RADIUS}
|
||||
[/not]
|
||||
variable=possible_unit_locations
|
||||
[/store_locations]
|
||||
|
||||
[if]
|
||||
[variable]
|
||||
name=possible_unit_locations.length
|
||||
less_than=1
|
||||
[/variable]
|
||||
|
||||
[then]
|
||||
{VARIABLE units_to_place 0}
|
||||
[/then]
|
||||
[/if]
|
||||
|
||||
{VARIABLE_OP unit_type_table_i add 1}
|
||||
|
||||
[if]
|
||||
[variable]
|
||||
name=unit_type_table_i
|
||||
numerical_equals=$unit_type_table.length
|
||||
[/variable]
|
||||
|
||||
[then]
|
||||
{VARIABLE unit_type_table_i 0}
|
||||
[/then]
|
||||
[/if]
|
||||
|
||||
{VARIABLE_OP units_to_place sub 1}
|
||||
[/do]
|
||||
[/while]
|
||||
|
||||
{CLEAR_VARIABLE unit_type_table,unit_type_table_i,possible_unit_locations,random_subscript,units_to_place}
|
||||
{CLEAR_VARIABLE unit_type_table,unit_type_table_i,random_placement_location}
|
||||
#enddef
|
||||
|
||||
#define FORCE_CHANCE_TO_HIT FILTER SECOND_FILTER CTH_NUMBER EXTRA_CONDITIONS_WML
|
||||
|
|
|
@ -1643,3 +1643,76 @@ function wml_actions.unsynced(cfg)
|
|||
wml_actions.command(cfg)
|
||||
end)
|
||||
end
|
||||
|
||||
wesnoth.wml_actions.random_placement = function(cfg)
|
||||
local dist_le_radius = nil
|
||||
|
||||
local parsed = helper.shallow_parsed(cfg)
|
||||
local filter = helper.get_child(parsed, "filter") or {}
|
||||
local command = helper.get_child(parsed, "command") or helper.wml_error("[random_placement] missing required [command] subtag")
|
||||
local radius = cfg.radius or 0
|
||||
local num_items = cfg.num_items or helper.wml_error("[random_placement] missing required 'num_items' attribute")
|
||||
local variable = cfg.variable or helper.wml_error("[random_placement] missing required 'variable' attribute")
|
||||
local use_delay = cfg.use_delay == true
|
||||
local allow_less = cfg.allow_less == true
|
||||
if radius < 0 then
|
||||
-- optimisation for radius = -1
|
||||
dist_le_radius = function() return false end
|
||||
elseif radius == 0 then
|
||||
-- optimisation for radius = 0
|
||||
dist_le_radius = function(x1,y1,x2,y2) return x1 == x2 and y1 == y2 end
|
||||
else
|
||||
-- optimisation: cloasure is faster than string lookups.
|
||||
local math_abs = math.abs
|
||||
-- same effect as helper.distance_between(x1,y1,x2,y2) <= radius but faster.
|
||||
dist_le_radius = function(x1,y1,x2,y2)
|
||||
local d_x = math_abs(x1-x2)
|
||||
if d_x > radius then
|
||||
return false
|
||||
end
|
||||
if d_x % 2 ~= 0 then
|
||||
if x1 % 2 == 0 then
|
||||
y2 = y2 - 0.5
|
||||
else
|
||||
y2 = y2 + 0.5
|
||||
end
|
||||
end
|
||||
local d_y = math_abs(y1-y2)
|
||||
return d_x + 2*d_y <= 2*radius
|
||||
end
|
||||
end
|
||||
|
||||
local locs = wesnoth.get_locations(filter)
|
||||
if type(num_items) == "string" then
|
||||
num_items = math.floor(loadstring("local size = " .. #locs .. "; return " .. num_items)())
|
||||
print("num_items=" .. num_items .. ", #locs=" .. #locs)
|
||||
end
|
||||
local size = #locs
|
||||
for i = 1, num_items do
|
||||
if size == 0 then
|
||||
if allow_less then
|
||||
wesnoth.message("placed only " .. i .. " items")
|
||||
return
|
||||
else
|
||||
helper.wml_error("[random_placement] failed to place items. only " .. i .. " items were placed")
|
||||
end
|
||||
end
|
||||
local index = wesnoth.random(size)
|
||||
local point = locs[index]
|
||||
wesnoth.set_variable(variable .. ".x", point[1])
|
||||
wesnoth.set_variable(variable .. ".y", point[2])
|
||||
wesnoth.set_variable(variable .. ".n", i)
|
||||
for j = size, 1, -1 do
|
||||
if dist_le_radius(locs[j][1], locs[j][2], point[1], point[2]) then
|
||||
-- optimisation: swapping elements and storing size in an extra variable is faster than table.remove(locs, j)
|
||||
locs[j] = locs[size]
|
||||
size = size - 1
|
||||
end
|
||||
end
|
||||
wesnoth.wml_actions.command (command)
|
||||
if use_delay and (i % 10 == 0) then
|
||||
--prevent freezing.
|
||||
wesnoth.delay(0);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue