P4 hazards: food spoilage with rot speed setting, smoking rack and salt, food poisoning, harsher blizzards, hard winters with lake ice, lightning on trees, snow on roofs (protocol 11)
This commit is contained in:
@@ -11,6 +11,11 @@ extends Node
|
||||
## (and a storm becomes a blizzard). Above the snowline it always snows.
|
||||
## Outputs ease toward the state's targets over about a minute, so fronts
|
||||
## roll in rather than switching.
|
||||
##
|
||||
## P4 (docs/PROGRESSION_DESIGN.md §5): every 12 days a hard winter, three
|
||||
## bitter cold days in a row (hard_winter()), colder still, with more snow and
|
||||
## blizzards. A blizzard cuts visibility right down and its wind strips the
|
||||
## warmth from anyone out in it (blizzard_chill(); a shelter keeps it out).
|
||||
|
||||
signal state_changed(state: String)
|
||||
|
||||
@@ -30,12 +35,18 @@ const TARGETS := {
|
||||
"rain": {"clouds": 0.92, "precip": 0.6, "wind": 0.60, "light": 0.50, "fog": 2.2, "warmth": -6.0},
|
||||
"storm": {"clouds": 1.00, "precip": 1.0, "wind": 1.00, "light": 0.30, "fog": 3.0, "warmth": -12.0},
|
||||
"snow": {"clouds": 0.90, "precip": 0.6, "wind": 0.35, "light": 0.68, "fog": 2.6, "warmth": -14.0},
|
||||
"blizzard": {"clouds": 1.00, "precip": 1.0, "wind": 0.90, "light": 0.45, "fog": 4.5, "warmth": -24.0},
|
||||
"blizzard": {"clouds": 1.00, "precip": 1.0, "wind": 1.00, "light": 0.40, "fog": 7.0, "warmth": -24.0},
|
||||
}
|
||||
const COLD_DAY_WARMTH := -8.0
|
||||
const BLEND_SECONDS := 50.0 ## time for outputs to cross from one state to another
|
||||
const CALM_START := 600.0 ## a new world's first 10 minutes are always clear
|
||||
const COLD_DAY_CHANCE := 0.25
|
||||
const HARD_WINTER_EVERY := 12 ## days 12-14, 24-26, ...
|
||||
const HARD_WINTER_DAYS := 3
|
||||
const HARD_WINTER_WARMTH := -8.0 ## on top of a cold day's
|
||||
const BLIZZARD_CHILL := 18.0 ## more warmth lost out in a blizzard's wind (a hard winter's freezes you by day)
|
||||
## In a hard winter the weather leans wet (more snow and blizzards).
|
||||
const HARD_WINTER_FRONT := -0.18
|
||||
|
||||
var world_seed := 1337
|
||||
var day_night: Node
|
||||
@@ -76,9 +87,22 @@ func setup(seed: int, dn: Node) -> void:
|
||||
func world_seconds() -> float:
|
||||
return (float(day_night.day - 1) + float(day_night.time)) * float(day_night.day_length)
|
||||
|
||||
## Day `day` is one of a hard winter's three bitter days.
|
||||
static func hard_winter(day: int) -> bool:
|
||||
return day >= HARD_WINTER_EVERY and (day - HARD_WINTER_EVERY) % HARD_WINTER_EVERY < HARD_WINTER_DAYS
|
||||
|
||||
## The first day of the next hard winter on or after `day`.
|
||||
static func next_hard_winter(day: int) -> int:
|
||||
var d := maxi(day, HARD_WINTER_EVERY)
|
||||
while not hard_winter(d):
|
||||
d += 1
|
||||
return d
|
||||
|
||||
func is_cold_day(day: int) -> bool:
|
||||
if day <= 1:
|
||||
return false
|
||||
if hard_winter(day):
|
||||
return true
|
||||
return float(absi(hash(Vector2i(world_seed, day))) % 10000) / 10000.0 < COLD_DAY_CHANCE
|
||||
|
||||
## The raw front value at an absolute time (higher = fairer).
|
||||
@@ -100,7 +124,7 @@ func _state_for(v: float, cold: bool) -> String:
|
||||
## The state at an absolute time, ignoring smoothing and overrides.
|
||||
func state_at(t: float) -> String:
|
||||
var day := int(floor(t / float(day_night.day_length))) + 1
|
||||
return _state_for(front_at(t), is_cold_day(day))
|
||||
return _state_for(front_at(t) + (HARD_WINTER_FRONT if hard_winter(day) else 0.0), is_cold_day(day))
|
||||
|
||||
func force(s: String) -> void:
|
||||
override = s
|
||||
@@ -116,7 +140,7 @@ func snap() -> void:
|
||||
wind = tg.wind
|
||||
light = tg.light
|
||||
fog = tg.fog
|
||||
warmth = tg.warmth + (COLD_DAY_WARMTH if cold_day else 0.0)
|
||||
warmth = tg.warmth + _cold_extra()
|
||||
ground_wet = 1.0 if state in ["rain", "storm"] else 0.0
|
||||
snow_cover = 0.7 if state in ["snow", "blizzard"] else (0.25 if cold_day else 0.0)
|
||||
|
||||
@@ -128,7 +152,7 @@ func _pick_state() -> void:
|
||||
if frozen and s.is_empty():
|
||||
s = "clear"
|
||||
if s.is_empty():
|
||||
s = _state_for(front_at(world_seconds()), cold_day)
|
||||
s = _state_for(front_at(world_seconds()) + (HARD_WINTER_FRONT if hard_winter(day_night.day) else 0.0), cold_day)
|
||||
if s != state:
|
||||
state = s
|
||||
state_changed.emit(state)
|
||||
@@ -145,7 +169,7 @@ func step(dt: float) -> void:
|
||||
wind = move_toward(wind, tg.wind, k)
|
||||
light = move_toward(light, tg.light, k * 0.8)
|
||||
fog = move_toward(fog, tg.fog, k * 3.0)
|
||||
warmth = move_toward(warmth, tg.warmth + (COLD_DAY_WARMTH if cold_day else 0.0), k * 20.0)
|
||||
warmth = move_toward(warmth, tg.warmth + _cold_extra(), k * 20.0)
|
||||
# The ground soaks in a couple of minutes of rain and dries over ten.
|
||||
var raining := precip > 0.2 and not snowing_globally()
|
||||
ground_wet = move_toward(ground_wet, 1.0 if raining else 0.0, dt / (120.0 if raining else 600.0))
|
||||
@@ -163,6 +187,22 @@ func step(dt: float) -> void:
|
||||
flash = 1.0
|
||||
lightning_count += 1
|
||||
|
||||
## Extra cold from the day: a cold day, and a hard winter on top.
|
||||
func _cold_extra() -> float:
|
||||
if not cold_day:
|
||||
return 0.0
|
||||
return COLD_DAY_WARMTH + (HARD_WINTER_WARMTH if day_night != null and hard_winter(day_night.day) else 0.0)
|
||||
|
||||
func in_hard_winter() -> bool:
|
||||
return day_night != null and hard_winter(day_night.day)
|
||||
|
||||
## Extra warmth lost by someone out in a blizzard's wind (0 when sheltered or
|
||||
## when it isn't blowing).
|
||||
func blizzard_chill(sheltered: bool) -> float:
|
||||
if sheltered or state != "blizzard":
|
||||
return 0.0
|
||||
return BLIZZARD_CHILL * clampf(precip, 0.0, 1.0)
|
||||
|
||||
func snowing_globally() -> bool:
|
||||
return state in ["snow", "blizzard"]
|
||||
|
||||
@@ -188,4 +228,6 @@ func label() -> String:
|
||||
var s: String = names[state]
|
||||
if cold_day and state in ["clear", "cloudy"]:
|
||||
s += ", cold"
|
||||
if in_hard_winter():
|
||||
s += " (hard winter)"
|
||||
return s
|
||||
|
||||
Reference in New Issue
Block a user