Merge branch 'easter_and_april_fools_stuff' into 'master'

easter_and_april_fools_stuff

See merge request veloren/veloren!4404
This commit is contained in:
crabman 2024-04-01 06:46:43 +00:00
commit d8bd81357b
54 changed files with 515 additions and 8 deletions

View File

@ -0,0 +1,12 @@
#![enable(implicit_some)]
(
name: Name("Treasure Egg"),
body: RandomWith("treasure_egg"),
alignment: Alignment(Wild),
loot: LootTable("common.loot_tables.calendar.easter.treasure_egg"),
inventory: (
loadout: Inline((
inherit: Asset("common.loadout.world.treasure_egg.treasure_egg"),
)), ),
meta: [],
)

View File

@ -339,6 +339,12 @@
Simple( Simple(
"common.items.npc_armor.biped_small.bushly.hand.bushly", "common.items.npc_armor.biped_small.bushly.hand.bushly",
): "common-items-npc_armor-biped_small-bushly-hand-bushly", ): "common-items-npc_armor-biped_small-bushly-hand-bushly",
Simple(
"common.items.npc_armor.biped_small.treasure_egg.chest.treasure_egg",
): "common-items-npc_armor-biped_small-treasure_egg-chest-treasure_egg",
Simple(
"common.items.npc_armor.biped_small.treasure_egg.foot.treasure_egg",
): "common-items-npc_armor-biped_small-treasure_egg-foot-treasure_egg",
Simple( Simple(
"common.items.npc_armor.biped_small.clockwork.foot.clockwork", "common.items.npc_armor.biped_small.clockwork.foot.clockwork",
): "common-items-npc_armor-biped_small-clockwork-foot-clockwork", ): "common-items-npc_armor-biped_small-clockwork-foot-clockwork",
@ -1206,6 +1212,12 @@
Simple( Simple(
"common.items.armor.misc.head.bandana.thief", "common.items.armor.misc.head.bandana.thief",
): "armor-misc-head-bandana-thief", ): "armor-misc-head-bandana-thief",
Simple(
"common.items.armor.misc.head.hare_hat",
): "armor-misc-head-hare_hat",
Simple(
"common.items.armor.misc.head.cat_capuche",
): "armor-misc-head-cat_capuche",
Simple( Simple(
"common.items.armor.misc.pants.hunting", "common.items.armor.misc.pants.hunting",
): "armor-misc-pants-grayscale", ): "armor-misc-pants-grayscale",
@ -2019,6 +2031,9 @@
Simple( Simple(
"common.items.utility.bomb", "common.items.utility.bomb",
): "object-bomb", ): "object-bomb",
Simple(
"common.items.utility.surprise_egg",
): "object-surprise_egg",
Simple( Simple(
"common.items.utility.coins", "common.items.utility.coins",
): "object-v-coin", ): "object-v-coin",

View File

@ -0,0 +1,15 @@
ItemDef(
legacy_name: "Cat Capuche",
legacy_description: "April Fools Special",
kind: Armor((
kind: Head,
stats: Direct((
energy_max: Some(4.0),
energy_reward: Some(0.04),
)),
)),
quality: Moderate,
tags: [
SalvageInto(Leather, 1),
],
)

View File

@ -0,0 +1,15 @@
ItemDef(
legacy_name: "Hare Hat",
legacy_description: "Easter Special",
kind: Armor((
kind: Head,
stats: Direct((
energy_max: Some(4.0),
energy_reward: Some(0.04),
)),
)),
quality: Moderate,
tags: [
SalvageInto(Leather, 1),
],
)

View File

@ -0,0 +1,16 @@
ItemDef(
legacy_name: "Treasure Egg",
legacy_description: "Easter Special",
kind: Armor((
kind: Chest,
stats: Direct((
protection: Some(Normal(4.0)),
poise_resilience: Some(Normal(4.0)),
energy_max: Some(3.4),
energy_reward: Some(0.81),
precision_power: Some(0.075),
)),
)),
quality: Low,
tags: [],
)

View File

@ -0,0 +1,16 @@
ItemDef(
legacy_name: "Treasure Egg",
legacy_description: "Easter Special",
kind: Armor((
kind: Foot,
stats: Direct((
protection: Some(Normal(1.0)),
poise_resilience: Some(Normal(4.0)),
energy_max: Some(3.4),
energy_reward: Some(0.81),
precision_power: Some(0.075),
)),
)),
quality: Low,
tags: [],
)

View File

@ -0,0 +1,9 @@
ItemDef(
legacy_name: "Surprise Egg",
legacy_description: "Easter Special",
kind: Throwable(
kind: SurpriseEgg,
),
quality: Common,
tags: [Utility],
)

View File

@ -0,0 +1,5 @@
#![enable(implicit_some)]
(
chest: Item("common.items.npc_armor.biped_small.treasure_egg.chest.treasure_egg"),
feet: Item("common.items.npc_armor.biped_small.treasure_egg.foot.treasure_egg"),
)

View File

@ -1,4 +1,5 @@
[ [
(1.0, Item("common.items.consumable.curious_potion")), (1.0, Item("common.items.consumable.curious_potion")),
(0.5, Item("common.items.armor.misc.head.cat_capuche")),
(19.0, Nothing), (19.0, Nothing),
] ]

View File

@ -0,0 +1,5 @@
[
(2.0, Item("common.items.utility.surprise_egg")),
(0.5, MultiDrop(Item("common.items.utility.coins"), 50, 250)),
(0.5, Item("common.items.armor.misc.head.hare_hat")),
]

View File

