mirror of
https://github.com/luanti-org/minetest_game.git
synced 2025-05-21 06:43:17 -04:00
Added meseors
This commit is contained in:
parent
8b50e7bf3d
commit
32d9ba2ff9
5 changed files with 321 additions and 0 deletions
36
mods/meseor/README.txt
Normal file
36
mods/meseor/README.txt
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
Compatible with Minetest 0.4.3 and later
|
||||||
|
Depends default
|
||||||
|
License WTFPL
|
||||||
|
|
||||||
|
* Warning, this mod can seriously damage maps, it is not 'on generated', instead impact is triggered by abm on dirt, grass, desert sand and sand. Unless testing in a new world you should edit the impact area and safe area in the init.lua.
|
||||||
|
|
||||||
|
* This first version is the fastest and simplest, also being compatible back to 0.4.3. Perhaps i will develop a more complex version for 0.4.6 including the new stuff like mese crystals, obsidian etc.
|
||||||
|
|
||||||
|
* Default parameters are for one impact every few minutes for your instant gratification, for normal use you might want to increase the abm interval and chance parameters. Personally i just add 1 or 2 zeros on the end of MSRCHA.
|
||||||
|
|
||||||
|
* The primary excavated nodes (stone, desert stone, dirt, grass, desert sand, sand, trees) are counted, the proportions calculated, then randomly layered around the crater in the same proportions and with the same total number of nodes, thickest at the crater rim and thinning inwards and outwards.
|
||||||
|
|
||||||
|
* Most stone is broken into gravel. Grass becomes dirt. Water, snow, plants are assumed to be vapourized and are not counted. As the ejected material is added it strips surrounding trees of their leaves.
|
||||||
|
|
||||||
|
* Damage is inflicted to nearby players depending on distance from impact point, by default a rare direct hit is fatal.
|
||||||
|
|
||||||
|
* There is a sound file for using your own choice of sound, the default sound is simply the pop of a dug node, it seems a good cute / abstract impact sound.
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.2.0
|
||||||
|
|
||||||
|
* Impacts can now be created on generated chunk as well as by abm, both are optional. By default only on generated impacts are enabled.
|
||||||
|
|
||||||
|
* By default on generated impacts are fairly common, you might want to increase parameter ONGCHA.
|
||||||
|
|
||||||
|
* On generated craters are limited to 16m radius, craters by abm can be up to 31m radius.
|
||||||
|
|
||||||
|
* On generated impacts are too distant to damage players.
|
||||||
|
|
||||||
|
* Compatible with default jungles, jungletree trunks are now counted and scattered.
|
||||||
|
|
||||||
|
* Meseor path is now excavated, single-node holes are punched in jungle canopies and in the ice above icecaves.
|
||||||
|
|
||||||
|
* Compatible with snow biomes mod, bugs fixed (nodes floating above snow, floating moss).
|
||||||
|
|
||||||
|
* Impact area and safe area apply to both on-gen and abm impacts.
|
1
mods/meseor/depends.txt
Normal file
1
mods/meseor/depends.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
default
|
270
mods/meseor/init.lua
Normal file
270
mods/meseor/init.lua
Normal file
|
@ -0,0 +1,270 @@
|
||||||
|
-- meseor 0.2.0 by paramat.
|
||||||
|
-- License WTFPL, see license.txt.
|
||||||
|
|
||||||
|
-- Parameters.
|
||||||
|
|
||||||
|
local ONGEN = true -- (true / false) Enable / disable impacts on generated chunk.
|
||||||
|
local ONGCHA = 9 -- 9 -- Ongen 1/x chance of impact per generated chunk.
|
||||||
|
|
||||||
|
local ABM = false -- Enable / disable impacts by abm on surface material.
|
||||||
|
local ABMINT = 181 -- 181 -- Abm interval.
|
||||||
|
local ABMCHA = 100000 -- 100000 -- Abm 1/x chance per node.
|
||||||
|
local DAMAGE = true -- Enable / disable player damage loop.
|
||||||
|
local DAMMAX = 20 -- 20 -- Maximum damage. 20 = direct hit is fatal.
|
||||||
|
|
||||||
|
local RADMIN = 3 -- 3 -- Minimum crater radius.
|
||||||
|
local RADMAX = 31 -- 31 -- Maximum crater radius, on-gen craters are limited to 16.
|
||||||
|
local STOCHA = 5 -- 5 -- 1/x chance of stone boulders instead of gravel.
|
||||||
|
|
||||||
|
local XMIN = -16000 -- Impact area dimensions. Impacts only inside this area.
|
||||||
|
local XMAX = 16000
|
||||||
|
local ZMIN = -16000
|
||||||
|
local ZMAX = 16000
|
||||||
|
|
||||||
|
local SAXMIN = 0 -- Safe area dimensions. No impacts inside this area.
|
||||||
|
local SAXMAX = 0 -- When overlapping impact area, the safe area overrides.
|
||||||
|
local SAZMIN = 0
|
||||||
|
local SAZMAX = 0
|
||||||
|
|
||||||
|
local DEBUG = true
|
||||||
|
|
||||||
|
-- Stuff.
|
||||||
|
|
||||||
|
meseor = {}
|
||||||
|
|
||||||
|
-- On generated.
|
||||||
|
|
||||||
|
if ONGEN then
|
||||||
|
minetest.register_on_generated(function(minp, maxp, seed)
|
||||||
|
if math.random(ONGCHA) == 2 then
|
||||||
|
local env = minetest.env
|
||||||
|
local maxrad = RADMAX
|
||||||
|
if maxrad > 16 then maxrad = 16 end
|
||||||
|
local conrad = math.random(RADMIN, maxrad)
|
||||||
|
local rimrad = math.ceil(conrad * 2.4)
|
||||||
|
local x = math.random(minp.x + rimrad, maxp.x - rimrad)
|
||||||
|
local z = math.random(minp.z + rimrad, maxp.z - rimrad)
|
||||||
|
-- Find surface with air above, abort if water found, ignore trees and ice.
|
||||||
|
local surfy = false
|
||||||
|
local aa = false
|
||||||
|
for y = maxp.y, minp.y, -1 do
|
||||||
|
local nodename = env:get_node({x=x,y=y,z=z}).name
|
||||||
|
if nodename == "default:water_source" or nodename == "default:water_flowing" then
|
||||||
|
return
|
||||||
|
elseif nodename == "air" then
|
||||||
|
aa = true
|
||||||
|
elseif aa and nodename ~= "air" and nodename ~= "ignore" and nodename ~= "snow:ice"
|
||||||
|
and nodename ~= "default:leaves" and nodename ~= "default:jungleleaves"
|
||||||
|
and nodename ~= "default:tree" and nodename ~= "default:jungletree" then
|
||||||
|
surfy = y
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not surfy then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
DAMAGE = false
|
||||||
|
crater({x=x,y=surfy,z=z},conrad)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Abm.
|
||||||
|
|
||||||
|
if ABM then
|
||||||
|
minetest.register_abm({
|
||||||
|
nodenames = {
|
||||||
|
"default:obsidian",
|
||||||
|
"moontest:dust",
|
||||||
|
},
|
||||||
|
interval = ABMINT,
|
||||||
|
chance = ABMCHA,
|
||||||
|
action = function(pos, node, _, _)
|
||||||
|
local env = minetest.env
|
||||||
|
local x = pos.x
|
||||||
|
local y = pos.y
|
||||||
|
local z = pos.z
|
||||||
|
-- Find close surface above, abort if underwater or no close surface found.
|
||||||
|
local surfy = false
|
||||||
|
for j = 1, 4 do
|
||||||
|
local nodename = env:get_node({x=x,y=y+j,z=z}).name
|
||||||
|
if nodename == "default:water_source" or nodename == "default:water_flowing" then
|
||||||
|
return
|
||||||
|
elseif nodename == "air" then
|
||||||
|
surfy = y+j-1
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not surfy then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local conrad = math.random(RADMIN, RADMAX)
|
||||||
|
crater({x=x,y=surfy,z=z},conrad)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Functions.
|
||||||
|
|
||||||
|
function crater(pos, conrad)
|
||||||
|
local env = minetest.env
|
||||||
|
local x = pos.x
|
||||||
|
local y = pos.y
|
||||||
|
local z = pos.z
|
||||||
|
local rimrad = math.ceil(conrad * 2.4)
|
||||||
|
-- If in safe zone or not in impact zone then abort.
|
||||||
|
if (x > SAXMIN - rimrad and x < SAXMAX + rimrad and z > SAZMIN - rimrad and z < SAZMAX + rimrad)
|
||||||
|
or not (x > XMIN and x < XMAX and z > ZMIN and z < ZMAX) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- Check enough depth.
|
||||||
|
for j = -conrad - 1, -1 do
|
||||||
|
local nodename = env:get_node({x=x,y=y+j,z=z}).name
|
||||||
|
if nodename == "air" or nodename == "ignore" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Check pos open to sky.
|
||||||
|
for j = 1, 160 do
|
||||||
|
local nodename = env:get_node({x=x,y=y+j,z=z}).name
|
||||||
|
if nodename ~= "air" and nodename ~= "ignore"
|
||||||
|
and nodename ~= "default:leaves" and nodename ~= "default:jungleleaves"
|
||||||
|
and nodename ~= "snow:ice" and nodename ~= "snow:needles" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Excavate path.
|
||||||
|
for j = 1, 160 do
|
||||||
|
local nodename = env:get_node({x=x,y=y+j,z=z}).name
|
||||||
|
if nodename ~= "air" and nodename ~= "ignore" then
|
||||||
|
env:remove_node({x=x,y=y+j,z=z})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Add meseorite.
|
||||||
|
env:add_node({x=x,y=y-conrad-1,z=z},{name="default:mese"})
|
||||||
|
-- Excavate cone and count excavated nodes.
|
||||||
|
local exsto = 0
|
||||||
|
local exdsto = 0
|
||||||
|
local exdirt = 0
|
||||||
|
local exdsan = 0
|
||||||
|
local exsan = 0
|
||||||
|
local extree = 0
|
||||||
|
local exjtree = 0
|
||||||
|
for j = 0, conrad * 2 do
|
||||||
|
for i = -j, j do
|
||||||
|
for k = -j, j do
|
||||||
|
if i ^ 2 + k ^ 2 <= j ^ 2 then
|
||||||
|
local exsno = false
|
||||||
|
local nodename = env:get_node({x=x+i,y=y-conrad+j,z=z+k}).name
|
||||||
|
if nodename == "default:stone" then
|
||||||
|
exsto = exsto + 1
|
||||||
|
elseif nodename == "default:desert_stone" then
|
||||||
|
exdsto = exdsto + 1
|
||||||
|
elseif nodename == "default:dirt" or nodename == "default:dirt_with_grass" then
|
||||||
|
exdirt = exdirt + 1
|
||||||
|
elseif nodename == "default:desert_sand" then
|
||||||
|
exdsan = exdsan + 1
|
||||||
|
elseif nodename == "default:sand" then
|
||||||
|
exsan = exsan + 1
|
||||||
|
elseif nodename == "default:tree" then
|
||||||
|
extree = extree + 1
|
||||||
|
elseif nodename == "default:jungletree" then
|
||||||
|
exjtree = exjtree + 1
|
||||||
|
elseif nodename == "snow:snow" then
|
||||||
|
exsno = true
|
||||||
|
end
|
||||||
|
if nodename ~= "air" then
|
||||||
|
env:remove_node({x=x+i,y=y-conrad+j,z=z+k})
|
||||||
|
end
|
||||||
|
if exsno then
|
||||||
|
env:remove_node({x=x+i,y=y-conrad+j,z=z+k})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Calculate proportions of ejecta.
|
||||||
|
local extot = exsto + exdsto + exdirt + exdsan + exsan + extree + exjtree
|
||||||
|
local pexsto = exsto / extot
|
||||||
|
local pexdsto = exdsto / extot
|
||||||
|
local pexdirt = exdirt / extot
|
||||||
|
local pexdsan = exdsan / extot
|
||||||
|
local pexsan = exsan / extot
|
||||||
|
local pextree = extree / extot
|
||||||
|
local pexjtree = exjtree / extot
|
||||||
|
-- Print to terminal.
|
||||||
|
if DEBUG then
|
||||||
|
print ("[meseor] Cone radius "..conrad.." node ("..x.." "..y.." "..z..")")
|
||||||
|
print ("[meseor] exsto "..exsto.." exdsto "..exdsto.." exdirt "..exdirt.." exdsan "..exdsan)
|
||||||
|
print ("[meseor] exsan "..exsan.." extree "..extree.." exjtree "..exjtree)
|
||||||
|
print ("[meseor] extot "..extot)
|
||||||
|
end
|
||||||
|
-- Add ejecta.
|
||||||
|
local addtot = 0
|
||||||
|
for rep = 1, 128 do
|
||||||
|
for i = -rimrad, rimrad do
|
||||||
|
for k = -rimrad, rimrad do
|
||||||
|
local rad = (i ^ 2 + k ^ 2) ^ 0.5
|
||||||
|
if rad <= rimrad and math.random() > math.abs(rad - conrad * 1.2) / (conrad * 1.2)
|
||||||
|
and addtot < extot and math.random(3) == 2 then
|
||||||
|
-- Find ground.
|
||||||
|
local groundy = false
|
||||||
|
for j = conrad - 1, -160, -1 do
|
||||||
|
local nodename = env:get_node({x=x+i,y=y+j,z=z+k}).name
|
||||||
|
if nodename == "default:leaves" or nodename == "default:jungleleaves"
|
||||||
|
or nodename == "default:papyrus" or nodename == "default:dry_shrub"
|
||||||
|
or nodename == "default:grass_1" or nodename == "default:grass_2"
|
||||||
|
or nodename == "default:grass_3" or nodename == "default:grass_4"
|
||||||
|
or nodename == "default:grass_5" or nodename == "default:apple"
|
||||||
|
or nodename == "default:junglegrass" or nodename == "snow:needles" then
|
||||||
|
env:remove_node({x=x+i,y=y+j,z=z+k})
|
||||||
|
elseif nodename ~= "air" and nodename ~= "ignore" and nodename ~= "snow:snow"
|
||||||
|
and nodename ~= "default:water_source" and nodename ~= "default:water_flowing" then
|
||||||
|
groundy = y+j
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if groundy then
|
||||||
|
local x = x + i
|
||||||
|
local y = groundy + 1
|
||||||
|
local z = z + k
|
||||||
|
if math.random() < pexjtree then
|
||||||
|
env:add_node({x=x,y=y,z=z},{name="default:jungletree"})
|
||||||
|
elseif math.random() < pextree then
|
||||||
|
env:add_node({x=x,y=y,z=z},{name="default:tree"})
|
||||||
|
elseif math.random() < pexsan then
|
||||||
|
env:add_node({x=x,y=y,z=z},{name="default:sand"})
|
||||||
|
elseif math.random() < pexdsan then
|
||||||
|
env:add_node({x=x,y=y,z=z},{name="default:desert_sand"})
|
||||||
|
elseif math.random() < pexdirt then
|
||||||
|
env:add_node({x=x,y=y,z=z},{name="default:dirt"})
|
||||||
|
elseif math.random() < pexdsto then
|
||||||
|
env:add_node({x=x,y=y,z=z},{name="default:desert_stone"})
|
||||||
|
elseif math.random() < pexsto then
|
||||||
|
if math.random(STOCHA) == 2 then
|
||||||
|
env:add_node({x=x,y=y,z=z},{name="default:stone"})
|
||||||
|
else
|
||||||
|
env:add_node({x=x,y=y,z=z},{name="default:gravel"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
addtot = addtot + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if addtot == extot then break end
|
||||||
|
end
|
||||||
|
-- Play sound.
|
||||||
|
minetest.sound_play("meseor", {gain = 1})
|
||||||
|
-- Damage player if inside rimrad.
|
||||||
|
if DAMAGE then
|
||||||
|
for _,player in ipairs(minetest.get_connected_players()) do
|
||||||
|
local plapos = player:getpos()
|
||||||
|
local pladis = ((plapos.x - x) ^ 2 + (plapos.y - y) ^ 2 + (plapos.z - z) ^ 2) ^ 0.5
|
||||||
|
local pladam = math.ceil((1 - pladis / rimrad) * DAMMAX)
|
||||||
|
if pladam > 0 then
|
||||||
|
player:set_hp(player:get_hp() - pladam)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
14
mods/meseor/license.txt
Normal file
14
mods/meseor/license.txt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
Version 2, December 2004
|
||||||
|
|
||||||
|
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||||
|
|
BIN
mods/meseor/sounds/meseor.ogg
Normal file
BIN
mods/meseor/sounds/meseor.ogg
Normal file
Binary file not shown.
Loading…
Add table
Reference in a new issue