From e48e3e11baf377aac5de0fc4880ec4e496084ea2 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Fri, 21 May 2021 09:52:03 +0300 Subject: [PATCH 1/4] Give bosses own creation function and loot table - Make goose miniboss fallback to differentiate bosses and minibosses --- .../loot_tables/dungeon/tier-0/boss.ron | 3 + .../loot_tables/dungeon/tier-1/boss.ron | 3 + .../loot_tables/dungeon/tier-2/boss.ron | 3 + .../loot_tables/dungeon/tier-3/boss.ron | 3 + .../loot_tables/dungeon/tier-4/boss.ron | 3 + world/src/site/dungeon/mod.rs | 253 +++++++++--------- 6 files changed, 145 insertions(+), 123 deletions(-) create mode 100644 assets/common/loot_tables/dungeon/tier-0/boss.ron create mode 100644 assets/common/loot_tables/dungeon/tier-1/boss.ron create mode 100644 assets/common/loot_tables/dungeon/tier-2/boss.ron create mode 100644 assets/common/loot_tables/dungeon/tier-3/boss.ron create mode 100644 assets/common/loot_tables/dungeon/tier-4/boss.ron diff --git a/assets/common/loot_tables/dungeon/tier-0/boss.ron b/assets/common/loot_tables/dungeon/tier-0/boss.ron new file mode 100644 index 0000000000..61eb15dd68 --- /dev/null +++ b/assets/common/loot_tables/dungeon/tier-0/boss.ron @@ -0,0 +1,3 @@ +[ + (1.0, LootTable("common.loot_tables.weapons.tier-0")), +] diff --git a/assets/common/loot_tables/dungeon/tier-1/boss.ron b/assets/common/loot_tables/dungeon/tier-1/boss.ron new file mode 100644 index 0000000000..e8aeabe107 --- /dev/null +++ b/assets/common/loot_tables/dungeon/tier-1/boss.ron @@ -0,0 +1,3 @@ +[ + (1.0, LootTable("common.loot_tables.weapons.tier-1")), +] diff --git a/assets/common/loot_tables/dungeon/tier-2/boss.ron b/assets/common/loot_tables/dungeon/tier-2/boss.ron new file mode 100644 index 0000000000..b3f1438a9d --- /dev/null +++ b/assets/common/loot_tables/dungeon/tier-2/boss.ron @@ -0,0 +1,3 @@ +[ + (1.0, LootTable("common.loot_tables.weapons.tier-2")), +] diff --git a/assets/common/loot_tables/dungeon/tier-3/boss.ron b/assets/common/loot_tables/dungeon/tier-3/boss.ron new file mode 100644 index 0000000000..d62f2d530b --- /dev/null +++ b/assets/common/loot_tables/dungeon/tier-3/boss.ron @@ -0,0 +1,3 @@ +[ + (1.0, LootTable("common.loot_tables.weapons.tier-3")), +] diff --git a/assets/common/loot_tables/dungeon/tier-4/boss.ron b/assets/common/loot_tables/dungeon/tier-4/boss.ron new file mode 100644 index 0000000000..971386273b --- /dev/null +++ b/assets/common/loot_tables/dungeon/tier-4/boss.ron @@ -0,0 +1,3 @@ +[ + (1.0, LootTable("common.loot_tables.weapons.tier-4")), +] diff --git a/world/src/site/dungeon/mod.rs b/world/src/site/dungeon/mod.rs index f0acba138b..42b9903e7a 100644 --- a/world/src/site/dungeon/mod.rs +++ b/world/src/site/dungeon/mod.rs @@ -796,126 +796,17 @@ impl Floor { boss_spawn_tile + if boss_tile_is_pillar { 1 } else { 0 }; if tile_pos == boss_spawn_tile && tile_wcenter.xy() == wpos2d { - let chosen = match room.difficulty { - 0 => Lottery::::load_expect( - "common.loot_tables.weapons.tier-0", - ), - 1 => Lottery::::load_expect( - "common.loot_tables.weapons.tier-1", - ), - 2 => Lottery::::load_expect( - "common.loot_tables.weapons.tier-2", - ), - 3 => Lottery::::load_expect( - "common.loot_tables.weapons.tier-3", - ), - 4 => Lottery::::load_expect( - "common.loot_tables.weapons.tier-4", - ), - 5 => Lottery::::load_expect( - "common.loot_tables.dungeon.tier-5.boss", - ), - _ => { - Lottery::::load_expect("common.loot_tables.fallback") - }, - }; - let entity = match room.difficulty { - 0 => { - vec![ - EntityInfo::at(tile_wcenter.map(|e| e as f32)) - .with_body(comp::Body::BipedLarge( - comp::biped_large::Body::random_with( - dynamic_rng, - &comp::biped_large::Species::Harvester, - ), - )) - .with_name("Harvester".to_string()) - .with_loot_drop(chosen.read().choose().to_item()), - ] - }, - 1 => { - vec![ - EntityInfo::at(tile_wcenter.map(|e| e as f32)) - .with_body(comp::Body::BipedLarge( - comp::biped_large::Body::random_with( - dynamic_rng, - &comp::biped_large::Species::Yeti, - ), - )) - .with_name("Yeti".to_string()) - .with_loot_drop(chosen.read().choose().to_item()), - ] - }, - 2 => { - vec![ - EntityInfo::at(tile_wcenter.map(|e| e as f32)) - .with_body(comp::Body::BipedLarge( - comp::biped_large::Body::random_with( - dynamic_rng, - &comp::biped_large::Species::Tidalwarrior, - ), - )) - .with_name("Tidal Warrior".to_string()) - .with_loot_drop(chosen.read().choose().to_item()), - ] - }, - 3 => { - let mut entities = Vec::new(); - entities.resize_with(2, || { - EntityInfo::at(tile_wcenter.map(|e| e as f32)) - .with_body(comp::Body::Golem( - comp::golem::Body::random_with( - dynamic_rng, - &comp::golem::Species::ClayGolem, - ), - )) - .with_name("Clay Golem".to_string()) - .with_loot_drop(chosen.read().choose().to_item()) - }); - entities - }, - 4 => { - vec![ - EntityInfo::at(tile_wcenter.map(|e| e as f32)) - .with_body(comp::Body::BipedLarge( - comp::biped_large::Body::random_with( - dynamic_rng, - &comp::biped_large::Species::Minotaur, - ), - )) - .with_name("Minotaur".to_string()) - .with_loot_drop(chosen.read().choose().to_item()), - ] - }, - 5 => { - vec![ - EntityInfo::at(tile_wcenter.map(|e| e as f32)) - .with_body(comp::Body::BipedLarge( - comp::biped_large::Body::random_with( - dynamic_rng, - &comp::biped_large::Species::Mindflayer, - ), - )) - .with_name("Mindflayer".to_string()) - .with_loot_drop(chosen.read().choose().to_item()) - .with_skillset_config( - common::skillset_builder::SkillSetConfig::Mindflayer, - ), - ] - }, - _ => { - vec![EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_body( - comp::Body::QuadrupedSmall( - comp::quadruped_small::Body::random_with( - dynamic_rng, - &comp::quadruped_small::Species::Sheep, - ), - ), - )] - }, + let entities = match room.difficulty { + 0 => boss_0(dynamic_rng, tile_wcenter), + 1 => boss_1(dynamic_rng, tile_wcenter), + 2 => boss_2(dynamic_rng, tile_wcenter), + 3 => boss_3(dynamic_rng, tile_wcenter), + 4 => boss_4(dynamic_rng, tile_wcenter), + 5 => boss_5(dynamic_rng, tile_wcenter), + _ => boss_fallback(dynamic_rng, tile_wcenter), }; - for entity in entity { + for entity in entities { supplement.add_entity( entity .with_level( @@ -1223,6 +1114,111 @@ impl Floor { } } +fn boss_0(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { + let chosen = Lottery::::load_expect("common.loot_tables.dungeon.tier-0.boss"); + + vec![ + EntityInfo::at(tile_wcenter.map(|e| e as f32)) + .with_body(comp::Body::BipedLarge( + comp::biped_large::Body::random_with( + dynamic_rng, + &comp::biped_large::Species::Harvester, + ), + )) + .with_name("Harvester".to_string()) + .with_loot_drop(chosen.read().choose().to_item()), + ] +} +fn boss_1(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { + let chosen = Lottery::::load_expect("common.loot_tables.dungeon.tier-1.boss"); + + vec![ + EntityInfo::at(tile_wcenter.map(|e| e as f32)) + .with_body(comp::Body::BipedLarge( + comp::biped_large::Body::random_with( + dynamic_rng, + &comp::biped_large::Species::Yeti, + ), + )) + .with_name("Yeti".to_string()) + .with_loot_drop(chosen.read().choose().to_item()), + ] +} +fn boss_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { + let chosen = Lottery::::load_expect("common.loot_tables.dungeon.tier-2.boss"); + + vec![ + EntityInfo::at(tile_wcenter.map(|e| e as f32)) + .with_body(comp::Body::BipedLarge( + comp::biped_large::Body::random_with( + dynamic_rng, + &comp::biped_large::Species::Tidalwarrior, + ), + )) + .with_name("Tidal Warrior".to_string()) + .with_loot_drop(chosen.read().choose().to_item()), + ] +} +fn boss_3(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { + let chosen = Lottery::::load_expect("common.loot_tables.dungeon.tier-3.boss"); + + let mut entities = Vec::new(); + entities.resize_with(2, || { + EntityInfo::at(tile_wcenter.map(|e| e as f32)) + .with_body(comp::Body::Golem(comp::golem::Body::random_with( + dynamic_rng, + &comp::golem::Species::ClayGolem, + ))) + .with_name("Clay Golem".to_string()) + .with_loot_drop(chosen.read().choose().to_item()) + }); + entities +} + +fn boss_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { + let chosen = Lottery::::load_expect("common.loot_tables.dungeon.tier-4.boss"); + + vec![ + EntityInfo::at(tile_wcenter.map(|e| e as f32)) + .with_body(comp::Body::BipedLarge( + comp::biped_large::Body::random_with( + dynamic_rng, + &comp::biped_large::Species::Minotaur, + ), + )) + .with_name("Minotaur".to_string()) + .with_loot_drop(chosen.read().choose().to_item()), + ] +} + +fn boss_5(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { + let chosen = Lottery::::load_expect("common.loot_tables.dungeon.tier-5.boss"); + + vec![ + EntityInfo::at(tile_wcenter.map(|e| e as f32)) + .with_body(comp::Body::BipedLarge( + comp::biped_large::Body::random_with( + dynamic_rng, + &comp::biped_large::Species::Mindflayer, + ), + )) + .with_name("Mindflayer".to_string()) + .with_loot_drop(chosen.read().choose().to_item()) + .with_skillset_config(common::skillset_builder::SkillSetConfig::Mindflayer), + ] +} + +fn boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { + vec![ + EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_body(comp::Body::QuadrupedSmall( + comp::quadruped_small::Body::random_with( + dynamic_rng, + &comp::quadruped_small::Species::Sheep, + ), + )), + ] +} + fn mini_boss_0(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { let chosen = Lottery::::load_expect("common.loot_tables.weapons.tier-0"); vec![ @@ -1362,11 +1358,8 @@ fn mini_boss_5(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { vec![ - EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_body(comp::Body::QuadrupedSmall( - comp::quadruped_small::Body::random_with( - dynamic_rng, - &comp::quadruped_small::Species::Sheep, - ), + EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_body(comp::Body::BirdMedium( + comp::bird_medium::Body::random_with(dynamic_rng, &comp::bird_medium::Species::Goose), )), ] } @@ -1375,6 +1368,19 @@ fn mini_boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Ve mod tests { use super::*; + #[test] + fn test_creating_bosses() { + let mut dynamic_rng = rand::thread_rng(); + let tile_wcenter = Vec3::new(0, 0, 0); + boss_0(&mut dynamic_rng, tile_wcenter); + boss_1(&mut dynamic_rng, tile_wcenter); + boss_2(&mut dynamic_rng, tile_wcenter); + boss_3(&mut dynamic_rng, tile_wcenter); + boss_4(&mut dynamic_rng, tile_wcenter); + boss_5(&mut dynamic_rng, tile_wcenter); + boss_fallback(&mut dynamic_rng, tile_wcenter); + } + #[test] fn test_creating_minibosses() { let mut dynamic_rng = rand::thread_rng(); @@ -1387,4 +1393,5 @@ mod tests { mini_boss_5(&mut dynamic_rng, tile_wcenter); mini_boss_fallback(&mut dynamic_rng, tile_wcenter); } + } From df58fa9acf8c1df4374b15c019132bcab61840a3 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Fri, 21 May 2021 11:20:37 +0300 Subject: [PATCH 2/4] Fixing loot tables - Use quad_low and quad_medium loot table for corresponding mobs in dungeons - Remove cultist loot table from T3-T4 loot tables - Use resize instead of vec[obj; len] to create different loot and not duplicated for miniboss_1 --- .../loot_tables/dungeon/tier-3/enemy.ron | 3 +-- .../loot_tables/dungeon/tier-4/enemy.ron | 4 ++-- world/src/site/dungeon/mod.rs | 19 ++++++++++--------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/assets/common/loot_tables/dungeon/tier-3/enemy.ron b/assets/common/loot_tables/dungeon/tier-3/enemy.ron index e7c466dfa9..0efcda9998 100644 --- a/assets/common/loot_tables/dungeon/tier-3/enemy.ron +++ b/assets/common/loot_tables/dungeon/tier-3/enemy.ron @@ -2,5 +2,4 @@ (1.0, LootTable("common.loot_tables.humanoids")), (1.0, LootTable("common.loot_tables.armor.steel")), (1.0, LootTable("common.loot_tables.weapons.tier-3")), - (3.0, LootTable("common.loot_tables.cultists")), -] \ No newline at end of file +] diff --git a/assets/common/loot_tables/dungeon/tier-4/enemy.ron b/assets/common/loot_tables/dungeon/tier-4/enemy.ron index 95c6ccb8dd..696bef6900 100644 --- a/assets/common/loot_tables/dungeon/tier-4/enemy.ron +++ b/assets/common/loot_tables/dungeon/tier-4/enemy.ron @@ -1,5 +1,5 @@ [ (1.0, LootTable("common.loot_tables.humanoids")), + (1.0, LootTable("common.loot_tables.armor.steel")), (1.0, LootTable("common.loot_tables.weapons.tier-4")), - (5.0, LootTable("common.loot_tables.cultists")), -] \ No newline at end of file +] diff --git a/world/src/site/dungeon/mod.rs b/world/src/site/dungeon/mod.rs index 42b9903e7a..21b1129426 100644 --- a/world/src/site/dungeon/mod.rs +++ b/world/src/site/dungeon/mod.rs @@ -1220,7 +1220,7 @@ fn boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { - let chosen = Lottery::::load_expect("common.loot_tables.weapons.tier-0"); + let chosen = Lottery::::load_expect("common.loot_tables.creature.quad_medium.default"); vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32)) .with_body(comp::Body::QuadrupedMedium( @@ -1235,8 +1235,9 @@ fn mini_boss_0(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { - let chosen = Lottery::::load_expect("common.loot_tables.weapons.tier-1"); - vec![ + let chosen = Lottery::::load_expect("common.loot_tables.creature.quad_medium.default"); + let mut entities = Vec::new(); + entities.resize_with(3, || { EntityInfo::at(tile_wcenter.map(|e| e as f32)) .with_body(comp::Body::QuadrupedMedium( comp::quadruped_medium::Body::random_with( @@ -1245,13 +1246,13 @@ fn mini_boss_1(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { - let chosen = Lottery::::load_expect("common.loot_tables.weapons.tier-2"); + let chosen = Lottery::::load_expect("common.loot_tables.creature.quad_low.default"); let mut entities = Vec::new(); entities.resize_with(6, || { EntityInfo::at(tile_wcenter.map(|e| e as f32)) @@ -1268,9 +1269,9 @@ fn mini_boss_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { - let chosen = Lottery::::load_expect("common.loot_tables.weapons.tier-3"); + let chosen = Lottery::::load_expect("common.loot_tables.creature.quad_low.default"); let mut entities = Vec::new(); - entities.resize_with(6, || { + entities.resize_with(8, || { EntityInfo::at(tile_wcenter.map(|e| e as f32)) .with_body(comp::Body::QuadrupedLow( comp::quadruped_low::Body::random_with( From 5d8685029146f2519a7e24b2170c08777120bedc Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Fri, 21 May 2021 11:36:48 +0300 Subject: [PATCH 3/4] fmt --- world/src/site/dungeon/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/world/src/site/dungeon/mod.rs b/world/src/site/dungeon/mod.rs index 21b1129426..43014f718e 100644 --- a/world/src/site/dungeon/mod.rs +++ b/world/src/site/dungeon/mod.rs @@ -1220,7 +1220,8 @@ fn boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { - let chosen = Lottery::::load_expect("common.loot_tables.creature.quad_medium.default"); + let chosen = + Lottery::::load_expect("common.loot_tables.creature.quad_medium.default"); vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32)) .with_body(comp::Body::QuadrupedMedium( @@ -1235,7 +1236,8 @@ fn mini_boss_0(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { - let chosen = Lottery::::load_expect("common.loot_tables.creature.quad_medium.default"); + let chosen = + Lottery::::load_expect("common.loot_tables.creature.quad_medium.default"); let mut entities = Vec::new(); entities.resize_with(3, || { EntityInfo::at(tile_wcenter.map(|e| e as f32)) @@ -1394,5 +1396,4 @@ mod tests { mini_boss_5(&mut dynamic_rng, tile_wcenter); mini_boss_fallback(&mut dynamic_rng, tile_wcenter); } - } From 849d51aaa3f70e937d1a2789cd89e7ce7eacfc7d Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Fri, 21 May 2021 19:33:31 +0300 Subject: [PATCH 4/4] Add note to tests --- world/src/site/dungeon/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/world/src/site/dungeon/mod.rs b/world/src/site/dungeon/mod.rs index 43014f718e..42adb0ef0c 100644 --- a/world/src/site/dungeon/mod.rs +++ b/world/src/site/dungeon/mod.rs @@ -1384,6 +1384,16 @@ mod tests { boss_fallback(&mut dynamic_rng, tile_wcenter); } + //FIXME: it will miss items with rng branching + // like this + // .with_main_tool(comp::Item::new_from_asset_expect( + // match dynamic_rng.gen_range(0..6) { + // 0 => "common.items.weapons.axe.malachite_axe-0", + // 1..=2 => "common.items.weapons.sword.cultist", + // 3 => "common.items.weapons.hammer.cultist_purp_2h-0", + // 4 => "common.items.weapons.staff.cultist_staff", + // _ => "common.items.weapons.bow.velorite", + // }, #[test] fn test_creating_minibosses() { let mut dynamic_rng = rand::thread_rng();