@ -1221,6 +1221,10 @@
keyword: "jiangshi", keyword: "jiangshi",
generic: "Jiangshi", generic: "Jiangshi",
), ),
treasure_egg: (
keyword: "treasure_egg",
generic: "Treasure Egg",
),
) )
), ),
fish_small: ( fish_small: (

View File

@ -1429,6 +1429,16 @@
threshold: 0.2, threshold: 0.2,
subtitle: "subtitle-attack-ground_slam", subtitle: "subtitle-attack-ground_slam",
), ),
SurpriseEgg: (
files: [
"voxygen.audio.sfx.abilities.surprise_egg_0",
"voxygen.audio.sfx.abilities.surprise_egg_1",
"voxygen.audio.sfx.abilities.surprise_egg_2",
"voxygen.audio.sfx.abilities.surprise_egg_3",
],
threshold: 2.2,
subtitle: "subtitle-surprise_egg",
),
LaserBeam: ( LaserBeam: (
files: [ files: [
"voxygen.audio.sfx.abilities.laser_beam", "voxygen.audio.sfx.abilities.laser_beam",

BIN
assets/voxygen/audio/sfx/abilities/surprise_egg_0.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/audio/sfx/abilities/surprise_egg_1.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/audio/sfx/abilities/surprise_egg_2.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/audio/sfx/abilities/surprise_egg_3.ogg (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -89,6 +89,7 @@ subtitle-instrument_wildskin_drum = Wildskin Drum playing
subtitle-pickup_instrument = Pickup instrument subtitle-pickup_instrument = Pickup instrument
subtitle-explosion = Explosion subtitle-explosion = Explosion
subtitle-surprise_egg = Divine Sound
subtitle-arrow_shot = Arrow released subtitle-arrow_shot = Arrow released
subtitle-arrow_miss = Arrow miss subtitle-arrow_miss = Arrow miss

View File

@ -301,6 +301,12 @@ armor-misc-head-bandana-red = Red Bandana
armor-misc-head-bandana-thief = Thief Bandana armor-misc-head-bandana-thief = Thief Bandana
.desc = Common bandit's mask. .desc = Common bandit's mask.
armor-misc-head-hare_hat = Hare Hat
.desc = Easter Special
armor-misc-head-cat_capuche = Cat Capuche
.desc = April Fools Special
armor-misc-pants-grayscale = Hunting Pants armor-misc-pants-grayscale = Hunting Pants
.desc = Crafted from soft, supple leather. .desc = Crafted from soft, supple leather.

View File

@ -307,6 +307,12 @@ common-items-npc_armor-biped_small-bushly-chest-bushly = Bushly
common-items-npc_armor-biped_small-bushly-hand-bushly = Mandragora common-items-npc_armor-biped_small-bushly-hand-bushly = Mandragora
.desc = Ceremonial attire used by members. .desc = Ceremonial attire used by members.
common-items-npc_armor-biped_small-treasure_egg-chest-treasure_egg = Treasure Egg Chest
.desc = Treasure Egg Chest
common-items-npc_armor-biped_small-treasure_egg-foot-treasure_egg = Treasure Egg Foot
.desc = Treasure Egg Foot
common-items-npc_armor-biped_small-clockwork-foot-clockwork = Clockwork Foot common-items-npc_armor-biped_small-clockwork-foot-clockwork = Clockwork Foot
.desc = Clockwork Foot. .desc = Clockwork Foot.

View File

@ -18,3 +18,6 @@ weapon-projectile-fireworks_white = Firework White
weapon-projectile-fireworks_yellow = Firework Yellow weapon-projectile-fireworks_yellow = Firework Yellow
.desc = The Great Doctor passed away after testing this contraption indoors. .desc = The Great Doctor passed away after testing this contraption indoors.
object-surprise_egg = Surprise Egg
.desc = Explosive Easter Special.

View File

@ -2988,6 +2988,14 @@
"voxel.armor.miner.helmet", "voxel.armor.miner.helmet",
(0.0, 1.0, 0.0), (-120.0, 210.0,15.0), 1.3, (0.0, 1.0, 0.0), (-120.0, 210.0,15.0), 1.3,
), ),
Simple("common.items.armor.misc.head.hare_hat"): VoxTrans(
"voxel.armor.misc.head.hare_hat",
(0.0, 2.0, -0.0), (-110.0, 210.0,15.0), 1.4,
),
Simple("common.items.armor.misc.head.cat_capuche"): VoxTrans(
"voxel.armor.misc.head.cat_capuche",
(0.0, 2.0, -0.0), (-110.0, 210.0,15.0), 1.4,
),
// Rings // Rings
Simple("common.items.armor.misc.ring.scratched"): VoxTrans( Simple("common.items.armor.misc.ring.scratched"): VoxTrans(
"voxel.armor.misc.ring.scratched", "voxel.armor.misc.ring.scratched",
@ -3357,6 +3365,10 @@
"voxel.object.bomb", "voxel.object.bomb",
(0.0, 0.5, 0.0), (-50.0, 40.0, 20.0), 0.8, (0.0, 0.5, 0.0), (-50.0, 40.0, 20.0), 0.8,
), ),
Simple("common.items.utility.surprise_egg"): VoxTrans(
"voxel.object.surprise_egg",
(0.0, 0.5, 0.0), (-50.0, 40.0, 20.0), 0.8,
),
Simple("common.items.utility.firework_blue"): VoxTrans( Simple("common.items.utility.firework_blue"): VoxTrans(
"voxel.weapon.projectile.fireworks_blue-0", "voxel.weapon.projectile.fireworks_blue-0",
(0.0, 0.5, 0.0), (-50.0, 40.0, 20.0), 0.8, (0.0, 0.5, 0.0), (-50.0, 40.0, 20.0), 0.8,

View File

@ -97,6 +97,7 @@ const int PHOENIX_BUILD_UP_AIM = 57;
const int CLAY_SHRAPNEL = 58; const int CLAY_SHRAPNEL = 58;
const int AIRFLOW = 59; const int AIRFLOW = 59;
const int SPORE = 60; const int SPORE = 60;
const int SURPRISE_EGG = 61;
// meters per second squared (acceleration) // meters per second squared (acceleration)
const float earth_gravity = 9.807; const float earth_gravity = 9.807;
@ -1029,6 +1030,19 @@ void main() {
spin_in_axis(vec3(rand1, rand2, rand3), rand4 * 1.5 + lifetime) spin_in_axis(vec3(rand1, rand2, rand3), rand4 * 1.5 + lifetime)
); );
break; break;
case SURPRISE_EGG:
f_reflect = 0.0;
// sparks should flicker, so it stops glowing for 18% of time 4 times per second, same thing used in 4th float of RGBA vector
float egg_color1 = 2 + 1 * rand2 + 2 * step(0.18, fract(tick.x*4));
float egg_color2 = 0 + 1 * rand2 + 4 * step(0.18, fract(tick.x*4));
float egg_color3 = 2 + 6 * step(0.18, fract(tick.x*4));
attr = Attr(
spiral_motion(vec3(0, 0, 5), abs(rand0) + abs(rand1) * percent() * 4.0, percent(), 8.0 * abs(rand2), rand3),
vec3((2.5 * (1 - slow_start(0.05)))),
vec4(egg_color1, egg_color2, egg_color3, 0.5 + 0.5 * step(0.18, fract(tick.x*4))),
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
);
break;
default: default:
attr = Attr( attr = Attr(
linear_motion( linear_motion(

BIN
assets/voxygen/voxel/armor/misc/head/cat_capuche.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/misc/head/hare_hat.vox (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -96,5 +96,8 @@
"common.items.npc_armor.biped_small.jiangshi.chest.jiangshi": ( "common.items.npc_armor.biped_small.jiangshi.chest.jiangshi": (
vox_spec: ("npc.jiangshi.chest", (-7.0, -4.0, -4.0)), vox_spec: ("npc.jiangshi.chest", (-7.0, -4.0, -4.0)),
), ),
"common.items.npc_armor.biped_small.treasure_egg.chest.treasure_egg": (
vox_spec: ("npc.treasure_egg.male.chest", (-4.0, -4.0, 0.0)),
),
}, },
)) ))

View File

@ -248,5 +248,13 @@
vox_spec: ("npc.jiangshi.foot_r", (-2.0, -3.0, -8.0)), vox_spec: ("npc.jiangshi.foot_r", (-2.0, -3.0, -8.0)),
) )
), ),
"common.items.npc_armor.biped_small.treasure_egg.foot.treasure_egg": (
left: (
vox_spec: ("npc.treasure_egg.male.foot_r", (-1.0, -1.5, -4.0)),
),
right: (
vox_spec: ("npc.treasure_egg.male.foot_r", (-1.0, -1.5, -4.0)),
)
),
}, },
)) ))

