Added meseors

This commit is contained in:
Amaz1 2014-05-13 20:54:33 +01:00
parent 8b50e7bf3d
commit 32d9ba2ff9
5 changed files with 321 additions and 0 deletions

36
mods/meseor/README.txt Normal file
View 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
View file

@ -0,0 +1 @@
default

270
mods/meseor/init.lua Normal file
View 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
View 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.

Binary file not shown.