forked from Bilka2/AbandonedRuins
-
Notifications
You must be signed in to change notification settings - Fork 0
/
spawning.lua
154 lines (131 loc) · 4.63 KB
/
spawning.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
local util = require("utilities")
local expressions = require("expression_parsing")
local spawning = {}
local function no_corpse_fade(half_size, center, surface)
local area = util.area_from_center_and_half_size(half_size, center)
for _, entity in pairs(surface.find_entities_filtered({area = area, type={"corpse"}})) do
entity.corpse_expires = false
end
end
local function spawn_entity(entity, relative_position, center, surface, extra_options, vars, prototypes)
local entity_name = expressions.entity(entity, vars)
if not prototypes[entity_name] then
util.debugprint("entity " .. entity_name .. " does not exist")
return
end
local force = extra_options.force or "neutral"
if force == "enemy" then
force = util.get_enemy_force()
end
local recipe
if extra_options.recipe then
if not game.recipe_prototypes[extra_options.recipe] then
util.debugprint("recipe " .. extra_options.recipe .. " does not exist")
else
recipe = extra_options.recipe
end
end
local e = surface.create_entity
{
name = entity_name,
position = {center.x + relative_position.x, center.y + relative_position.y},
direction = defines.direction[extra_options.dir] or defines.direction.north,
force = force,
raise_built = true,
create_build_effect_smoke = false,
recipe = recipe
}
if extra_options.dmg then
util.safe_damage(e, extra_options.dmg, expressions.number(extra_options.dmg.dmg, vars))
end
if extra_options.dead then
util.safe_die(e, extra_options.dead)
end
if extra_options.fluids then
local fluids = {}
for name, amount_expression in pairs(extra_options.fluids) do
local amount = expressions.number(amount_expression, vars)
if amount > 0 then
fluids[name] = amount
end
end
util.safe_insert_fluid(e, fluids)
end
if extra_options.items then
local items = {}
for name, count_expression in pairs(extra_options.items) do
local count = expressions.number(count_expression, vars)
if count > 0 then
items[name] = count
end
end
util.safe_insert(e, items)
end
end
local function spawn_entities(entities, center, surface, vars)
if not entities then return end
local prototypes = game.entity_prototypes
for _, entity_info in pairs(entities) do
spawn_entity(entity_info[1], entity_info[2], center, surface, entity_info[3] or {}, vars, prototypes)
end
end
local function spawn_tiles(tiles, center, surface)
if not tiles then return end
local prototypes = game.tile_prototypes
local valid = {}
for _, tile_info in pairs(tiles) do
local name = tile_info[1]
local pos = tile_info[2]
if prototypes[name] then
valid[#valid+1] = {name = name, position = {center.x + pos.x, center.y + pos.y}}
else
util.debugprint("tile " .. name .. " does not exist")
end
end
surface.set_tiles(
valid,
true, -- correct_tiles, Default: true
true, -- remove_colliding_entities, Default: true
true, -- remove_colliding_decoratives, Default: true
true) -- raise_event, Default: false
end
local function parse_variables(vars)
if not vars then return end
local parsed = {}
for _, var in pairs(vars) do
if var.type == "entity-expression" then
parsed[var.name] = expressions.entity(var.value)
elseif var.type == "number-expression" then
parsed[var.name] = expressions.number(var.value)
else
error("Unrecognized variable type: " .. var.type)
end
end
return parsed
end
local function clear_area(half_size, center, surface)
local area = util.area_from_center_and_half_size(half_size, center)
-- exclude tiles that we shouldn't spawn on
if surface.count_tiles_filtered{ area = area, limit = 1, collision_mask = {"item-layer", "object-layer"} } == 1 then
return false
end
for _, entity in pairs(surface.find_entities_filtered({area = area, type = {"resource"}, invert = true})) do
if (entity.valid and entity.type ~= "tree") or math.random() < (half_size / 14) then
entity.destroy({do_cliff_correction = true, raise_destroy = true})
end
end
return true
end
spawning.spawn_ruin = function(ruin, half_size, center, surface)
if surface.valid and clear_area(half_size, center, surface) then
local vars = parse_variables(ruin.variables)
spawn_entities(ruin.entities, center, surface, vars)
spawn_tiles(ruin.tiles, center, surface)
no_corpse_fade(half_size, center, surface)
end
end
spawning.spawn_random_ruin = function(ruins, half_size, center, surface)
--spawn a random ruin from the list
spawning.spawn_ruin(ruins[math.random(#ruins)], half_size, center, surface)
end
return spawning