View File

@ -1401,6 +1401,104 @@
vox_spec: ("armor.misc.head.woolly_wintercap", (-3.0, -8.0, -4.0)), vox_spec: ("armor.misc.head.woolly_wintercap", (-3.0, -8.0, -4.0)),
color: None color: None
), ),
// Hare Hat (Easter hat+event)
(Human, Male, "common.items.armor.misc.head.hare_hat"): (
vox_spec: ("armor.misc.head.hare_hat", (-4.0, -6.0, -4.0)),
color: None
),
(Human, Female, "common.items.armor.misc.head.hare_hat"): (
vox_spec: ("armor.misc.head.hare_hat", (-4.0, -5.0, -4.0)),
color: None
),
(Elf, Male, "common.items.armor.misc.head.hare_hat"): (
vox_spec: ("armor.misc.head.hare_hat", (-3.0, -6.0, -5.0)),
color: None
),
(Elf, Female, "common.items.armor.misc.head.hare_hat"): (
vox_spec: ("armor.misc.head.hare_hat", (-3.0, -6.0, -5.0)),
color: None
),
(Dwarf, Male, "common.items.armor.misc.head.hare_hat"): (
vox_spec: ("armor.misc.head.hare_hat", (-5.0, -5.0, -5.0)),
color: None
),
(Dwarf, Female, "common.items.armor.misc.head.hare_hat"): (
vox_spec: ("armor.misc.head.hare_hat", (-5.0, -5.0, -5.0)),
color: None
),
(Danari, Male, "common.items.armor.misc.head.hare_hat"): (
vox_spec: ("armor.misc.head.hare_hat", (-2.0, -6.0, -2.0)),
color: None
),
(Danari, Female, "common.items.armor.misc.head.hare_hat"): (
vox_spec: ("armor.misc.head.hare_hat", (-2.0, -6.0, -2.0)),
color: None
),
(Draugr, Male, "common.items.armor.misc.head.hare_hat"): (
vox_spec: ("armor.misc.head.hare_hat", (-6.0, -6.0, -3.0)),
color: None
),
(Draugr, Female, "common.items.armor.misc.head.hare_hat"): (
vox_spec: ("armor.misc.head.hare_hat", (-6.0, -6.0, -4.0)),
color: None
),
(Orc, Male, "common.items.armor.misc.head.hare_hat"): (
vox_spec: ("armor.misc.head.hare_hat", (-3.0, -5.0, -3.0)),
color: None
),
(Orc, Female, "common.items.armor.misc.head.hare_hat"): (
vox_spec: ("armor.misc.head.hare_hat", (-3.0, -7.0, -5.0)),
color: None
),
// Cat Capuche (April Fools hat+event)
(Human, Male, "common.items.armor.misc.head.cat_capuche"): (
vox_spec: ("armor.misc.head.cat_capuche", (-4.0, -6.0, -4.0)),
color: None
),
(Human, Female, "common.items.armor.misc.head.cat_capuche"): (
vox_spec: ("armor.misc.head.cat_capuche", (-4.0, -5.0, -4.0)),
color: None
),
(Elf, Male, "common.items.armor.misc.head.cat_capuche"): (
vox_spec: ("armor.misc.head.cat_capuche", (-3.0, -6.0, -5.0)),
color: None
),
(Elf, Female, "common.items.armor.misc.head.cat_capuche"): (
vox_spec: ("armor.misc.head.cat_capuche", (-3.0, -6.0, -5.0)),
color: None
),
(Dwarf, Male, "common.items.armor.misc.head.cat_capuche"): (
vox_spec: ("armor.misc.head.cat_capuche", (-5.0, -5.0, -5.0)),
color: None
),
(Dwarf, Female, "common.items.armor.misc.head.cat_capuche"): (
vox_spec: ("armor.misc.head.cat_capuche", (-5.0, -5.0, -5.0)),
color: None
),
(Danari, Male, "common.items.armor.misc.head.cat_capuche"): (
vox_spec: ("armor.misc.head.cat_capuche", (-2.0, -6.0, -2.0)),
color: None
),
(Danari, Female, "common.items.armor.misc.head.cat_capuche"): (
vox_spec: ("armor.misc.head.cat_capuche", (-2.0, -6.0, -2.0)),
color: None
),
(Draugr, Male, "common.items.armor.misc.head.cat_capuche"): (
vox_spec: ("armor.misc.head.cat_capuche", (-6.0, -6.0, -3.0)),
color: None
),
(Draugr, Female, "common.items.armor.misc.head.cat_capuche"): (
vox_spec: ("armor.misc.head.cat_capuche", (-6.0, -6.0, -4.0)),
color: None
),
(Orc, Male, "common.items.armor.misc.head.cat_capuche"): (
vox_spec: ("armor.misc.head.cat_capuche", (-3.0, -5.0, -3.0)),
color: None
),
(Orc, Female, "common.items.armor.misc.head.cat_capuche"): (
vox_spec: ("armor.misc.head.cat_capuche", (-3.0, -7.0, -5.0)),
color: None
),
// Gnarling Chieftain Mask // Gnarling Chieftain Mask
(Human, Male, "common.items.armor.misc.head.gnarling_mask"): ( (Human, Male, "common.items.armor.misc.head.gnarling_mask"): (
vox_spec: ("armor.misc.head.gnarling_mask", (-4.0, 1.0, -2.0)), vox_spec: ("armor.misc.head.gnarling_mask", (-4.0, 1.0, -2.0)),

View File

@ -753,6 +753,8 @@
Simple("common.items.armor.misc.head.helmet"): "voxel.armor.misc.head.helmet", Simple("common.items.armor.misc.head.helmet"): "voxel.armor.misc.head.helmet",
Simple("common.items.armor.misc.head.gnarling_mask"): "voxel.armor.misc.head.gnarling_mask_drop", Simple("common.items.armor.misc.head.gnarling_mask"): "voxel.armor.misc.head.gnarling_mask_drop",
Simple("common.items.armor.miner.helmet"): "voxel.armor.miner.helmet", Simple("common.items.armor.miner.helmet"): "voxel.armor.miner.helmet",
Simple("common.items.armor.misc.head.hare_hat"): "voxel.armor.misc.head.hare_hat",
Simple("common.items.armor.misc.head.cat_capuche"): "voxel.armor.misc.head.cat_capuche",
// Rings // Rings
Simple("common.items.armor.misc.ring.scratched"): "voxel.armor.misc.ring.scratched", Simple("common.items.armor.misc.ring.scratched"): "voxel.armor.misc.ring.scratched",
Simple("common.items.armor.misc.ring.gold"): "voxel.armor.misc.ring.gold", Simple("common.items.armor.misc.ring.gold"): "voxel.armor.misc.ring.gold",
@ -849,6 +851,7 @@
Simple("common.items.food.tomatosalad"): "voxel.sprite.food.salad_tomato", Simple("common.items.food.tomatosalad"): "voxel.sprite.food.salad_tomato",
// Throwables // Throwables
Simple("common.items.utility.bomb"): "voxel.object.bomb", Simple("common.items.utility.bomb"): "voxel.object.bomb",
Simple("common.items.utility.surprise_egg"): "voxel.object.surprise_egg",
Simple("common.items.utility.firework_blue"): "voxel.weapon.projectile.fireworks_blue-0", Simple("common.items.utility.firework_blue"): "voxel.weapon.projectile.fireworks_blue-0",
Simple("common.items.utility.firework_green"): "voxel.weapon.projectile.fireworks_green-0", Simple("common.items.utility.firework_green"): "voxel.weapon.projectile.fireworks_green-0",
Simple("common.items.utility.firework_purple"): "voxel.weapon.projectile.fireworks_purple-0", Simple("common.items.utility.firework_purple"): "voxel.weapon.projectile.fireworks_purple-0",

BIN
assets/voxygen/voxel/npc/treasure_egg/male/chest.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/treasure_egg/male/foot_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/object/surprise_egg.vox (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -1091,4 +1091,14 @@
central: ("armor.empty"), central: ("armor.empty"),
) )
), ),
SurpriseEgg: (
bone0: (
offset: (-5.5, -5.5, 0.0),
central: ("object.surprise_egg"),
),
bone1: (
offset: (0.0, 0.0, 0.0),
central: ("armor.empty"),
)
),
}) })

