123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678 |
- local FREQ_BIAS = -.6
- local FREQ_SCALE = 3
- local SPEED = .02
- local fns = {
- on_strike = {},
- freq_bias = {},
- intens_bias = {},
- heat_bias = {},
- humidity_bias = {},
- }
- storms = {
- }
- local perlins = {}
- local sounds = {
- thunder = {
- "storms_thunder_01_ccby_hantorio",
- "storms_thunder_01_ccby_hantorio",
- -- "storms_thunder_02_PD",
- "storms_thunder_03_PD",
- },
- }
- local function color_lerp(a, b, x)
- local x1 = 1.0 - x
-
- return {
- r = a.r * x1 + b.r * x,
- g = a.g * x1 + b.g * x,
- b = a.b * x1 + b.b * x,
- -- a = a.a * x1 + b.a * x,
- }
- end
- storms.register_on_lightning_strike = function(fn)
- table.insert(fns.on_strike, fn)
- end
- storms.register_freq_bias = function(fn)
- table.insert(fns.freq_bias, fn)
- end
- storms.register_intensity_bias = function(fn)
- table.insert(fns.intens_bias, fn)
- end
- storms.register_heat_bias = function(fn)
- table.insert(fns.heat_bias, fn)
- end
- storms.register_humidity_bias = function(fn)
- table.insert(fns.humidty_bias, fn)
- end
- local function get_intens_bias(pos, orig_intens, player)
- local bias = 0
- for _,fn in ipairs(fns.intens_bias) do
- bias = bias + fn(pos, orig_intens, player)
- end
- return bias
- end
- local function get_freq_bias(pos, orig_freq, player)
- local bias = 0
- for _,fn in ipairs(fns.freq_bias) do
- bias = bias + fn(pos, orig_freq, player)
- end
- return bias
- end
- local function get_heat_bias(pos, orig)
- local bias = 0
- for _,fn in ipairs(fns.heat_bias) do
- bias = bias + fn(pos, orig)
- end
- return bias
- end
- local function get_humidity_bias(pos, orig)
- local bias = 0
- for _,fn in ipairs(fns.humidity_bias) do
- bias = bias + fn(pos, orig)
- end
- return bias
- end
- local on = false
- local storm_players = {}
- local good_biomes = {}
- for _,def in pairs(minetest.registered_biomes) do
- if def.y_max >= 10 and def.y_min <= 10 then
- table.insert(good_biomes, def)
- end
- end
- local function get_noise(pos)
- return heat_noise:get2d({x=pos.x, y=pos.z}), humidity_noise:get2d({x=pos.x, y=pos.z})
- end
- local function find_biome(he, hu)
- local smallest = 99999999999
- local tmp = nil
-
- for _,def in pairs(good_biomes) do
- local a = he - def.heat_point
- local b = hu - def.humidity_point
- local c = math.sqrt(a*a + b*b)
- if c < smallest then
- smallest = c
- tmp = def
- end
- end
-
- return tmp.name
- end
- local function get_biome(pos)
- local he, hu = get_noise(pos)
- he = he + get_heat_bias(pos, he)
- hu = hu + get_humidity_bias(pos, hu)
-
- return find_biome(he, hu)
- end
- minetest.after(0, function()
- local noise = minetest.get_mapgen_setting_noiseparams("mg_biome_np_heat")
- heat_noise = minetest.get_perlin(noise)
-
- noise = minetest.get_mapgen_setting_noiseparams("mg_biome_np_humidity")
- humidity_noise = minetest.get_perlin(noise)
- end)
- local function randompos(center, dist)
- return {
- x = center.x + math.random(-dist, dist),
- y = center.y,
- z = center.z + math.random(-dist, dist),
- }
- end
- local function pcopy(p)
- return {x=p.x, y=p.y, z=p.z}
- end
- local function do_lightning(cloudh, pos)
-
- local h = cloudh - 10
-
- while h > -15 do
- minetest.add_particle({
- pos = {x=pos.x, y=h, z=pos.z},
- velocity = {x=0, y=0, z=0},
- acceleration = {x=0, y=0, z=0},
- expirationtime = .1,
- size = 300,
- collisiondetection = false,
- vertical = true,
- texture = "storms_lightning.png",
- playername = "singleplayer"
- })
-
- h = h - 30
- end
-
- local p = {x=pos.x, y=cloudh, z=pos.z}
- while p.y >= -1 do
- local n = minetest.get_node(p)
- if n.name ~= "air" and n.name ~= "ignore" then
-
- -- node callbacks
- local def = minetest.registered_nodes[n.name]
- if def.on_lightning_strike then
- def.on_lightning_strike(pcopy(p))
- end
-
- -- global callbacks
- for _,fn in pairs(fns.on_strike) do
- fn(pcopy(p), n)
- end
-
- break
- end
-
- p.y = p.y - 1
- end
-
- minetest.sound_play(sounds.thunder[math.random(#sounds.thunder)], {
- pos = p,
- max_hear_distance = 100,
- gain = 5.0,
- })
-
- end
- local function spawn_blizzard(pos, vel, sz)
- local ht = 7
- minetest.add_particlespawner({
- amount = 4000,
- time = 5,
- minpos = vector.add({x=pos.x-sz, y=pos.y-ht, z=pos.z-sz}, vector.multiply(vel, -.95)),
- maxpos = vector.add({x=pos.x+sz, y=pos.y+ht, z=pos.z+sz}, vector.multiply(vel, -.95)),
- minvel = vector.add(vel, {x=-1, y=0, z=-1}),
- maxvel = vector.add(vel, {x=5, y=0.5, z=5}),
- minacc = {x=-01.1, y=0.1, z=-01.1},
- maxacc = {x=01.1, y=01.3, z=01.1},
- minexptime = 1.5,
- maxexptime = 2.5,
- collisiondetection = true,
- collision_removal = true,
- minsize = 40,
- maxsize = 45,
- texture = "storms_snow.png",
- })
- end
- local function spawn_sandstorm(pos, vel, sz, lvl)
- local ht = 7
- minetest.add_particlespawner({
- amount = lvl * 5000,
- time = 5,
- minpos = vector.add({x=pos.x-sz, y=pos.y-ht, z=pos.z-sz}, vector.multiply(vel, -.95)),
- maxpos = vector.add({x=pos.x+sz, y=pos.y+ht, z=pos.z+sz}, vector.multiply(vel, -.95)),
- minvel = vector.add(vel, {x=-1, y=0, z=-1}),
- maxvel = vector.add(vel, {x=5, y=0.5, z=5}),
- minacc = {x=-01.1, y=0.1, z=-01.1},
- maxacc = {x=01.1, y=01.3, z=01.1},
- minexptime = 1.5,
- maxexptime = 2.5,
- collisiondetection = true,
- collision_removal = true,
- minsize = 40,
- maxsize = 45,
- texture = "storms_dust.png",
- })
- end
- local function spawn_rainclouds(pos, vel, sz, lvl)
- local offht = 60
- local ht = 10
- minetest.add_particlespawner({
- amount = lvl * 5000,
- time = 5,
- minpos = {x=pos.x-sz, y=pos.y+offht, z=pos.z-sz},
- maxpos = {x=pos.x+sz, y=pos.y+offht+ht, z=pos.z+sz},
- minvel = vector.add(vel, {x=-1, y=0, z=-1}),
- maxvel = vector.add(vel, {x=5, y=0.5, z=5}),
- minacc = {x=-0.1, y=0.1, z=-0.1},
- maxacc = {x=0.1, y=0.3, z=0.1},
- minexptime = 2,
- maxexptime = 7,
- minsize = 300,
- maxsize = 400,
- texture = "storms_cloud.png^[colorize:black:120",
- })
- end
- local function spawn_rain(pos, vel, sz, lvl)
- local offht = 10
- local ht = 10
-
- minetest.add_particlespawner({
- amount = lvl * 1000,
- time = 5,
- minpos = {x=pos.x-sz, y=pos.y+offht, z=pos.z-sz},
- maxpos = {x=pos.x+sz, y=pos.y+offht+ht, z=pos.z+sz},
- minvel = {x=vel.x, y=-40, z=vel.z},
- maxvel = {x=vel.x, y=-40, z=vel.z},
- minacc = {x=-0.1, y=0.1, z=-0.1},
- maxacc = {x=0.1, y=0.3, z=0.1},
- collisiondetection = true,
- collision_removal = true,
- minexptime = 2,
- maxexptime = 7,
- minsize = 10,
- maxsize = 15,
- texture = "storms_raindrop.png",
- })
- end
- local function spawn_snow(pos, vel, sz, lvl)
- local offht = 10
- local ht = 10
-
- minetest.add_particlespawner({
- amount = lvl * 1000,
- time = 5,
- minpos = {x=pos.x-sz, y=pos.y+offht, z=pos.z-sz},
- maxpos = {x=pos.x+sz, y=pos.y+offht+ht, z=pos.z+sz},
- minvel = {x=vel.x, y=-20, z=vel.z},
- maxvel = {x=vel.x, y=-20, z=vel.z},
- minacc = {x=-0.1, y=0.1, z=-0.1},
- maxacc = {x=0.1, y=0.3, z=0.1},
- collisiondetection = true,
- collision_removal = true,
- minexptime = 2,
- maxexptime = 7,
- minsize = 10,
- maxsize = 15,
- texture = "storms_snowflake.png",
- })
- end
- local function spawn_lightning(pos, amount, sz)
- local offht = 60
- for i = 1,math.random(amount) do
- minetest.after(math.random(5), function()
- do_lightning(pos.y+60, randompos(pos, sz))
- end)
- end
- end
- local biome_skies = {
- ["tundra"] = {color = {r=255, g=255, b=255}, clouds = false},
- ["taiga"] = {color = {r=255, g=255, b=255}, clouds = false},
- ["snowy_grassland"] = {color = {r=255, g=255, b=255}, clouds = false},
- ["cold_desert"] = {color = {r=255, g=255, b=255}, clouds = false},
-
- ["desert"] = {color = {r=130, g=105, b=25}, clouds = false},
- ["sandstone_desert"] = {color = {r=130, g=105, b=25}, clouds = false},
-
- ["grassland"] = {color = {r=20, g=20, b=30}, clouds = false},
- ["deciduous_forest"] = {color = {r=20, g=20, b=30}, clouds = false},
- ["coniferous_forest"] = {color = {r=20, g=20, b=30}, clouds = false},
- ["savanna"] = {color = {r=20, g=20, b=30}, clouds = false},
- ["rainforest"] = {color = {r=20, g=20, b=30}, clouds = false},
- }
- local biome_spawners = {}
- biome_spawners.tundra = function(pos, dir, lvl)
- spawn_blizzard(pos, dir, 15, lvl)
- end
- biome_spawners.taiga = function(pos, dir, lvl)
- spawn_snow(pos, {x=0, y=0, z=0}, 20, lvl)
- end
- biome_spawners.grassland = function(pos, dir, lvl)
- spawn_rainclouds(pos, dir, 200, lvl)
- spawn_rain(pos, {x=0, y=0, z=0}, 20, lvl)
- spawn_lightning(pos, 15 * lvl, 60)
- end
- biome_spawners.snowy_grassland = function(pos, dir, lvl)
- spawn_blizzard(pos, dir, 15, lvl)
- end
- biome_spawners.savanna = function(pos, dir, lvl)
- spawn_rainclouds(pos, dir, 200, lvl)
- -- spawn_rain(pos, {x=0, y=0, z=0}, 10)
- spawn_lightning(pos, 30 * lvl, 70)
- end
- biome_spawners.deciduous_forest = function(pos, dir, lvl)
- spawn_rainclouds(pos, dir, 200, lvl)
- spawn_rain(pos, {x=0, y=0, z=0}, 20, lvl)
- end
- biome_spawners.rainforest = function(pos, dir, lvl)
- spawn_rainclouds(pos, dir, 200, lvl)
- spawn_rain(pos, {x=0, y=0, z=0}, 20, lvl)
- end
- biome_spawners.coniferous_forest = function(pos, dir, lvl)
- spawn_rainclouds(pos, dir, 200, lvl)
- spawn_rain(pos, {x=0, y=0, z=0}, 20, lvl)
- end
- biome_spawners.cold_desert = function(pos, dir, lvl)
- spawn_blizzard(pos, dir, 15, lvl)
- end
- biome_spawners.desert = function(pos, dir, lvl)
- spawn_sandstorm(pos, dir, 15, lvl)
- end
- biome_spawners.sandstone_desert = function(pos, dir, lvl)
- spawn_sandstorm(pos, dir, 15, lvl)
- end
- local function set_biome_storm_sky(pinfo, b1, b2, n_biome, n_normal)
- local sky1 = biome_skies[b1]
- local sky2 = biome_skies[b2]
- if not sky1 then
- print("missing biome: ".. b1)
- return
- end
- if not sky2 then
- print("missing biome: ".. b2)
- return
- end
-
- local color = color_lerp(sky1.color, sky2.color, n_biome)
- color = color_lerp(color, pinfo.default_sky.color, n_normal)
-
- local sky
- if n_normal > .75 then
- sky = pinfo.default_sky
- elseif n_biome > .5 then
- sky = sky2
- else
- sky = sky1
- end
-
- pinfo.player:set_sky(color, sky.type or "plain", sky.tex, sky.clouds or false)
- end
- minetest.register_craftitem("storms:rainstick", {
- description = "Magic Rainstick",
- inventory_image = "default_stick.png^[colorize:gold:80",
- stack_max = 1,
- on_use = function(itemstack, player, pointed_thing)
-
-
- if sky_defaults == nil then
- sky_defaults = {}
- sky_defaults.col, sky_defaults.tp, sky_defaults.tex, sky_defaults.cl = player:get_sky()
- end
-
-
- if on then
- on = false
- player:set_sky(sky_defaults.col, sky_defaults.tp, sky_defaults.tex, sky_defaults.cl)
- else
- on = true
-
-
-
- local function spawn_storm()
- local pos = player:get_pos()
- local biome = get_biome(pos)
-
-
- local fn = biome_spawners[biome]
-
- if not fn then
- print("missing spawner biome: "..biome)
- end
- fn(pos, {x=20, y=0, x=10}, 1)
-
- -- set_biome_storm_sky(player, biome)
-
- if on then
- minetest.after(5, function()
- spawn_storm()
- end)
- end
-
- end
-
- spawn_storm()
-
- player:set_sky({r=20, g=20, b=30}, "plain", nil, false)
- end
-
-
- end,
- })
- storms.register_on_lightning_strike(function(pos)
- -- pos.y = pos.y + 1
- -- minetest.set_node(pos, {name="fire:basic_flame"})
-
- end)
- local function get_player_sky(player)
- local sky = {}
- sky.color, sky.type, sky.tex, sky.clouds = player:get_sky()
- return sky
- end
- minetest.register_on_joinplayer(function(player)
- local name = player:get_player_name()
- storm_players[name] = {
- a = nil,
- b = nil,
- fill = 1,
- player = player,
- default_sky = get_player_sky(player),
- }
-
- print(dump(storm_players[name].default_sky))
- end)
- minetest.register_on_leaveplayer(function(player)
- local name = player:get_player_name()
- storm_players[name] = nil
- end)
- local function activate_storm(player )
- local pos = player:get_pos()
- local biome = get_biome(pos)
-
-
- local fn = biome_spawners[biome]
-
- if not fn then
- print("missing spawner biome: "..biome)
- end
- fn(pos)
-
- end
- local function clamp(min, max, n)
- if n < min then return min end
- if n > max then return max end
- return n
- end
- local function storm_loop()
- local time = minetest.get_gametime()
-
- for name,pinfo in pairs(storm_players) do
- local pos = pinfo.player:get_pos()
-
- local t = math.sin(time / (5 * 2 * math.pi))
- local t2 = math.cos(time / (7 * 2 * math.pi))
-
- local p1 = {
- x = ((t * 20 + t2 * 30 + pos.x + time) % 65536) - 32768,
- y = 0,
- z = ((t * 20 + t2 * 30 + pos.z + time) % 65536) - 32768,
- }
-
- local dx = perlins.dx:get2dMap_flat(p1)[1]
- local dz = perlins.dz:get2dMap_flat(p1)[1]
-
-
- -- for i = 1,2000,3 do
- -- local f3 = perlins.freq3:get3dMap_flat({x=pos.x, y=pos.z, z=i --[[(time *20) % 2000]]})[1]
- -- f3 = (f3 * 4) - 1.6
- -- print("perlin: ".. dump(f3))
- -- end
- local f3 = perlins.freq3:get3dMap_flat({x=pos.x, y=pos.z, z=(time * SPEED) % 65536})[1]
- f3 = (f3 * FREQ_SCALE) + FREQ_BIAS -- - 1.6
- -- print("perlin: ".. dump(f3))
-
- f3 = f3 + get_freq_bias(pos, f3, pinfo.player)
-
- local biome = get_biome(pos)
- -- f3 = nil
- -- print("storm intensity: ".. f .. " ("..f1..", "..f2..")")
- local intens = f3 + get_intens_bias(pos, f3, pinfo.player)
- if f3 > 0 then
-
- local dir = {x = dx, y = 0, z = dz}
-
- local fn = biome_spawners[biome]
-
- if not fn then
- print("missing spawner biome: "..biome)
- end
- fn(pos, dir, 1, intens)
-
- end
-
-
-
-
- set_biome_storm_sky(pinfo, biome, biome, 1, clamp(0, 1, 1-intens))
- end
-
-
- minetest.after(5, storm_loop)
- end
- minetest.after(2, function()
-
- perlins.dx = minetest.get_perlin_map({
- flags = {eased = false},
- lacunarity = 4,
- octaves = 4,
- offset = 0,
- persistence = 0.65,
- seed = 35363,
- scale = 10,
- spread = {x=1000, y=1000, z=1000}
- }, {x=1,y=1,z=1})
-
- perlins.dz = minetest.get_perlin_map({
- flags = {eased = false},
- lacunarity = 4,
- octaves = 4,
- offset = 0,
- persistence = 0.65,
- seed = 678786,
- scale = 10,
- spread = {x=1000, y=1000, z=1000}
- }, {x=1,y=1,z=1})
-
- --[[
- perlins.freq1 = minetest.get_perlin_map({
- flags = {eased = false},
- lacunarity = 2,
- octaves = 3,
- offset = 0,
- persistence = 0.25,
- seed = 79932,
- scale = 1,
- spread = {x=2000, y=2000, z=2000}
- }, {x=1,y=1,z=1})
-
- perlins.freq2 = minetest.get_perlin_map({
- flags = {eased = false},
- lacunarity = 2,
- octaves = 1,
- offset = 0,
- persistence = 0.25,
- seed = 6445,
- scale = 1,
- spread = {x=2000, y=2000, z=2000}
- }, {x=1,y=1,z=1})
- ]]
-
- perlins.freq3 = minetest.get_perlin_map({
- flags = {eased = false},
- lacunarity = 4,
- octaves = 5,
- offset = 0,
- persistence = 0.45,
- seed = 179334,
- scale = 1,
- spread = {x=500, y=500, z=500}
- }, {x=2,y=2,z=2})
-
-
- storm_loop()
- end)
|