commit | author | age
|
1da213
|
1 |
--[[ |
S |
2 |
Radioactivity |
|
3 |
|
|
4 |
Radiation resistance represents the extent to which a material |
|
5 |
attenuates radiation passing through it; i.e., how good a radiation |
|
6 |
shield it is. This is identified per node type. For materials that |
|
7 |
exist in real life, the radiation resistance value that this system |
|
8 |
uses for a node type consisting of a solid cube of that material is the |
|
9 |
(approximate) number of halvings of ionising radiation that is achieved |
|
10 |
by a meter of the material in real life. This is approximately |
|
11 |
proportional to density, which provides a good way to estimate it. |
|
12 |
Homogeneous mixtures of materials have radiation resistance computed |
|
13 |
by a simple weighted mean. Note that the amount of attenuation that |
|
14 |
a material achieves in-game is not required to be (and is not) the |
|
15 |
same as the attenuation achieved in real life. |
|
16 |
|
|
17 |
Radiation resistance for a node type may be specified in the node |
|
18 |
definition, under the key "radiation_resistance". As an interim |
|
19 |
measure, until node definitions widely include this, this code |
|
20 |
knows a bunch of values for particular node types in several mods, |
|
21 |
and values for groups of node types. The node definition takes |
|
22 |
precedence if it specifies a value. Nodes for which no value at |
|
23 |
all is known are taken to provide no radiation resistance at all; |
|
24 |
this is appropriate for the majority of node types. Only node types |
|
25 |
consisting of a fairly homogeneous mass of material should report |
|
26 |
non-zero radiation resistance; anything with non-uniform geometry |
|
27 |
or complex internal structure should show no radiation resistance. |
|
28 |
Fractional resistance values are permitted. |
|
29 |
--]] |
|
30 |
|
|
31 |
local S = technic.getter |
|
32 |
|
|
33 |
local rad_resistance_node = { |
|
34 |
["default:brick"] = 13, |
|
35 |
["default:bronzeblock"] = 45, |
|
36 |
["default:clay"] = 15, |
|
37 |
["default:coalblock"] = 9.6, |
|
38 |
["default:cobble"] = 15, |
|
39 |
["default:copperblock"] = 46, |
|
40 |
["default:desert_cobble"] = 15, |
|
41 |
["default:desert_sand"] = 10, |
|
42 |
["default:desert_stone"] = 17, |
|
43 |
["default:desert_stonebrick"] = 17, |
|
44 |
["default:diamondblock"] = 24, |
|
45 |
["default:dirt"] = 8.2, |
|
46 |
["default:dirt_with_grass"] = 8.2, |
|
47 |
["default:dirt_with_grass_footsteps"] = 8.2, |
|
48 |
["default:dirt_with_snow"] = 8.2, |
|
49 |
["default:glass"] = 17, |
|
50 |
["default:goldblock"] = 170, |
|
51 |
["default:gravel"] = 10, |
|
52 |
["default:ice"] = 5.6, |
|
53 |
["default:lava_flowing"] = 8.5, |
|
54 |
["default:lava_source"] = 17, |
|
55 |
["default:mese"] = 21, |
|
56 |
["default:mossycobble"] = 15, |
df15a5
|
57 |
["pbj_pup:pbj_pup"] = 10000, |
VE |
58 |
["pbj_pup:pbj_pup_candies"] = 10000, |
383f7d
|
59 |
["gloopblocks:rainbow_block_diagonal"] = 5000, |
VE |
60 |
["gloopblocks:rainbow_block_horizontal"] = 10000, |
cb5e3e
|
61 |
["default:nyancat"] = 10000, |
VE |
62 |
["default:nyancat_rainbow"] = 10000, |
|
63 |
["nyancat:nyancat"] = 10000, |
|
64 |
["nyancat:nyancat_rainbow"] = 10000, |
1da213
|
65 |
["default:obsidian"] = 18, |
S |
66 |
["default:obsidian_glass"] = 18, |
|
67 |
["default:sand"] = 10, |
|
68 |
["default:sandstone"] = 15, |
|
69 |
["default:sandstonebrick"] = 15, |
|
70 |
["default:snowblock"] = 1.7, |
|
71 |
["default:steelblock"] = 40, |
|
72 |
["default:stone"] = 17, |
|
73 |
["default:stone_with_coal"] = 16, |
|
74 |
["default:stone_with_copper"] = 20, |
|
75 |
["default:stone_with_diamond"] = 18, |
|
76 |
["default:stone_with_gold"] = 34, |
|
77 |
["default:stone_with_iron"] = 20, |
|
78 |
["default:stone_with_mese"] = 17, |
|
79 |
["default:stonebrick"] = 17, |
|
80 |
["default:water_flowing"] = 2.8, |
|
81 |
["default:water_source"] = 5.6, |
|
82 |
["farming:desert_sand_soil"] = 10, |
|
83 |
["farming:desert_sand_soil_wet"] = 10, |
|
84 |
["farming:soil"] = 8.2, |
|
85 |
["farming:soil_wet"] = 8.2, |
|
86 |
["glooptest:akalin_crystal_glass"] = 21, |
|
87 |
["glooptest:akalinblock"] = 40, |
|
88 |
["glooptest:alatro_crystal_glass"] = 21, |
|
89 |
["glooptest:alatroblock"] = 40, |
|
90 |
["glooptest:amethystblock"] = 18, |
|
91 |
["glooptest:arol_crystal_glass"] = 21, |
|
92 |
["glooptest:crystal_glass"] = 21, |
|
93 |
["glooptest:emeraldblock"] = 19, |
|
94 |
["glooptest:heavy_crystal_glass"] = 21, |
|
95 |
["glooptest:mineral_akalin"] = 20, |
|
96 |
["glooptest:mineral_alatro"] = 20, |
|
97 |
["glooptest:mineral_amethyst"] = 17, |
|
98 |
["glooptest:mineral_arol"] = 20, |
|
99 |
["glooptest:mineral_desert_coal"] = 16, |
|
100 |
["glooptest:mineral_desert_iron"] = 20, |
|
101 |
["glooptest:mineral_emerald"] = 17, |
|
102 |
["glooptest:mineral_kalite"] = 20, |
|
103 |
["glooptest:mineral_ruby"] = 18, |
|
104 |
["glooptest:mineral_sapphire"] = 18, |
|
105 |
["glooptest:mineral_talinite"] = 20, |
|
106 |
["glooptest:mineral_topaz"] = 18, |
|
107 |
["glooptest:reinforced_crystal_glass"] = 21, |
|
108 |
["glooptest:rubyblock"] = 27, |
|
109 |
["glooptest:sapphireblock"] = 27, |
|
110 |
["glooptest:talinite_crystal_glass"] = 21, |
|
111 |
["glooptest:taliniteblock"] = 40, |
|
112 |
["glooptest:topazblock"] = 24, |
|
113 |
["mesecons_extrawires:mese_powered"] = 21, |
|
114 |
["moreblocks:cactus_brick"] = 13, |
|
115 |
["moreblocks:cactus_checker"] = 8.5, |
|
116 |
["moreblocks:circle_stone_bricks"] = 17, |
|
117 |
["moreblocks:clean_glass"] = 17, |
|
118 |
["moreblocks:coal_checker"] = 9.0, |
|
119 |
["moreblocks:coal_glass"] = 17, |
|
120 |
["moreblocks:coal_stone"] = 17, |
|
121 |
["moreblocks:coal_stone_bricks"] = 17, |
|
122 |
["moreblocks:glow_glass"] = 17, |
|
123 |
["moreblocks:grey_bricks"] = 15, |
|
124 |
["moreblocks:iron_checker"] = 11, |
|
125 |
["moreblocks:iron_glass"] = 17, |
|
126 |
["moreblocks:iron_stone"] = 17, |
|
127 |
["moreblocks:iron_stone_bricks"] = 17, |
|
128 |
["moreblocks:plankstone"] = 9.3, |
|
129 |
["moreblocks:split_stone_tile"] = 15, |
|
130 |
["moreblocks:split_stone_tile_alt"] = 15, |
|
131 |
["moreblocks:stone_tile"] = 15, |
|
132 |
["moreblocks:super_glow_glass"] = 17, |
|
133 |
["moreblocks:tar"] = 7.0, |
|
134 |
["moreblocks:wood_tile"] = 1.7, |
|
135 |
["moreblocks:wood_tile_center"] = 1.7, |
|
136 |
["moreblocks:wood_tile_down"] = 1.7, |
|
137 |
["moreblocks:wood_tile_flipped"] = 1.7, |
|
138 |
["moreblocks:wood_tile_full"] = 1.7, |
|
139 |
["moreblocks:wood_tile_left"] = 1.7, |
|
140 |
["moreblocks:wood_tile_right"] = 1.7, |
|
141 |
["moreblocks:wood_tile_up"] = 1.7, |
|
142 |
["moreores:mineral_mithril"] = 18, |
|
143 |
["moreores:mineral_silver"] = 21, |
|
144 |
["moreores:mineral_tin"] = 19, |
|
145 |
["moreores:mithril_block"] = 26, |
|
146 |
["moreores:silver_block"] = 53, |
|
147 |
["moreores:tin_block"] = 37, |
|
148 |
["snow:snow_brick"] = 2.8, |
|
149 |
["technic:brass_block"] = 43, |
|
150 |
["technic:carbon_steel_block"] = 40, |
|
151 |
["technic:cast_iron_block"] = 40, |
|
152 |
["technic:chernobylite_block"] = 40, |
|
153 |
["technic:chromium_block"] = 37, |
|
154 |
["technic:corium_flowing"] = 40, |
|
155 |
["technic:corium_source"] = 80, |
|
156 |
["technic:granite"] = 18, |
|
157 |
["technic:lead_block"] = 80, |
|
158 |
["technic:marble"] = 18, |
|
159 |
["technic:marble_bricks"] = 18, |
|
160 |
["technic:mineral_chromium"] = 19, |
|
161 |
["technic:mineral_uranium"] = 71, |
|
162 |
["technic:mineral_zinc"] = 19, |
|
163 |
["technic:stainless_steel_block"] = 40, |
|
164 |
["technic:zinc_block"] = 36, |
|
165 |
["tnt:tnt"] = 11, |
|
166 |
["tnt:tnt_burning"] = 11, |
|
167 |
} |
|
168 |
local rad_resistance_group = { |
|
169 |
concrete = 16, |
|
170 |
tree = 3.4, |
|
171 |
uranium_block = 500, |
|
172 |
wood = 1.7, |
|
173 |
} |
|
174 |
local cache_radiation_resistance = {} |
|
175 |
local function node_radiation_resistance(node_name) |
|
176 |
local resistance = cache_radiation_resistance[node_name] |
|
177 |
if resistance then |
|
178 |
return resistance |
|
179 |
end |
|
180 |
local def = minetest.registered_nodes[node_name] |
|
181 |
if not def then |
|
182 |
cache_radiation_resistance[node_name] = 0 |
|
183 |
return 0 |
|
184 |
end |
|
185 |
resistance = def.radiation_resistance or |
|
186 |
rad_resistance_node[node_name] |
|
187 |
if not resistance then |
|
188 |
resistance = 0 |
|
189 |
for g, v in pairs(def.groups) do |
|
190 |
if v > 0 and rad_resistance_group[g] then |
|
191 |
resistance = resistance + rad_resistance_group[g] |
|
192 |
end |
|
193 |
end |
|
194 |
end |
|
195 |
resistance = math.sqrt(resistance) |
|
196 |
cache_radiation_resistance[node_name] = resistance |
|
197 |
return resistance |
|
198 |
end |
|
199 |
|
|
200 |
|
|
201 |
--[[ |
|
202 |
Radioactive nodes cause damage to nearby players. The damage |
|
203 |
effect depends on the intrinsic strength of the radiation source, |
|
204 |
the distance between the source and the player, and the shielding |
|
205 |
effect of the intervening material. These determine a rate of damage; |
|
206 |
total damage caused is the integral of this over time. |
|
207 |
|
|
208 |
In the absence of effective shielding, for a specific source the |
|
209 |
damage rate varies realistically in inverse proportion to the square |
|
210 |
of the distance. (Distance is measured to the player's abdomen, |
|
211 |
not to the nominal player position which corresponds to the foot.) |
|
212 |
However, if the player is inside a non-walkable (liquid or gaseous) |
|
213 |
radioactive node, the nominal distance could go to zero, yielding |
|
214 |
infinite damage. In that case, the player's body is displacing the |
|
215 |
radioactive material, so the effective distance should remain non-zero. |
|
216 |
We therefore apply a lower distance bound of sqrt(0.75), which is |
|
217 |
the maximum distance one can get from the node center within the node. |
|
218 |
|
|
219 |
A radioactive node is identified by being in the "radioactive" group, |
|
220 |
and the group value signifies the strength of the radiation source. |
|
221 |
The group value is the distance from a node at which an unshielded |
|
222 |
player will be damaged by 1 HP/s. Or, equivalently, it is the square |
|
223 |
root of the damage rate in HP/s that an unshielded player one node |
|
224 |
away will take. |
|
225 |
|
|
226 |
Shielding is assessed by adding the shielding values of all nodes |
|
227 |
between the source node and the player, ignoring the source node itself. |
|
228 |
As in reality, shielding causes exponential attenuation of radiation. |
|
229 |
However, the effect is scaled down relative to real life. A node with |
|
230 |
radiation resistance value R yields attenuation of sqrt(R) * 0.1 nepers. |
|
231 |
(In real life it would be about R * 0.69 nepers, by the definition |
|
232 |
of the radiation resistance values.) The sqrt part of this formula |
|
233 |
scales down the differences between shielding types, reflecting the |
|
234 |
game's simplification of making expensive materials such as gold |
|
235 |
readily available in cubes. The multiplicative factor in the |
|
236 |
formula scales down the difference between shielded and unshielded |
|
237 |
safe distances, avoiding the latter becoming impractically large. |
|
238 |
|
06dec2
|
239 |
Damage is processed at rates down to 0.2 HP/s, which in the absence of |
1da213
|
240 |
shielding is attained at the distance specified by the "radioactive" |
06dec2
|
241 |
group value. Computed damage rates below 0.2 HP/s result in no |
1da213
|
242 |
damage at all to the player. This gives the player an opportunity |
S |
243 |
to be safe, and limits the range at which source/player interactions |
|
244 |
need to be considered. |
|
245 |
--]] |
|
246 |
local abdomen_offset = 1 |
|
247 |
local cache_scaled_shielding = {} |
06dec2
|
248 |
local rad_dmg_cutoff = 0.2 |
S |
249 |
local radiated_players = {} |
1da213
|
250 |
|
cbe974
|
251 |
local armor_enabled = technic.config:get_bool("enable_radiation_protection") |
b739ed
|
252 |
local entity_damage = technic.config:get_bool("enable_entity_radiation_damage") |
NZ |
253 |
local longterm_damage = technic.config:get_bool("enable_longterm_radiation_damage") |
|
254 |
|
06dec2
|
255 |
local function apply_fractional_damage(o, dmg) |
1da213
|
256 |
local dmg_int = math.floor(dmg) |
S |
257 |
-- The closer you are to getting one more damage point, |
|
258 |
-- the more likely it will be added. |
|
259 |
if math.random() < dmg - dmg_int then |
|
260 |
dmg_int = dmg_int + 1 |
|
261 |
end |
|
262 |
if dmg_int > 0 then |
06dec2
|
263 |
local new_hp = math.max(o:get_hp() - dmg_int, 0) |
S |
264 |
o:set_hp(new_hp) |
|
265 |
return new_hp == 0 |
1da213
|
266 |
end |
06dec2
|
267 |
return false |
S |
268 |
end |
|
269 |
|
1810f4
|
270 |
local function calculate_base_damage(node_pos, object_pos, strength) |
06dec2
|
271 |
local shielding = 0 |
1810f4
|
272 |
local dist = vector.distance(node_pos, object_pos) |
06dec2
|
273 |
|
1810f4
|
274 |
for ray_pos in technic.trace_node_ray(node_pos, |
NZ |
275 |
vector.direction(node_pos, object_pos), dist) do |
06dec2
|
276 |
local shield_name = minetest.get_node(ray_pos).name |
51be33
|
277 |
shielding = shielding + node_radiation_resistance(shield_name) * 0.025 |
06dec2
|
278 |
end |
S |
279 |
|
|
280 |
local dmg = (strength * strength) / |
|
281 |
(math.max(0.75, dist * dist) * math.exp(shielding)) |
|
282 |
|
|
283 |
if dmg < rad_dmg_cutoff then return end |
1810f4
|
284 |
return dmg |
NZ |
285 |
end |
06dec2
|
286 |
|
1810f4
|
287 |
local function calculate_damage_multiplier(object) |
NZ |
288 |
local ag = object.get_armor_groups and object:get_armor_groups() |
|
289 |
if not ag then |
|
290 |
return 0 |
|
291 |
end |
73afc4
|
292 |
if ag.immortal then |
NZ |
293 |
return 0 |
|
294 |
end |
1810f4
|
295 |
if ag.radiation then |
NZ |
296 |
return 0.01 * ag.radiation |
|
297 |
end |
|
298 |
if ag.fleshy then |
|
299 |
return math.sqrt(0.01 * ag.fleshy) |
|
300 |
end |
|
301 |
return 0 |
|
302 |
end |
|
303 |
|
|
304 |
local function calculate_object_center(object) |
|
305 |
if object:is_player() then |
|
306 |
return {x=0, y=abdomen_offset, z=0} |
|
307 |
end |
|
308 |
return {x=0, y=0, z=0} |
|
309 |
end |
|
310 |
|
|
311 |
local function dmg_object(pos, object, strength) |
|
312 |
local obj_pos = vector.add(object:getpos(), calculate_object_center(object)) |
cbe974
|
313 |
local mul |
NZ |
314 |
if armor_enabled or entity_damage then |
|
315 |
-- we need to check may the object be damaged even if armor is disabled |
|
316 |
mul = calculate_damage_multiplier(object) |
|
317 |
if mul == 0 then |
|
318 |
return |
|
319 |
end |
1810f4
|
320 |
end |
b739ed
|
321 |
local dmg = calculate_base_damage(pos, obj_pos, strength) |
NZ |
322 |
if not dmg then |
|
323 |
return |
|
324 |
end |
cbe974
|
325 |
if armor_enabled then |
NZ |
326 |
dmg = dmg * mul |
|
327 |
end |
1810f4
|
328 |
apply_fractional_damage(object, dmg) |
b739ed
|
329 |
if longterm_damage and object:is_player() then |
1810f4
|
330 |
local pn = object:get_player_name() |
NZ |
331 |
radiated_players[pn] = (radiated_players[pn] or 0) + dmg |
|
332 |
end |
1da213
|
333 |
end |
S |
334 |
|
|
335 |
local rad_dmg_mult_sqrt = math.sqrt(1 / rad_dmg_cutoff) |
|
336 |
local function dmg_abm(pos, node) |
|
337 |
local strength = minetest.get_item_group(node.name, "radioactive") |
|
338 |
local max_dist = strength * rad_dmg_mult_sqrt |
|
339 |
for _, o in pairs(minetest.get_objects_inside_radius(pos, |
|
340 |
max_dist + abdomen_offset)) do |
b739ed
|
341 |
if entity_damage or o:is_player() then |
NZ |
342 |
dmg_object(pos, o, strength) |
|
343 |
end |
1da213
|
344 |
end |
S |
345 |
end |
|
346 |
|
|
347 |
if minetest.setting_getbool("enable_damage") then |
|
348 |
minetest.register_abm({ |
|
349 |
nodenames = {"group:radioactive"}, |
|
350 |
interval = 1, |
|
351 |
chance = 1, |
|
352 |
action = dmg_abm, |
|
353 |
}) |
06dec2
|
354 |
|
b739ed
|
355 |
if longterm_damage then |
NZ |
356 |
minetest.register_globalstep(function(dtime) |
|
357 |
for pn, dmg in pairs(radiated_players) do |
|
358 |
dmg = dmg - (dtime / 8) |
|
359 |
local player = minetest.get_player_by_name(pn) |
|
360 |
local killed |
|
361 |
if player and dmg > rad_dmg_cutoff then |
|
362 |
killed = apply_fractional_damage(player, (dmg * dtime) / 8) |
|
363 |
else |
|
364 |
dmg = nil |
|
365 |
end |
|
366 |
-- on_dieplayer will have already set this if the player died |
|
367 |
if not killed then |
|
368 |
radiated_players[pn] = dmg |
|
369 |
end |
06dec2
|
370 |
end |
b739ed
|
371 |
end) |
06dec2
|
372 |
|
b739ed
|
373 |
minetest.register_on_dieplayer(function(player) |
NZ |
374 |
radiated_players[player:get_player_name()] = nil |
|
375 |
end) |
|
376 |
end |
1da213
|
377 |
end |
S |
378 |
|
|
379 |
-- Radioactive materials that can result from destroying a reactor |
|
380 |
local griefing = technic.config:get_bool("enable_corium_griefing") |
|
381 |
|
|
382 |
for _, state in pairs({"flowing", "source"}) do |
|
383 |
minetest.register_node("technic:corium_"..state, { |
|
384 |
description = S(state == "source" and "Corium Source" or "Flowing Corium"), |
|
385 |
drawtype = (state == "source" and "liquid" or "flowingliquid"), |
|
386 |
[state == "source" and "tiles" or "special_tiles"] = {{ |
|
387 |
name = "technic_corium_"..state.."_animated.png", |
|
388 |
animation = { |
|
389 |
type = "vertical_frames", |
|
390 |
aspect_w = 16, |
|
391 |
aspect_h = 16, |
|
392 |
length = 3.0, |
|
393 |
}, |
|
394 |
}}, |
|
395 |
paramtype = "light", |
|
396 |
paramtype2 = (state == "flowing" and "flowingliquid" or nil), |
|
397 |
light_source = (state == "source" and 8 or 5), |
|
398 |
walkable = false, |
|
399 |
pointable = false, |
|
400 |
diggable = false, |
|
401 |
buildable_to = true, |
|
402 |
drop = "", |
|
403 |
drowning = 1, |
|
404 |
liquidtype = state, |
|
405 |
liquid_alternative_flowing = "technic:corium_flowing", |
|
406 |
liquid_alternative_source = "technic:corium_source", |
|
407 |
liquid_viscosity = LAVA_VISC, |
|
408 |
liquid_renewable = false, |
|
409 |
damage_per_second = 6, |
|
410 |
post_effect_color = {a=192, r=80, g=160, b=80}, |
|
411 |
groups = { |
|
412 |
liquid = 2, |
|
413 |
hot = 3, |
|
414 |
igniter = (griefing and 1 or 0), |
06dec2
|
415 |
radioactive = (state == "source" and 12 or 6), |
1da213
|
416 |
not_in_creative_inventory = (state == "flowing" and 1 or nil), |
S |
417 |
}, |
|
418 |
}) |
|
419 |
end |
|
420 |
|
|
421 |
if rawget(_G, "bucket") and bucket.register_liquid then |
|
422 |
bucket.register_liquid( |
|
423 |
"technic:corium_source", |
|
424 |
"technic:corium_flowing", |
|
425 |
"technic:bucket_corium", |
|
426 |
"technic_bucket_corium.png", |
|
427 |
"Corium Bucket" |
|
428 |
) |
|
429 |
end |
|
430 |
|
|
431 |
minetest.register_node("technic:chernobylite_block", { |
|
432 |
description = S("Chernobylite Block"), |
|
433 |
tiles = {"technic_chernobylite_block.png"}, |
|
434 |
is_ground_content = true, |
06dec2
|
435 |
groups = {cracky=1, radioactive=4, level=2}, |
1da213
|
436 |
sounds = default.node_sound_stone_defaults(), |
S |
437 |
light_source = 2, |
|
438 |
}) |
|
439 |
|
|
440 |
minetest.register_abm({ |
|
441 |
nodenames = {"group:water"}, |
|
442 |
neighbors = {"technic:corium_source"}, |
|
443 |
interval = 1, |
|
444 |
chance = 1, |
|
445 |
action = function(pos, node) |
|
446 |
minetest.remove_node(pos) |
|
447 |
end, |
|
448 |
}) |
|
449 |
|
|
450 |
minetest.register_abm({ |
|
451 |
nodenames = {"technic:corium_flowing"}, |
|
452 |
neighbors = {"group:water"}, |
|
453 |
interval = 1, |
|
454 |
chance = 1, |
|
455 |
action = function(pos, node) |
|
456 |
minetest.set_node(pos, {name="technic:chernobylite_block"}) |
|
457 |
end, |
|
458 |
}) |
|
459 |
|
|
460 |
minetest.register_abm({ |
|
461 |
nodenames = {"technic:corium_flowing"}, |
|
462 |
interval = 5, |
|
463 |
chance = (griefing and 10 or 1), |
|
464 |
action = function(pos, node) |
|
465 |
minetest.set_node(pos, {name="technic:chernobylite_block"}) |
|
466 |
end, |
|
467 |
}) |
|
468 |
|
|
469 |
if griefing then |
|
470 |
minetest.register_abm({ |
|
471 |
nodenames = {"technic:corium_source", "technic:corium_flowing"}, |
|
472 |
interval = 4, |
|
473 |
chance = 4, |
|
474 |
action = function(pos, node) |
|
475 |
for _, offset in ipairs({ |
|
476 |
vector.new(1,0,0), |
|
477 |
vector.new(-1,0,0), |
|
478 |
vector.new(0,0,1), |
|
479 |
vector.new(0,0,-1), |
|
480 |
vector.new(0,-1,0), |
|
481 |
}) do |
|
482 |
if math.random(8) == 1 then |
|
483 |
minetest.dig_node(vector.add(pos, offset)) |
|
484 |
end |
|
485 |
end |
|
486 |
end, |
|
487 |
}) |
|
488 |
end |
|
489 |
|