View File

@ -0,0 +1,14 @@
SpawnEntry (
name: "Easter Jungle Area",
note: "Easter NPCs",
rules: [
Pack(
groups: [
(1, (1, 1, "common.entity.calendar.easter.peaceful.treasure_egg")),
],
spawn_mode: Land,
calendar_events: Some([Easter]),
day_period: [Night, Morning, Noon, Evening],
),
],
)

View File

@ -0,0 +1,14 @@
SpawnEntry (
name: "Easter Jungle Core",
note: "Easter NPCs",
rules: [
Pack(
groups: [
(1, (1, 1, "common.entity.calendar.easter.peaceful.treasure_egg")),
],
spawn_mode: Land,
calendar_events: Some([Easter]),
day_period: [Night, Morning, Noon, Evening],
),
],
)

View File

@ -0,0 +1,14 @@
SpawnEntry (
name: "Easter Temperate Rainforest",
note: "Easter NPCs",
rules: [
Pack(
groups: [
(1, (1, 1, "common.entity.calendar.easter.peaceful.treasure_egg")),
],
spawn_mode: Land,
calendar_events: Some([Easter]),
day_period: [Night, Morning, Noon, Evening],
),
],
)

View File

@ -0,0 +1,14 @@
SpawnEntry (
name: "Easter Tropical Rainforest",
note: "Easter NPCs",
rules: [
Pack(
groups: [
(1, (1, 1, "common.entity.calendar.easter.peaceful.treasure_egg")),
],
spawn_mode: Land,
calendar_events: Some([Easter]),
day_period: [Night, Morning, Noon, Evening],
),
],
)

