starlit  Diff

Differences From Artifact [d1f4916ac1]:

To Artifact [de51a702a5]:


    42     42   		surfaceTemp = heat;
    43     43   		waterTemp = heat + biome.waterTempDelta;
    44     44   		surfaceHumid = humid;
    45     45   	}
    46     46   end
    47     47   
    48     48   local vdsq = lib.math.vdsq
    49         -function world.climate.temp(pos) --> irradiance at pos in W
           49  +function world.climate.temp(pos, timeshift) --> irradiance at pos in W
    50     50   	local cl = world.climate.eval(pos)
    51     51   	local radCenters = starlit.region.radiator.store:get_areas_for_pos(pos, false, true)
    52     52   	local irradiance = 0
    53     53   	for _,e in pairs(radCenters) do
    54     54   		local rpos = minetest.string_to_pos(e.data)
    55     55   		local rdef = assert(minetest.registered_nodes[assert(minetest.get_node(rpos)).name])
    56     56   		local rc = rdef._starlit.radiator
................................................................................
    79     79   					power = power * (1 - (dist_sq / ((r_max+1)^2)))
    80     80   				end
    81     81   				power = power * (1 - (obstruct/5))
    82     82   				irradiance = irradiance + power
    83     83   			end
    84     84   		end
    85     85   	end
           86  +	local w = world.climate.weatherAt(pos, timeshift)
           87  +
    86     88   	return irradiance + cl.surfaceTemp
    87     89   end
           90  +
           91  +function world.ecology.biomeAt(pos)
           92  +	return world.ecology.biomes.db[minetest.get_biome_name(minetest.get_biome_data(pos).biome)]
           93  +end
           94  +
           95  +
           96  +minetest.after(0, function()
           97  +	world.climate.weatherMap.kind = minetest.get_perlin {
           98  +		seed = 0x925afe;
           99  +		octaves = 2;
          100  +		spread = vector.new(256,256,120);
          101  +	};
          102  +	world.climate.weatherMap.severity = minetest.get_perlin {
          103  +		seed = 0x39de1d;
          104  +		octaves = 1;
          105  +		spread = vector.new(256,256,60);
          106  +	};
          107  +end)
          108  +
          109  +function world.climate.weatherAt(pos, timeshift)
          110  +	timeshift = timeshift or 0
          111  +	local wv  = world.climate.weatherMap.kind:get_3d(vector.new(pos.x, pos.z, minetest.get_gametime() + timeshift))
          112  +	local sev = world.climate.weatherMap.severity:get_3d(vector.new(pos.x, pos.z, minetest.get_gametime() + timeshift))
          113  +	local b = world.ecology.biomeAt(pos)
          114  +	local w = 'starlit:clear'
          115  +	for i,v in ipairs(b.weather) do
          116  +		if wv < v[1] then
          117  +			w = v[2]
          118  +			break
          119  +		end
          120  +	end
          121  +	local mods = {
          122  +		cloudCover = 0;
          123  +		rain = 0; -- affects plant growth
          124  +		snow = 0; -- spawns snow layer
          125  +		fog = 0;
          126  +		temp = 0;
          127  +		hum = 0;
          128  +		rad = 0;
          129  +	}
          130  +	return world.climate.weather.db[w], sev
          131  +end
          132  +
          133  +
          134  +-- weather manages particle systems, and provides modifiers for
          135  +-- temp, cloud cover, received precipitation, and fog
          136  +
          137  +world.climate.weather.link('starlit:clear', {
          138  +	name = 'Clear';
          139  +})
          140  +world.climate.weather.link('starlit:cloudy', {
          141  +	name = 'Cloudy';
          142  +	mod = function(m, temp, hum, sev)
          143  +		m.cloudCover = math.max(m.cloudCover, sev)
          144  +	end;
          145  +})
          146  +world.climate.weather.link('starlit:precip', {
          147  +	name = function(temp, hum, sev)
          148  +		if temp < 0 then return 'Snow' else return 'Rain' end
          149  +	end;
          150  +	mod = function(m, temp, hum, sev)
          151  +		m.cloudCover = math.max(m.cloudCover, sev)
          152  +		if temp < 0 then
          153  +			m.snow = math.max(m.snow, sev/2)
          154  +		else
          155  +			m.rain = math.max(m.rain, sev/2)
          156  +		end
          157  +	end;
          158  +})
          159  +world.climate.weather.link('starlit:storm', {
          160  +	name = function(temp, hum, sev)
          161  +		if temp < 0 then
          162  +			if sev > .5
          163  +				then return 'Blizzard'
          164  +				else return 'Snowstorm'
          165  +			end
          166  +		else
          167  +			if sev > .5
          168  +				then return 'Monsoon'
          169  +				else return 'Rainstorm'
          170  +			end
          171  +		end
          172  +	end;
          173  +	mod = function(m, temp, hum, sev)
          174  +		m.cloudCover = math.max(m.cloudCover, sev)
          175  +		if temp < 0 then
          176  +			m.snow = math.max(m.snow, sev/2 + .5)
          177  +		else
          178  +			m.rain = math.max(m.rain, sev/2 + .5)
          179  +		end
          180  +	end;
          181  +})
          182  +world.climate.weather.link('starlit:tstorm', {
          183  +	name = 'Thunderstorm';
          184  +	danger = 1;
          185  +	mod = function(m, temp, hum, sev)
          186  +		m.cloudCover = math.max(m.cloudCover, sev)
          187  +		m.danger = (sev>.5) and 2 or 1
          188  +	end;
          189  +})
          190  +world.climate.weather.link('starlit:sstorm', {
          191  +	name = 'Solar Storm';
          192  +	danger = 2;
          193  +})
          194  +world.climate.weather.link('starlit:meteorShower', {
          195  +	name = 'Meteor Shower';
          196  +	danger = 2;
          197  +})
    88    198   
    89    199   world.ecology.biomes.foreach('starlit:biome-gen', {}, function(id, b)
    90    200   	b.def.name = id
    91    201   	minetest.register_biome(b.def)
    92    202   end)
    93    203   
    94    204   world.ecology.plants.foreach('starlit:plant-gen', {}, function(id, b)
................................................................................
   160    270   	}
   161    271   	for k,v in pairs(b.decoration) do dec[k] = v end
   162    272   	b.decoration = minetest.register_decoration(dec)
   163    273   end)
   164    274   
   165    275   local toward = lib.math.toward
   166    276   local hfinterval = 1.5
   167         -starlit.startJob('starlit:heatflow', hfinterval, function(delta)
          277  +starlit.startJob('starlit:temps', hfinterval, function(delta)
   168    278   
   169    279   	-- our base thermal conductivity (κ) is measured in °C/°C/s. say the
   170    280   	-- player is in -30°C weather, and has an internal temperature of
   171    281   	-- 10°C. then:
   172    282   	--   κ  = .1°C/C/s (which is apparently 100mHz)
   173    283   	--   Tₚ =  10°C
   174    284   	--   Tₑ = -30°C
................................................................................
   175    285   	--   d  = Tₑ − Tₚ = -40°C
   176    286   	--   ΔT = κ×d = -.4°C/s
   177    287   	-- too cold:
   178    288   	--		x = beginning of danger zone
   179    289   	--    κ × (x - Tₚ) = y where y < Tₚ
   180    290   	-- our final change in temperature is computed as tΔC where t is time
   181    291   	local kappa = starlit.constant.heat.thermalConductivity
          292  +	local now = minetest.get_gametime()
   182    293   	for name,user in pairs(starlit.activeUsers) do
   183    294   		local tr = user:species().tempRange
   184    295   		local t = starlit.world.climate.temp(user.entity:get_pos())
          296  +
          297  +		local weather,wsev = starlit.world.climate.weatherAt(user.entity:get_pos())
          298  +		local wfac
          299  +		if user.env.weather == nil
          300  +			then wfac = 1
          301  +			else wfac = (now - user.env.weather.when) / 10
          302  +		end
          303  +		if user.env.weather == nil or now - user.env.weather.when >= 10 then
          304  +			user.env.weather = {when = now, what = weather}
          305  +		end
   185    306   
   186    307   		do -- this bit probably belongs in starlit:bio but we do it here in order
   187    308   		   -- to spare ourselves another call into the dark swamp of climate.temp
   188    309   		   local urg = 1
   189    310   		   local hz = user:tempHazard(t)
   190    311   			local tr = user:species().tempRange.survivable
   191    312   		   if hz == 'cold' then