View File

@ -0,0 +1,14 @@
SpawnEntry (
name: "Easter Tundra Core",
note: "Easter NPCs",
rules: [
Pack(
groups: [
(1, (1, 1, "common.entity.calendar.easter.peaceful.treasure_egg")),
],
spawn_mode: Land,
calendar_events: Some([Easter]),
day_period: [Night, Morning, Noon, Evening],
),
],
)

View File

@ -0,0 +1,14 @@
SpawnEntry (
name: "Easter Tundra Forest",
note: "Easter NPCs",
rules: [
Pack(
groups: [
(1, (1, 1, "common.entity.calendar.easter.peaceful.treasure_egg")),
],
spawn_mode: Land,
calendar_events: Some([Easter]),
day_period: [Night, Morning, Noon, Evening],
),
],
)

View File

@ -0,0 +1,14 @@
SpawnEntry (
name: "Easter Tundra Snow",
note: "Easter NPCs",
rules: [
Pack(
groups: [
(1, (1, 1, "common.entity.calendar.easter.peaceful.treasure_egg")),
],
spawn_mode: Land,
calendar_events: Some([Easter]),
day_period: [Night, Morning, Noon, Evening],
),
],
)

View File

@ -9,6 +9,7 @@ pub enum CalendarEvent {
Christmas = 0, Christmas = 0,
Halloween = 1, Halloween = 1,
AprilFools = 2, AprilFools = 2,
Easter = 3,
} }
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
@ -49,6 +50,10 @@ impl Calendar {
this.events.push(CalendarEvent::AprilFools); this.events.push(CalendarEvent::AprilFools);
} }
if now.month() == 3 && now.day() == 31 || now.month() == 4 && (1..=7).contains(&now.day()) {
this.events.push(CalendarEvent::Easter);
}
this this
} }
} }

View File

@ -367,6 +367,7 @@ impl<'a> From<&'a Body> for Psyche {
biped_small::Species::Haniwa => 0.1, biped_small::Species::Haniwa => 0.1,
biped_small::Species::Sahagin => 0.1, biped_small::Species::Sahagin => 0.1,
biped_small::Species::Myrmidon => 0.0, biped_small::Species::Myrmidon => 0.0,
biped_small::Species::TreasureEgg => 9.9,
biped_small::Species::Husk biped_small::Species::Husk
| biped_small::Species::Boreal | biped_small::Species::Boreal
| biped_small::Species::Clockwork | biped_small::Species::Clockwork

View File

@ -549,6 +549,7 @@ impl Body {
biped_small::Species::Flamekeeper => Vec3::new(5.0, 5.0, 10.0), biped_small::Species::Flamekeeper => Vec3::new(5.0, 5.0, 10.0),
biped_small::Species::ShamanicSpirit => Vec3::new(1.3, 2.0, 2.3), biped_small::Species::ShamanicSpirit => Vec3::new(1.3, 2.0, 2.3),
biped_small::Species::Jiangshi => Vec3::new(1.3, 1.8, 2.5), biped_small::Species::Jiangshi => Vec3::new(1.3, 1.8, 2.5),
biped_small::Species::TreasureEgg => Vec3::new(1.1, 1.1, 1.4),
_ => Vec3::new(1.0, 0.75, 1.4), _ => Vec3::new(1.0, 0.75, 1.4),
}, },
Body::BirdLarge(body) => match body.species { Body::BirdLarge(body) => match body.species {

View File

@ -52,6 +52,7 @@ make_case_elim!(
Flamekeeper = 15, Flamekeeper = 15,
ShamanicSpirit = 16, ShamanicSpirit = 16,
Jiangshi = 17, Jiangshi = 17,
TreasureEgg = 18,
} }
); );
@ -78,6 +79,7 @@ pub struct AllSpecies<SpeciesMeta> {
pub flamekeeper: SpeciesMeta, pub flamekeeper: SpeciesMeta,
pub shamanic_spirit: SpeciesMeta, pub shamanic_spirit: SpeciesMeta,
pub jiangshi: SpeciesMeta, pub jiangshi: SpeciesMeta,
pub treasure_egg: SpeciesMeta,
} }
impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta> { impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta> {
@ -104,11 +106,12 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta>
Species::Flamekeeper => &self.flamekeeper, Species::Flamekeeper => &self.flamekeeper,
Species::ShamanicSpirit => &self.shamanic_spirit, Species::ShamanicSpirit => &self.shamanic_spirit,
Species::Jiangshi => &self.jiangshi, Species::Jiangshi => &self.jiangshi,
Species::TreasureEgg => &self.treasure_egg,
} }
} }
} }
pub const ALL_SPECIES: [Species; 18] = [ pub const ALL_SPECIES: [Species; 19] = [
Species::Gnome, Species::Gnome,
Species::Sahagin, Species::Sahagin,
Species::Adlet, Species::Adlet,
@ -127,6 +130,7 @@ pub const ALL_SPECIES: [Species; 18] = [
Species::Flamekeeper, Species::Flamekeeper,
Species::ShamanicSpirit, Species::ShamanicSpirit,
Species::Jiangshi, Species::Jiangshi,
Species::TreasureEgg,
]; ];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> { impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {

View File

@ -121,6 +121,7 @@ make_case_elim!(
TerracottaStatue = 106, TerracottaStatue = 106,
TerracottaDemolisherBomb = 107, TerracottaDemolisherBomb = 107,
BoltBesieger = 108, BoltBesieger = 108,
SurpriseEgg = 109,
} }
); );
@ -131,7 +132,7 @@ impl Body {
} }
} }
pub const ALL_OBJECTS: [Body; 109] = [ pub const ALL_OBJECTS: [Body; 110] = [
Body::Arrow, Body::Arrow,
Body::Bomb, Body::Bomb,
Body::Scarecrow, Body::Scarecrow,
@ -241,6 +242,7 @@ pub const ALL_OBJECTS: [Body; 109] = [
Body::Pebble, Body::Pebble,
Body::TerracottaStatue, Body::TerracottaStatue,
Body::BoltBesieger, Body::BoltBesieger,
Body::SurpriseEgg,
]; ];
impl From<Body> for super::Body { impl From<Body> for super::Body {
@ -359,6 +361,7 @@ impl Body {
Body::Pebble => "pebble", Body::Pebble => "pebble",
Body::TerracottaStatue => "terracotta_statue", Body::TerracottaStatue => "terracotta_statue",
Body::BoltBesieger => "besieger_bolt", Body::BoltBesieger => "besieger_bolt",
Body::SurpriseEgg => "surprise_egg",
} }
} }
@ -391,8 +394,9 @@ impl Body {
| Body::AdletSpear | Body::AdletSpear
| Body::AdletTrap | Body::AdletTrap
| Body::Flamethrower => 500.0, | Body::Flamethrower => 500.0,
Body::Bomb | Body::Mine => 2000.0, // I have no idea what it's supposed to be Body::Bomb | Body::Mine | Body::SurpriseEgg => 2000.0, /* I have no idea what it's */
Body::Crate => 300.0, // a lot of wood and maybe some contents // supposed to be
Body::Crate => 300.0, // a lot of wood and maybe some contents
Body::Scarecrow => 900.0, Body::Scarecrow => 900.0,
Body::TrainingDummy => 2000.0, Body::TrainingDummy => 2000.0,
Body::Snowball => 0.9 * WATER_DENSITY, Body::Snowball => 0.9 * WATER_DENSITY,
@ -425,7 +429,7 @@ impl Body {
| Body::Pebble | Body::Pebble
| Body::BoltBesieger => 1.0, | Body::BoltBesieger => 1.0,
Body::SpitPoison => 100.0, Body::SpitPoison => 100.0,
Body::Bomb | Body::DagonBomb | Body::TerracottaDemolisherBomb => { Body::Bomb | Body::DagonBomb | Body::SurpriseEgg | Body::TerracottaDemolisherBomb => {
0.5 * IRON_DENSITY * std::f32::consts::PI / 6.0 * self.dimensions().x.powi(3) 0.5 * IRON_DENSITY * std::f32::consts::PI / 6.0 * self.dimensions().x.powi(3)
}, },
Body::Campfire | Body::CampfireLit | Body::BarrelOrgan | Body::TerracottaStatue => { Body::Campfire | Body::CampfireLit | Body::BarrelOrgan | Body::TerracottaStatue => {

View File

@ -34,7 +34,7 @@ use vek::Rgb;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Throwable { pub enum Throwable {
Bomb, Bomb,
Mine, SurpriseEgg,
TrainingDummy, TrainingDummy,
Firework(Reagent), Firework(Reagent),
} }

View File

@ -26,6 +26,9 @@ pub enum Object {
requires_no_aggro: bool, requires_no_aggro: bool,
buildup_time: Secs, buildup_time: Secs,
}, },
SurpriseEgg {
owner: Option<Uid>,
},
} }
impl Component for Object { impl Component for Object {

View File

@ -115,6 +115,9 @@ pub enum Outcome {
TerracottaStatueCharge { TerracottaStatueCharge {
pos: Vec3<f32>, pos: Vec3<f32>,
}, },
SurpriseEgg {
pos: Vec3<f32>,
},
Utterance { Utterance {
pos: Vec3<f32>, pos: Vec3<f32>,
body: comp::Body, body: comp::Body,
@ -191,6 +194,7 @@ impl Outcome {
| Outcome::FlamethrowerCharge { pos } | Outcome::FlamethrowerCharge { pos }
| Outcome::FuseCharge { pos } | Outcome::FuseCharge { pos }
| Outcome::TerracottaStatueCharge { pos } | Outcome::TerracottaStatueCharge { pos }
| Outcome::SurpriseEgg { pos }
| Outcome::LaserBeam { pos } | Outcome::LaserBeam { pos }
| Outcome::GroundDig { pos } | Outcome::GroundDig { pos }
| Outcome::PortalActivated { pos } | Outcome::PortalActivated { pos }

View File

@ -1065,7 +1065,7 @@ impl ServerEvent for InventoryManipEvent {
vel: comp::Vel(vel), vel: comp::Vel(vel),
body: match kind { body: match kind {
item::Throwable::Bomb => comp::object::Body::Bomb, item::Throwable::Bomb => comp::object::Body::Bomb,
item::Throwable::Mine => comp::object::Body::Mine, item::Throwable::SurpriseEgg => comp::object::Body::SurpriseEgg,
item::Throwable::Firework(reagent) => comp::object::Body::for_firework(reagent), item::Throwable::Firework(reagent) => comp::object::Body::for_firework(reagent),
item::Throwable::TrainingDummy => comp::object::Body::TrainingDummy, item::Throwable::TrainingDummy => comp::object::Body::TrainingDummy,
}, },
@ -1075,7 +1075,9 @@ impl ServerEvent for InventoryManipEvent {
owner: Some(owner), owner: Some(owner),
reagent, reagent,
}), }),
item::Throwable::Mine => Some(comp::Object::Bomb { owner: Some(owner) }), item::Throwable::SurpriseEgg => {
Some(comp::Object::SurpriseEgg { owner: Some(owner) })
},
item::Throwable::TrainingDummy => None, item::Throwable::TrainingDummy => None,
}, },
light_emitter: match kind { light_emitter: match kind {

View File

@ -98,6 +98,12 @@ impl<'a> System<'a> for Sys {
}); });
} }
}, },
Object::SurpriseEgg { .. } => {
if physics.is_some_and(|physics| physics.on_surface().is_some()) {
emitters.emit(DeleteEvent(entity));
outcome_bus.emit_now(Outcome::SurpriseEgg { pos: pos.0 });
}
},
Object::Firework { owner, reagent } => { Object::Firework { owner, reagent } => {
if vel.0.z < 0.0 { if vel.0.z < 0.0 {
const ENABLE_RECURSIVE_FIREWORKS: bool = true; const ENABLE_RECURSIVE_FIREWORKS: bool = true;

View File

@ -167,6 +167,7 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Flamekeeper, _) => (3.0, 3.5), (Flamekeeper, _) => (3.0, 3.5),
(ShamanicSpirit, _) => (-0.5, 4.5), (ShamanicSpirit, _) => (-0.5, 4.5),
(Jiangshi, _) => (-1.0, 6.5), (Jiangshi, _) => (-1.0, 6.5),
(TreasureEgg, _) => (-1.0, 9.0),
}, },
chest: match (body.species, body.body_type) { chest: match (body.species, body.body_type) {
(Gnome, _) => (0.0, 9.0), (Gnome, _) => (0.0, 9.0),
@ -187,6 +188,7 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Flamekeeper, _) => (0.0, 14.0), (Flamekeeper, _) => (0.0, 14.0),
(ShamanicSpirit, _) => (0.0, 14.5), (ShamanicSpirit, _) => (0.0, 14.5),
(Jiangshi, _) => (0.0, 14.0), (Jiangshi, _) => (0.0, 14.0),
(TreasureEgg, _) => (0.0, 3.0),
}, },
pants: match (body.species, body.body_type) { pants: match (body.species, body.body_type) {
(Gnome, _) => (0.0, -3.0), (Gnome, _) => (0.0, -3.0),
@ -207,6 +209,7 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Flamekeeper, _) => (-1.0, -8.0), (Flamekeeper, _) => (-1.0, -8.0),
(ShamanicSpirit, _) => (0.0, -8.0), (ShamanicSpirit, _) => (0.0, -8.0),
(Jiangshi, _) => (0.5, -6.0), (Jiangshi, _) => (0.5, -6.0),
(TreasureEgg, _) => (0.0, 1.0),
}, },
tail: match (body.species, body.body_type) { tail: match (body.species, body.body_type) {
(Gnome, _) => (0.0, 0.0), (Gnome, _) => (0.0, 0.0),
@ -227,6 +230,7 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Flamekeeper, _) => (0.0, 0.0), (Flamekeeper, _) => (0.0, 0.0),
(ShamanicSpirit, _) => (0.0, 0.0), (ShamanicSpirit, _) => (0.0, 0.0),
(Jiangshi, _) => (0.0, 0.0), (Jiangshi, _) => (0.0, 0.0),
(TreasureEgg, _) => (0.0, 0.0),
}, },
hand: match (body.species, body.body_type) { hand: match (body.species, body.body_type) {
(Gnome, _) => (4.0, 0.5, -1.0), (Gnome, _) => (4.0, 0.5, -1.0),
@ -247,6 +251,7 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Flamekeeper, _) => (4.0, 1.5, -3.5), (Flamekeeper, _) => (4.0, 1.5, -3.5),
(ShamanicSpirit, _) => (5.0, 0.0, 1.0), (ShamanicSpirit, _) => (5.0, 0.0, 1.0),
(Jiangshi, _) => (5.0, -1.0, 3.0), (Jiangshi, _) => (5.0, -1.0, 3.0),
(TreasureEgg, _) => (5.0, 2.0, 5.0),
}, },
foot: match (body.species, body.body_type) { foot: match (body.species, body.body_type) {
(Gnome, _) => (3.0, 0.0, 4.0), (Gnome, _) => (3.0, 0.0, 4.0),
@ -267,6 +272,7 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Flamekeeper, _) => (3.5, 3.0, 7.0), (Flamekeeper, _) => (3.5, 3.0, 7.0),
(ShamanicSpirit, _) => (3.5, 3.0, 7.0), (ShamanicSpirit, _) => (3.5, 3.0, 7.0),
(Jiangshi, _) => (3.0, 0.0, 8.0), (Jiangshi, _) => (3.0, 0.0, 8.0),
(TreasureEgg, _) => (2.0, 0.5, 4.0),
}, },
grip: match (body.species, body.body_type) { grip: match (body.species, body.body_type) {
(Gnome, _) => (0.0, 0.0, 5.0), (Gnome, _) => (0.0, 0.0, 5.0),
@ -287,6 +293,7 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Flamekeeper, _) => (0.0, 0.0, 8.0), (Flamekeeper, _) => (0.0, 0.0, 8.0),
(ShamanicSpirit, _) => (0.0, 0.0, 8.0), (ShamanicSpirit, _) => (0.0, 0.0, 8.0),
(Jiangshi, _) => (0.0, 0.0, 8.0), (Jiangshi, _) => (0.0, 0.0, 8.0),
(TreasureEgg, _) => (0.0, 0.0, 7.0),
}, },
scaler: match (body.species, body.body_type) { scaler: match (body.species, body.body_type) {
(Gnome, _) => 0.8, (Gnome, _) => 0.8,
@ -307,6 +314,7 @@ impl<'a> From<&'a Body> for SkeletonAttr {
(Flamekeeper, _) => 4.0, (Flamekeeper, _) => 4.0,
(ShamanicSpirit, _) => 1.0, (ShamanicSpirit, _) => 1.0,
(Jiangshi, _) => 1.0, (Jiangshi, _) => 1.0,
(TreasureEgg, _) => 1.0,
}, },
} }
} }

View File

@ -182,6 +182,7 @@ pub enum SfxEvent {
PortalActivated, PortalActivated,
TeleportedByPortal, TeleportedByPortal,
FromTheAshes, FromTheAshes,
SurpriseEgg,
} }
#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Hash, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Deserialize, Hash, Eq)]
@ -462,6 +463,10 @@ impl SfxMgr {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::GroundSlam); let sfx_trigger_item = triggers.get_key_value(&SfxEvent::GroundSlam);
audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater);
}, },
Outcome::SurpriseEgg { pos, .. } => {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::SurpriseEgg);
audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater);
},
Outcome::LaserBeam { pos, .. } => { Outcome::LaserBeam { pos, .. } => {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::LaserBeam); let sfx_trigger_item = triggers.get_key_value(&SfxEvent::LaserBeam);
audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater);

View File

@ -112,6 +112,7 @@ pub enum ParticleMode {
ClayShrapnel = 58, ClayShrapnel = 58,
Airflow = 59, Airflow = 59,
Spore = 60, Spore = 60,
SurpriseEgg = 61,
} }
impl ParticleMode { impl ParticleMode {

View File

@ -351,6 +351,16 @@ impl ParticleMgr {
) )
}); });
}, },
Outcome::SurpriseEgg { pos, .. } => {
self.particles.resize_with(self.particles.len() + 50, || {
Particle::new(
Duration::from_millis(1000),
time,
ParticleMode::SurpriseEgg,
*pos,
)
});
},
Outcome::FlashFreeze { pos, .. } => { Outcome::FlashFreeze { pos, .. } => {
self.particles.resize_with( self.particles.resize_with(
self.particles.len() self.particles.len()

View File

@ -171,6 +171,10 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
"world.wildlife.spawn.calendar.april_fools.tundra.core", "world.wildlife.spawn.calendar.april_fools.tundra.core",
|c, _col| close(c.temp, CONFIG.snow_temp, 0.15) * BASE_DENSITY * 0.5, |c, _col| close(c.temp, CONFIG.snow_temp, 0.15) * BASE_DENSITY * 0.5,
), ),
(
"world.wildlife.spawn.calendar.easter.tundra.core",
|c, _col| close(c.temp, CONFIG.snow_temp, 0.15) * BASE_DENSITY * 0.5,
),
// Snowy animals // Snowy animals
("world.wildlife.spawn.tundra.snow", |c, col| { ("world.wildlife.spawn.tundra.snow", |c, col| {
close(c.temp, CONFIG.snow_temp, 0.3) * BASE_DENSITY * col.snow_cover as i32 as f32 * 1.0 close(c.temp, CONFIG.snow_temp, 0.3) * BASE_DENSITY * col.snow_cover as i32 as f32 * 1.0
@ -203,6 +207,15 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
* 1.0 * 1.0
}, },
), ),
(
"world.wildlife.spawn.calendar.easter.tundra.snow",
|c, col| {
close(c.temp, CONFIG.snow_temp, 0.3)
* BASE_DENSITY
* col.snow_cover as i32 as f32
* 1.0
},
),
// Forest animals // Forest animals
("world.wildlife.spawn.tundra.forest", |c, col| { ("world.wildlife.spawn.tundra.forest", |c, col| {
close(c.temp, CONFIG.snow_temp, 0.3) * col.tree_density * BASE_DENSITY * 1.4 close(c.temp, CONFIG.snow_temp, 0.3) * col.tree_density * BASE_DENSITY * 1.4
@ -232,6 +245,10 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
"world.wildlife.spawn.calendar.april_fools.tundra.forest", "world.wildlife.spawn.calendar.april_fools.tundra.forest",
|c, col| close(c.temp, CONFIG.snow_temp, 0.3) * col.tree_density * BASE_DENSITY * 1.4, |c, col| close(c.temp, CONFIG.snow_temp, 0.3) * col.tree_density * BASE_DENSITY * 1.4,
), ),
(
"world.wildlife.spawn.calendar.easter.tundra.forest",
|c, col| close(c.temp, CONFIG.snow_temp, 0.3) * col.tree_density * BASE_DENSITY * 1.4,
),
// **Taiga** // **Taiga**
// Forest core animals // Forest core animals
("world.wildlife.spawn.taiga.core_forest", |c, col| { ("world.wildlife.spawn.taiga.core_forest", |c, col| {
@ -256,6 +273,12 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
close(c.temp, CONFIG.snow_temp + 0.2, 0.2) * col.tree_density * BASE_DENSITY * 0.4 close(c.temp, CONFIG.snow_temp + 0.2, 0.2) * col.tree_density * BASE_DENSITY * 0.4
}, },
), ),
(
"world.wildlife.spawn.calendar.easter.taiga.core",
|c, col| {
close(c.temp, CONFIG.snow_temp + 0.2, 0.2) * col.tree_density * BASE_DENSITY * 0.4
},
),
// Core animals // Core animals
("world.wildlife.spawn.taiga.core", |c, _col| { ("world.wildlife.spawn.taiga.core", |c, _col| {
close(c.temp, CONFIG.snow_temp + 0.2, 0.2) * BASE_DENSITY * 1.0 close(c.temp, CONFIG.snow_temp + 0.2, 0.2) * BASE_DENSITY * 1.0
@ -338,6 +361,15 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
* 4.0 * 4.0
}, },
), ),
(
"world.wildlife.spawn.calendar.easter.temperate.rainforest",
|c, _col| {
close(c.temp, CONFIG.temperate_temp + 0.1, 0.6)
* close(c.humidity, CONFIG.forest_hum, 0.6)
* BASE_DENSITY
* 4.0
},
),
// Ocean animals // Ocean animals
("world.wildlife.spawn.temperate.ocean", |_c, col| { ("world.wildlife.spawn.temperate.ocean", |_c, col| {
close(col.temp, CONFIG.temperate_temp, 1.0) / 10.0 close(col.temp, CONFIG.temperate_temp, 1.0) / 10.0
@ -395,6 +427,15 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
* 8.0 * 8.0
}, },
), ),
(
"world.wildlife.spawn.calendar.easter.jungle.area",
|c, _col| {
close(c.temp, CONFIG.tropical_temp + 0.2, 0.3)
* close(c.humidity, CONFIG.jungle_hum, 0.2)
* BASE_DENSITY
* 8.0
},
),
// **Tropical** // **Tropical**
// River animals // River animals
("world.wildlife.spawn.tropical.river", |c, col| { ("world.wildlife.spawn.tropical.river", |c, col| {