Removed all rng matches in code to determine loot tables, and moved to loot tables specific for each sprite, creature, or dungeon.

This commit is contained in:
Sam
2021-04-02 23:03:59 -04:00
parent 9ad5b0f6b7
commit 27f178286d
40 changed files with 416 additions and 453 deletions

View File

@ -0,0 +1,4 @@
[
(1.0, LootTable("common.loot_tables.food.prepared")),
(2.0, LootTable("common.loot_tables.cave_large")),
]

View File

@ -0,0 +1,6 @@
[
(1.0, LootTable("common.loot_tables.food.prepared")),
(1.0, LootTable("common.loot_tables.cave_large")),
(1.0, LootTable("common.loot_tables.weapons.tier-2")),
(5.0, Item("common.items.crafting_ing.leather_troll")),
]

View File

@ -0,0 +1,6 @@
[
(1.0, LootTable("common.loot_tables.food.prepared")),
(1.0, Item("common.items.crafting_ing.icy_fang")),
(1.0, LootTable("common.loot_tables.weapons.tier-2")),
(4.0, LootTable("common.loot_tables.cave_large")),
]

View File

@ -0,0 +1,4 @@
[
(1.0, LootTable("common.loot_tables.food.wild_ingredients")),
(1.0, LootTable("common.loot_tables.fallback")),
]

View File

@ -0,0 +1,3 @@
[
(1.0, LootTable("common.loot_tables.weapons.tier-5")),
]

View File

@ -0,0 +1,7 @@
[
(1.0, LootTable("common.loot_tables.food.prepared")),
(1.0, LootTable("common.loot_tables.armor.steel")),
(1.0, LootTable("common.loot_tables.weapons.tier-1")),
(1.0, LootTable("common.loot_tables.weapons.tier-2")),
(1.0, LootTable("common.loot_tables.weapons.tier-3")),
]

View File

@ -0,0 +1,7 @@
[
(1.0, LootTable("common.loot_tables.humanoids")),
(1.0, LootTable("common.loot_tables.armor.swift")),
(1.0, LootTable("common.loot_tables.armor.cloth")),
(1.0, LootTable("common.loot_tables.weapons.starter")),
(1.0, LootTable("common.loot_tables.fallback")),
]

View File

@ -0,0 +1,5 @@
[
(1.0, LootTable("common.loot_tables.food.wild_ingredients")),
(1.0, Item("common.items.crafting_ing.leather_scraps")),
(1.0, LootTable("common.loot_tables.fallback")),
]

View File

@ -0,0 +1,4 @@
[
(1.0, LootTable("common.loot_tables.food.wild_ingredients")),
(1.0, Item("common.items.crafting_ing.leather_scraps")),
]

View File

@ -0,0 +1,5 @@
[
(1.0, LootTable("common.loot_tables.food.wild_ingredients")),
(1.0, Item("common.items.crafting_ing.leather_scraps")),
(1.0, Item("common.items.crafting_ing.icy_fang")),
]

View File

@ -0,0 +1,4 @@
[
(1.0, LootTable("common.loot_tables.food.wild_ingredients")),
(1.0, Item("common.items.crafting_ing.leather_scraps")),
]

View File

@ -0,0 +1,3 @@
[
(1.0, LootTable("common.loot_tables.materials.underground")),
]

View File

@ -1,4 +1,3 @@
[ [
(1.0, Item("common.items.crafting_ing.leather_scraps")), (1.0, Item("common.items.crafting_ing.leather_scraps")),
(1.0, CreatureMaterial),
] ]

View File

@ -0,0 +1,4 @@
[
(1.0, Item("common.items.crafting_ing.leather_scraps")),
(1.0, Item("common.items.crafting_ing.raptor_feather")),
]

View File

@ -0,0 +1,5 @@
[
(1.0, LootTable("common.loot_tables.humanoids")),
(1.0, LootTable("common.loot_tables.armor.cloth")),
(2.0, LootTable("common.loot_tables.weapons.tier-0")),
]

View File

@ -0,0 +1,5 @@
[
(1.0, LootTable("common.loot_tables.humanoids")),
(1.0, LootTable("common.loot_tables.armor.swift")),
(2.0, LootTable("common.loot_tables.weapons.tier-1")),
]

View File

@ -0,0 +1,5 @@
[
(1.0, LootTable("common.loot_tables.humanoids")),
(1.0, LootTable("common.loot_tables.armor.plate")),
(2.0, LootTable("common.loot_tables.weapons.tier-2")),
]

View File

@ -0,0 +1,6 @@
[
(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")),
]

View File

@ -0,0 +1,5 @@
[
(1.0, LootTable("common.loot_tables.humanoids")),
(1.0, LootTable("common.loot_tables.weapons.tier-4")),
(5.0, LootTable("common.loot_tables.cultists")),
]

View File

@ -0,0 +1,4 @@
[
(1.0, LootTable("common.loot_tables.creature.biped_large.mindflayer")),
(3.0, LootTable("common.loot_tables.miniboss")),
]

View File

@ -0,0 +1,6 @@
[
(1.0, LootTable("common.loot_tables.humanoids")),
(1.0, LootTable("common.loot_tables.weapons.tier-5")),
(3.0, LootTable("common.loot_tables.cultists")),
(5.0, Item("common.items.food.cheese")),
]

View File

@ -0,0 +1,6 @@
[
(1.0, LootTable("common.loot_tables.weapons.tier-1")),
(1.0, LootTable("common.loot_tables.armor.cloth")),
(1.0, LootTable("common.loot_tables.armor.swift")),
(1.0, LootTable("common.loot_tables.fallback")),
]

View File

@ -0,0 +1,8 @@
[
(1.0, LootTable("common.loot_tables.weapons.tier-0")),
(1.0, LootTable("common.loot_tables.weapons.tier-1")),
(1.0, LootTable("common.loot_tables.armor.cloth")),
(1.0, LootTable("common.loot_tables.armor.swift")),
(0.1, LootTable("common.loot_tables.armor.plate")),
(1.0, LootTable("common.loot_tables.fallback")),
]

View File

@ -0,0 +1,4 @@
[
(1.0, LootTable("common.loot_tables.materials.common")),
(2.0, LootTable("common.loot_tables.food.prepared")),
]

View File

@ -0,0 +1,6 @@
[
(1.0, LootTable("common.loot_tables.materials.common")),
(1.0, LootTable("common.loot_tables.weapons.tier-0")),
(1.0, LootTable("common.loot_tables.materials.underground")),
(1.0, LootTable("common.loot_tables.fallback")),
]

View File

@ -2190,7 +2190,7 @@ GrassBlue: Some((
wind_sway: 1.0, wind_sway: 1.0,
)), )),
// Underwater Chests // Underwater Chests
ChestBurried: Some(( ChestBuried: Some((
variations: [ variations: [
( (
model: "voxygen.voxel.sprite.underwater_chests.chest_skull", model: "voxygen.voxel.sprite.underwater_chests.chest_skull",

View File

@ -254,9 +254,6 @@ fn loot_table(loot_table: &str) -> Result<(), Box<dyn Error>> {
LootSpec::LootTable(table) => { LootSpec::LootTable(table) => {
wtr.write_record(&[&chance, "LootTable", table, "", ""])? wtr.write_record(&[&chance, "LootTable", table, "", ""])?
}, },
LootSpec::CreatureMaterial => {
wtr.write_record(&[&chance, "CreatureMaterial", "", "", ""])?
},
} }
} }

View File

@ -403,7 +403,6 @@ fn loot_table(loot_table: &str) -> Result<(), Box<dyn Error>> {
.expect("No loot table") .expect("No loot table")
.to_string(), .to_string(),
), ),
"CreatureMaterial" => LootSpec::CreatureMaterial,
a => panic!( a => panic!(
"Loot specifier kind must be either \"Item\" or \"LootTable\"\n{}", "Loot specifier kind must be either \"Item\" or \"LootTable\"\n{}",
a a

View File

@ -16,7 +16,6 @@ pub mod theropod;
use crate::{ use crate::{
assets::{self, Asset}, assets::{self, Asset},
comp::Item,
make_case_elim, make_case_elim,
npc::NpcKind, npc::NpcKind,
}; };
@ -583,30 +582,6 @@ impl Body {
_ => Vec3::unit_z(), _ => Vec3::unit_z(),
} }
} }
pub fn get_material(&self) -> Item {
Item::new_from_asset_expect(match self {
Body::QuadrupedSmall(_) => "common.items.crafting_ing.leather_scraps",
Body::QuadrupedMedium(b) => match b.species {
quadruped_medium::Species::Frostfang | quadruped_medium::Species::Roshwalr => {
"common.items.crafting_ing.icy_fang"
},
_ => "common.items.crafting_ing.leather_scraps",
},
Body::Theropod(b) => match b.species {
theropod::Species::Sandraptor
| theropod::Species::Snowraptor
| theropod::Species::Woodraptor => "common.items.crafting_ing.raptor_feather",
_ => "common.items.crafting_ing.leather_scraps",
},
Body::BipedLarge(b) => match b.species {
biped_large::Species::Troll => "common.items.crafting_ing.leather_troll",
biped_large::Species::Wendigo => "common.items.crafting_ing.icy_fang",
_ => "common.items.food.cheese",
},
_ => "common.items.food.cheese",
})
}
} }
impl Component for Body { impl Component for Body {

View File

@ -19,7 +19,6 @@ use crate::{
}; };
use core::mem; use core::mem;
use crossbeam_utils::atomic::AtomicCell; use crossbeam_utils::atomic::AtomicCell;
use rand::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage}; use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage; use specs_idvs::IdvStorage;
@ -579,7 +578,6 @@ impl Item {
pub fn try_reclaim_from_block(block: Block) -> Option<Self> { pub fn try_reclaim_from_block(block: Block) -> Option<Self> {
let chosen; let chosen;
let mut rng = rand::thread_rng();
Some(Item::new_from_asset_expect(match block.get_sprite()? { Some(Item::new_from_asset_expect(match block.get_sprite()? {
SpriteKind::Apple => "common.items.food.apple", SpriteKind::Apple => "common.items.food.apple",
SpriteKind::Mushroom => "common.items.food.mushroom", SpriteKind::Mushroom => "common.items.food.mushroom",
@ -601,44 +599,21 @@ impl Item {
// Containers // Containers
// IMPORTANT: Add any new container to `SpriteKind::is_container` // IMPORTANT: Add any new container to `SpriteKind::is_container`
SpriteKind::Chest => { SpriteKind::Chest => {
chosen = Lottery::<LootSpec>::load_expect(match rng.gen_range(0..7) { chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.sprite.chest").read();
0 => "common.loot_tables.weapons.tier-0", return Some(chosen.choose().to_item());
1 => "common.loot_tables.weapons.tier-1",
2 => "common.loot_tables.armor.swift",
3 => "common.loot_tables.armor.cloth",
4 => "common.loot_tables.armor.plate",
_ => "common.loot_tables.fallback",
})
.read();
return Some(chosen.choose().to_item(None));
}, },
SpriteKind::ChestBurried => { SpriteKind::ChestBuried => {
chosen = Lottery::<LootSpec>::load_expect(match rng.gen_range(0..7) { chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.sprite.chest-buried")
1 => "common.loot_tables.weapons.tier-1",
2 => "common.loot_tables.armor.swift",
3 => "common.loot_tables.armor.cloth",
_ => "common.loot_tables.fallback",
})
.read(); .read();
return Some(chosen.choose().to_item(None)); return Some(chosen.choose().to_item());
}, },
SpriteKind::Mud => { SpriteKind::Mud => {
chosen = Lottery::<LootSpec>::load_expect(match rng.gen_range(0..5) { chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.sprite.mud").read();
0 => "common.loot_tables.materials.common", return Some(chosen.choose().to_item());
1 => "common.loot_tables.weapons.tier-0",
2 => "common.loot_tables.materials.underground",
_ => "common.loot_tables.fallback",
})
.read();
return Some(chosen.choose().to_item(None));
}, },
SpriteKind::Crate => { SpriteKind::Crate => {
chosen = Lottery::<LootSpec>::load_expect(match rng.gen_range(0..4) { chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.sprite.crate").read();
0 => "common.loot_tables.materials.common", return Some(chosen.choose().to_item());
_ => "common.loot_tables.food.prepared",
})
.read();
return Some(chosen.choose().to_item(None));
}, },
SpriteKind::Beehive => "common.items.crafting_ing.honey", SpriteKind::Beehive => "common.items.crafting_ing.honey",

View File

@ -68,7 +68,6 @@ impl From<Vec<(f32, LootSpec)>> for ProbabilityFile {
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into_iter() .into_iter()
}, },
LootSpec::CreatureMaterial => vec![].into_iter(),
}) })
.collect(), .collect(),
} }

View File

@ -28,7 +28,7 @@
use crate::{ use crate::{
assets::{self, AssetExt}, assets::{self, AssetExt},
comp::{Body, Item}, comp::Item,
}; };
use rand::prelude::*; use rand::prelude::*;
use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde::{de::DeserializeOwned, Deserialize, Serialize};
@ -83,30 +83,23 @@ pub enum LootSpec {
ItemQuantity(String, u32, u32), ItemQuantity(String, u32, u32),
/// Loot table /// Loot table
LootTable(String), LootTable(String),
/// Matches on species to provide a crafting material
CreatureMaterial,
} }
impl LootSpec { impl LootSpec {
#[allow(unused_must_use)] pub fn to_item(&self) -> Item {
pub fn to_item(&self, body: Option<Body>) -> Item {
match self { match self {
Self::Item(item) => Item::new_from_asset_expect(&item), Self::Item(item) => Item::new_from_asset_expect(&item),
Self::ItemQuantity(item, lower, upper) => { Self::ItemQuantity(item, lower, upper) => {
let range = *lower..=*upper; let range = *lower..=*upper;
let quantity = thread_rng().gen_range(range); let quantity = thread_rng().gen_range(range);
let mut item = Item::new_from_asset_expect(&item); let mut item = Item::new_from_asset_expect(&item);
item.set_amount(quantity); let _ = item.set_amount(quantity);
item item
}, },
Self::LootTable(table) => Lottery::<LootSpec>::load_expect(&table) Self::LootTable(table) => Lottery::<LootSpec>::load_expect(&table)
.read() .read()
.choose() .choose()
.to_item(body), .to_item(),
Self::CreatureMaterial => body.map_or(
Item::new_from_asset_expect("common.items.food.cheese"),
|b| b.get_material(),
),
} }
} }
} }
@ -164,9 +157,6 @@ mod tests {
let loot_table = Lottery::<LootSpec>::load_expect_cloned(&loot_table); let loot_table = Lottery::<LootSpec>::load_expect_cloned(&loot_table);
validate_table_contents(loot_table); validate_table_contents(loot_table);
}, },
LootSpec::CreatureMaterial => {
item.to_item(None);
},
} }
} }
} }

View File

@ -105,7 +105,7 @@ make_case_elim!(
VialEmpty = 0x4E, VialEmpty = 0x4E,
PotionMinor = 0x4F, PotionMinor = 0x4F,
GrassBlue = 0x50, GrassBlue = 0x50,
ChestBurried = 0x51, ChestBuried = 0x51,
Mud = 0x52, Mud = 0x52,
FireBowlGround = 0x53, FireBowlGround = 0x53,
CaveMushroom = 0x54, CaveMushroom = 0x54,
@ -182,7 +182,7 @@ impl SpriteKind {
SpriteKind::WardrobeDouble => 3.0, SpriteKind::WardrobeDouble => 3.0,
SpriteKind::Pot => 0.90, SpriteKind::Pot => 0.90,
SpriteKind::Mud => 0.36, SpriteKind::Mud => 0.36,
SpriteKind::ChestBurried => 0.91, SpriteKind::ChestBuried => 0.91,
SpriteKind::StonyCoral => 1.4, SpriteKind::StonyCoral => 1.4,
// TODO: Find suitable heights. // TODO: Find suitable heights.
SpriteKind::BarrelCactus SpriteKind::BarrelCactus
@ -233,7 +233,7 @@ impl SpriteKind {
SpriteKind::VialEmpty => true, SpriteKind::VialEmpty => true,
SpriteKind::PotionMinor => true, SpriteKind::PotionMinor => true,
SpriteKind::Bowl => true, SpriteKind::Bowl => true,
SpriteKind::ChestBurried => true, SpriteKind::ChestBuried => true,
SpriteKind::Mud => true, SpriteKind::Mud => true,
SpriteKind::Seashells => true, SpriteKind::Seashells => true,
_ => false, _ => false,
@ -244,7 +244,7 @@ impl SpriteKind {
pub fn is_container(&self) -> bool { pub fn is_container(&self) -> bool {
matches!( matches!(
self, self,
SpriteKind::Chest | SpriteKind::ChestBurried | SpriteKind::Mud | SpriteKind::Crate, SpriteKind::Chest | SpriteKind::ChestBuried | SpriteKind::Mud | SpriteKind::Crate,
) )
} }

View File

@ -1,6 +1,9 @@
use crate::{ use crate::{
client::Client, client::Client,
comp::{biped_large, quadruped_low, quadruped_small, skills::SkillGroupKind, PhysicsState}, comp::{
biped_large, quadruped_low, quadruped_medium, quadruped_small, skills::SkillGroupKind,
theropod, PhysicsState,
},
rtsim::RtSim, rtsim::RtSim,
Server, SpawnPoint, StateExt, Server, SpawnPoint, StateExt,
}; };
@ -28,7 +31,6 @@ use common::{
use common_net::{msg::ServerGeneral, sync::WorldSyncExt}; use common_net::{msg::ServerGeneral, sync::WorldSyncExt};
use common_sys::state::BlockChange; use common_sys::state::BlockChange;
use hashbrown::HashSet; use hashbrown::HashSet;
use rand::prelude::*;
use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt}; use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt};
use tracing::error; use tracing::error;
use vek::{Vec2, Vec3}; use vek::{Vec2, Vec3};
@ -338,77 +340,56 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
// Decide for a loot drop before turning into a lootbag // Decide for a loot drop before turning into a lootbag
let old_body = state.ecs().write_storage::<Body>().remove(entity); let old_body = state.ecs().write_storage::<Body>().remove(entity);
let mut rng = rand::thread_rng(); let lottery = || {
let mut lottery = || {
Lottery::<LootSpec>::load_expect(match old_body { Lottery::<LootSpec>::load_expect(match old_body {
Some(common::comp::Body::Humanoid(_)) => match rng.gen_range(0..5) { Some(common::comp::Body::Humanoid(_)) => "common.loot_tables.creature.humanoid",
0 => "common.loot_tables.humanoids",
1 => "common.loot_tables.armor.swift",
2 => "common.loot_tables.armor.cloth",
3 => "common.loot_tables.weapons.starter",
4 => "common.loot_tables.humanoids",
_ => "common.loot_tables.fallback",
},
Some(common::comp::Body::QuadrupedSmall(quadruped_small)) => { Some(common::comp::Body::QuadrupedSmall(quadruped_small)) => {
match quadruped_small.species { match quadruped_small.species {
quadruped_small::Species::Dodarock => { quadruped_small::Species::Dodarock => {
"common.loot_tables.materials.underground" "common.loot_tables.creature.quad_small.dodarock"
},
_ => match rng.gen_range(0..4) {
0 => "common.loot_tables.food.wild_ingredients",
_ => "common.loot_tables.wild_animal",
}, },
_ => "common.loot_tables.creature.quad_small.default",
} }
}, },
Some(common::comp::Body::QuadrupedMedium(_)) => match rng.gen_range(0..4) { Some(Body::QuadrupedMedium(quadruped_medium)) => match quadruped_medium.species {
0 => "common.loot_tables.food.wild_ingredients", quadruped_medium::Species::Frostfang | quadruped_medium::Species::Roshwalr => {
_ => "common.loot_tables.wild_animal", "common.loot_tables.creature.quad_medium.ice"
}, },
Some(common::comp::Body::BirdMedium(_)) => match rng.gen_range(0..3) { _ => "common.loot_tables.creature.quad_medium.default",
0 => "common.loot_tables.food.wild_ingredients",
_ => "common.loot_tables.fallback",
}, },
Some(common::comp::Body::FishMedium(_)) => "common.loot_tables.fish", Some(common::comp::Body::BirdMedium(_)) => {
Some(common::comp::Body::FishSmall(_)) => "common.loot_tables.fish", "common.loot_tables.creature.bird_medium"
},
Some(common::comp::Body::FishMedium(_)) => "common.loot_tables.creature.fish",
Some(common::comp::Body::FishSmall(_)) => "common.loot_tables.creature.fish",
Some(common::comp::Body::BipedLarge(biped_large)) => match biped_large.species { Some(common::comp::Body::BipedLarge(biped_large)) => match biped_large.species {
biped_large::Species::Wendigo => match rng.gen_range(0..7) { biped_large::Species::Wendigo => {
0 => "common.loot_tables.food.prepared", "common.loot_tables.creature.biped_large.wendigo"
1 => "common.loot_tables.wild_animal",
2 => "common.loot_tables.weapons.tier-2",
_ => "common.loot_tables.cave_large",
},
biped_large::Species::Troll => match rng.gen_range(0..8) {
0 => "common.loot_tables.food.prepared",
1 => "common.loot_tables.cave_large",
2 => "common.loot_tables.weapons.tier-2",
_ => "common.loot_tables.wild_animal",
}, },
biped_large::Species::Troll => "common.loot_tables.creature.biped_large.troll",
biped_large::Species::Occultsaurok biped_large::Species::Occultsaurok
| biped_large::Species::Mightysaurok | biped_large::Species::Mightysaurok
| biped_large::Species::Slysaurok => "common.loot_tables.saurok", | biped_large::Species::Slysaurok => {
_ => match rng.gen_range(0..3) { "common.loot_tables.creature.biped_large.saurok"
0 => "common.loot_tables.food.prepared",
_ => "common.loot_tables.cave_large",
}, },
_ => "common.loot_tables.creature.biped_large.default",
}, },
Some(common::comp::Body::Golem(_)) => match rng.gen_range(0..5) { Some(common::comp::Body::Golem(_)) => "common.loot_tables.creature.golem",
0 => "common.loot_tables.food.prepared", Some(common::comp::Body::Theropod(theropod)) => match theropod.species {
1 => "common.loot_tables.armor.steel", theropod::Species::Sandraptor
2 => "common.loot_tables.weapons.tier-1", | theropod::Species::Snowraptor
3 => "common.loot_tables.weapons.tier-2", | theropod::Species::Woodraptor => {
4 => "common.loot_tables.weapons.tier-3", "common.loot_tables.creature.theropod.raptor"
_ => "common.loot_tables.fallback",
}, },
Some(common::comp::Body::Theropod(_)) => "common.loot_tables.wild_animal", _ => "common.loot_tables.creature.theropod.default",
Some(common::comp::Body::Dragon(_)) => "common.loot_tables.weapons.tier-5", },
Some(common::comp::Body::Dragon(_)) => "common.loot_tables.creature.dragon",
Some(common::comp::Body::QuadrupedLow(quadruped_low)) => { Some(common::comp::Body::QuadrupedLow(quadruped_low)) => {
match quadruped_low.species { match quadruped_low.species {
quadruped_low::Species::Maneater => "common.loot_tables.maneater", quadruped_low::Species::Maneater => {
_ => match rng.gen_range(0..3) { "common.loot_tables.creature.quad_low.maneater"
0 => "common.loot_tables.food.wild_ingredients",
1 => "common.loot_tables.wild_animal",
_ => "common.loot_tables.fallback",
}, },
_ => "common.loot_tables.creature.quad_low.default",
} }
}, },
_ => "common.loot_tables.fallback", _ => "common.loot_tables.fallback",
@ -418,7 +399,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
let item = { let item = {
let mut item_drops = state.ecs().write_storage::<comp::ItemDrop>(); let mut item_drops = state.ecs().write_storage::<comp::ItemDrop>();
item_drops.remove(entity).map_or_else( item_drops.remove(entity).map_or_else(
|| lottery().read().choose().to_item(old_body), || lottery().read().choose().to_item(),
|item_drop| item_drop.0, |item_drop| item_drop.0,
) )
}; };

View File

@ -282,7 +282,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) {
) )
}), }),
// Underwater chests // Underwater chests
(ChestBurried, true, |_, col| { (ChestBuried, true, |_, col| {
( (
MUSH_FACT MUSH_FACT
* 1.0e-6 * 1.0e-6

View File

@ -553,54 +553,25 @@ impl Floor {
// Bad // Bad
let chosen = match room.difficulty { let chosen = match room.difficulty {
0 => Lottery::<LootSpec>::load_expect( 0 => Lottery::<LootSpec>::load_expect(
match dynamic_rng.gen_range(0..4) { "common.loot_tables.dungeon.tier-0.enemy",
0 => "common.loot_tables.humanoids",
1 => "common.loot_tables.armor.cloth",
_ => "common.loot_tables.weapons.tier-0",
},
), ),
1 => Lottery::<LootSpec>::load_expect( 1 => Lottery::<LootSpec>::load_expect(
match dynamic_rng.gen_range(0..4) { "common.loot_tables.dungeon.tier-1.enemy",
0 => "common.loot_tables.humanoids",
1 => "common.loot_tables.armor.swift",
_ => "common.loot_tables.weapons.tier-1",
},
), ),
2 => Lottery::<LootSpec>::load_expect( 2 => Lottery::<LootSpec>::load_expect(
match dynamic_rng.gen_range(0..4) { "common.loot_tables.dungeon.tier-2.enemy",
0 => "common.loot_tables.humanoids",
1 => "common.loot_tables.armor.plate",
_ => "common.loot_tables.weapons.tier-2",
},
), ),
3 => Lottery::<LootSpec>::load_expect( 3 => Lottery::<LootSpec>::load_expect(
match dynamic_rng.gen_range(0..10) { "common.loot_tables.dungeon.tier-3.enemy",
0 => "common.loot_tables.humanoids",
1 => "common.loot_tables.armor.steel",
2 => "common.loot_tables.weapons.tier-3",
_ => "common.loot_tables.cultists",
},
), ),
4 => Lottery::<LootSpec>::load_expect( 4 => Lottery::<LootSpec>::load_expect(
match dynamic_rng.gen_range(0..6) { "common.loot_tables.dungeon.tier-4.enemy",
0 => "common.loot_tables.humanoids",
1 => "common.loot_tables.fallback",
2 => "common.loot_tables.weapons.tier-4",
_ => "common.loot_tables.cultists",
},
), ),
5 => Lottery::<LootSpec>::load_expect( 5 => Lottery::<LootSpec>::load_expect(
match dynamic_rng.gen_range(0..5) { "common.loot_tables.dungeon.tier-5.enemy",
0 => "common.loot_tables.humanoids",
1 => "common.loot_tables.fallback",
2 => "common.loot_tables.weapons.tier-5",
_ => "common.loot_tables.cultists",
},
), ),
_ => Lottery::<LootSpec>::load_expect("common.loot_tables.fallback"), _ => Lottery::<LootSpec>::load_expect("common.loot_tables.fallback"),
}; };
let chosen = chosen.read();
let chosen = chosen.choose();
//let is_giant = //let is_giant =
// RandomField::new(room.seed.wrapping_add(1)).chance(Vec3::from(tile_pos), // RandomField::new(room.seed.wrapping_add(1)).chance(Vec3::from(tile_pos),
// 0.2) && !room.boss; // 0.2) && !room.boss;
@ -615,23 +586,22 @@ impl Floor {
.with_alignment(comp::Alignment::Enemy) .with_alignment(comp::Alignment::Enemy)
.with_loadout_config(loadout_builder::LoadoutConfig::CultistAcolyte) .with_loadout_config(loadout_builder::LoadoutConfig::CultistAcolyte)
.with_skillset_config(common::skillset_builder::SkillSetConfig::CultistAcolyte) .with_skillset_config(common::skillset_builder::SkillSetConfig::CultistAcolyte)
.with_loot_drop(chosen.to_item(None)) .with_loot_drop(chosen.read().choose().to_item())
.with_level(dynamic_rng.gen_range((room.difficulty as f32).powf(1.25) + 3.0..(room.difficulty as f32).powf(1.5) + 4.0).round() as u16); .with_level(dynamic_rng.gen_range((room.difficulty as f32).powf(1.25) + 3.0..(room.difficulty as f32).powf(1.5) + 4.0).round() as u16);
let entity = match room.difficulty { let entity = match room.difficulty {
0 => { 0 => entity
let body = .with_body(comp::Body::BipedSmall(
comp::Body::BipedSmall(comp::biped_small::Body::random_with( comp::biped_small::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::biped_small::Species::Gnarling, &comp::biped_small::Species::Gnarling,
)); ),
entity ))
.with_body(body)
.with_name("Gnarling") .with_name("Gnarling")
.with_loadout_config(loadout_builder::LoadoutConfig::Gnarling) .with_loadout_config(loadout_builder::LoadoutConfig::Gnarling)
.with_skillset_config( .with_skillset_config(
common::skillset_builder::SkillSetConfig::Gnarling, common::skillset_builder::SkillSetConfig::Gnarling,
) )
.with_loot_drop(chosen.to_item(Some(body))) .with_loot_drop(chosen.read().choose().to_item())
.with_main_tool(comp::Item::new_from_asset_expect( .with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0..5) { match dynamic_rng.gen_range(0..5) {
0 => { 0 => {
@ -647,58 +617,49 @@ impl Floor {
wooden_spear" wooden_spear"
}, },
}, },
)) )),
}, 1 => entity
1 => { .with_body(comp::Body::BipedSmall(
let body = comp::biped_small::Body::random_with(
comp::Body::BipedSmall(comp::biped_small::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::biped_small::Species::Adlet, &comp::biped_small::Species::Adlet,
)); ),
entity ))
.with_body(body)
.with_name("Adlet") .with_name("Adlet")
.with_loadout_config(loadout_builder::LoadoutConfig::Adlet) .with_loadout_config(loadout_builder::LoadoutConfig::Adlet)
.with_skillset_config( .with_skillset_config(
common::skillset_builder::SkillSetConfig::Adlet, common::skillset_builder::SkillSetConfig::Adlet,
) )
.with_loot_drop(chosen.to_item(Some(body))) .with_loot_drop(chosen.read().choose().to_item())
.with_main_tool(comp::Item::new_from_asset_expect( .with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0..5) { match dynamic_rng.gen_range(0..5) {
0 => { 0 => "common.items.npc_weapons.biped_small.adlet.adlet_bow",
"common.items.npc_weapons.biped_small.adlet.\
adlet_bow"
},
1 => { 1 => {
"common.items.npc_weapons.biped_small.adlet.\ "common.items.npc_weapons.biped_small.adlet.gnoll_staff"
gnoll_staff"
}, },
_ => { _ => {
"common.items.npc_weapons.biped_small.adlet.\ "common.items.npc_weapons.biped_small.adlet.\
wooden_spear" wooden_spear"
}, },
}, },
)) )),
}, 2 => entity
2 => { .with_body(comp::Body::BipedSmall(
let body = comp::biped_small::Body::random_with(
comp::Body::BipedSmall(comp::biped_small::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::biped_small::Species::Sahagin, &comp::biped_small::Species::Sahagin,
)); ),
entity ))
.with_body(body)
.with_name("Sahagin") .with_name("Sahagin")
.with_loadout_config(loadout_builder::LoadoutConfig::Sahagin) .with_loadout_config(loadout_builder::LoadoutConfig::Sahagin)
.with_skillset_config( .with_skillset_config(
common::skillset_builder::SkillSetConfig::Sahagin, common::skillset_builder::SkillSetConfig::Sahagin,
) )
.with_loot_drop(chosen.to_item(Some(body))) .with_loot_drop(chosen.read().choose().to_item())
.with_main_tool(comp::Item::new_from_asset_expect( .with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0..5) { match dynamic_rng.gen_range(0..5) {
0 => { 0 => {
"common.items.npc_weapons.biped_small.sahagin.\ "common.items.npc_weapons.biped_small.sahagin.adlet_bow"
adlet_bow"
}, },
1 => { 1 => {
"common.items.npc_weapons.biped_small.sahagin.\ "common.items.npc_weapons.biped_small.sahagin.\
@ -709,27 +670,24 @@ impl Floor {
wooden_spear" wooden_spear"
}, },
}, },
)) )),
}, 3 => entity
3 => { .with_body(comp::Body::BipedSmall(
let body = comp::biped_small::Body::random_with(
comp::Body::BipedSmall(comp::biped_small::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::biped_small::Species::Haniwa, &comp::biped_small::Species::Haniwa,
)); ),
entity ))
.with_body(body)
.with_name("Haniwa") .with_name("Haniwa")
.with_loadout_config(loadout_builder::LoadoutConfig::Haniwa) .with_loadout_config(loadout_builder::LoadoutConfig::Haniwa)
.with_skillset_config( .with_skillset_config(
common::skillset_builder::SkillSetConfig::Haniwa, common::skillset_builder::SkillSetConfig::Haniwa,
) )
.with_loot_drop(chosen.to_item(Some(body))) .with_loot_drop(chosen.read().choose().to_item())
.with_main_tool(comp::Item::new_from_asset_expect( .with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0..5) { match dynamic_rng.gen_range(0..5) {
0 => { 0 => {
"common.items.npc_weapons.biped_small.haniwa.\ "common.items.npc_weapons.biped_small.haniwa.adlet_bow"
adlet_bow"
}, },
1 => { 1 => {
"common.items.npc_weapons.biped_small.haniwa.\ "common.items.npc_weapons.biped_small.haniwa.\
@ -740,22 +698,20 @@ impl Floor {
wooden_spear" wooden_spear"
}, },
}, },
)) )),
}, 4 => entity
4 => { .with_body(comp::Body::BipedSmall(
let body = comp::biped_small::Body::random_with(
comp::Body::BipedSmall(comp::biped_small::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::biped_small::Species::Myrmidon, &comp::biped_small::Species::Myrmidon,
)); ),
entity ))
.with_body(body)
.with_name("Myrmidon") .with_name("Myrmidon")
.with_loadout_config(loadout_builder::LoadoutConfig::Myrmidon) .with_loadout_config(loadout_builder::LoadoutConfig::Myrmidon)
.with_skillset_config( .with_skillset_config(
common::skillset_builder::SkillSetConfig::Myrmidon, common::skillset_builder::SkillSetConfig::Myrmidon,
) )
.with_loot_drop(chosen.to_item(Some(body))) .with_loot_drop(chosen.read().choose().to_item())
.with_main_tool(comp::Item::new_from_asset_expect( .with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0..5) { match dynamic_rng.gen_range(0..5) {
0 => { 0 => {
@ -771,25 +727,19 @@ impl Floor {
wooden_spear" wooden_spear"
}, },
}, },
)) )),
},
5 => match dynamic_rng.gen_range(0..6) { 5 => match dynamic_rng.gen_range(0..6) {
0 => { 0 => entity
let body = comp::Body::Humanoid(comp::humanoid::Body::random()); .with_body(comp::Body::Humanoid(comp::humanoid::Body::random()))
entity
.with_body(body)
.with_name("Cultist Warlock") .with_name("Cultist Warlock")
.with_loadout_config( .with_loadout_config(loadout_builder::LoadoutConfig::Warlock)
loadout_builder::LoadoutConfig::Warlock,
)
.with_skillset_config( .with_skillset_config(
common::skillset_builder::SkillSetConfig::Warlock, common::skillset_builder::SkillSetConfig::Warlock,
) )
.with_loot_drop(chosen.to_item(Some(body))) .with_loot_drop(chosen.read().choose().to_item())
.with_main_tool(comp::Item::new_from_asset_expect( .with_main_tool(comp::Item::new_from_asset_expect(
"common.items.weapons.staff.cultist_staff", "common.items.weapons.staff.cultist_staff",
)) )),
},
1 => entity 1 => entity
.with_body(comp::Body::Object(comp::object::Body::Crossbow)) .with_body(comp::Body::Object(comp::object::Body::Crossbow))
.with_name("Possessed Turret".to_string()) .with_name("Possessed Turret".to_string())
@ -802,7 +752,7 @@ impl Floor {
.with_skillset_config( .with_skillset_config(
common::skillset_builder::SkillSetConfig::Warlord, common::skillset_builder::SkillSetConfig::Warlord,
) )
.with_loot_drop(chosen.to_item(None)) .with_loot_drop(chosen.read().choose().to_item())
.with_main_tool(comp::Item::new_from_asset_expect( .with_main_tool(comp::Item::new_from_asset_expect(
match dynamic_rng.gen_range(0..5) { match dynamic_rng.gen_range(0..5) {
0 => "common.items.weapons.axe.malachite_axe-0", 0 => "common.items.weapons.axe.malachite_axe-0",
@ -853,10 +803,7 @@ impl Floor {
"common.loot_tables.weapons.tier-4", "common.loot_tables.weapons.tier-4",
), ),
5 => Lottery::<LootSpec>::load_expect( 5 => Lottery::<LootSpec>::load_expect(
match dynamic_rng.gen_range(0..3) { "common.loot_tables.dungeon.tier-5.boss",
0 => "common.loot_tables.mindflayer",
_ => "common.loot_tables.miniboss",
},
), ),
_ => { _ => {
Lottery::<LootSpec>::load_expect("common.loot_tables.fallback") Lottery::<LootSpec>::load_expect("common.loot_tables.fallback")
@ -866,85 +813,81 @@ impl Floor {
let chosen = chosen.choose(); let chosen = chosen.choose();
let entity = match room.difficulty { let entity = match room.difficulty {
0 => { 0 => {
let body = comp::Body::BipedLarge( vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::BipedLarge(
comp::biped_large::Body::random_with( comp::biped_large::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::biped_large::Species::Harvester, &comp::biped_large::Species::Harvester,
), ),
); ))
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body)
.with_name("Harvester".to_string()) .with_name("Harvester".to_string())
.with_loot_drop(chosen.to_item(Some(body))), .with_loot_drop(chosen.to_item()),
] ]
}, },
1 => { 1 => {
let body = comp::Body::BipedLarge( vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::BipedLarge(
comp::biped_large::Body::random_with( comp::biped_large::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::biped_large::Species::Yeti, &comp::biped_large::Species::Yeti,
), ),
); ))
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body)
.with_name("Yeti".to_string()) .with_name("Yeti".to_string())
.with_loot_drop(chosen.to_item(Some(body))), .with_loot_drop(chosen.to_item()),
] ]
}, },
2 => { 2 => {
let body = comp::Body::BipedLarge( vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::BipedLarge(
comp::biped_large::Body::random_with( comp::biped_large::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::biped_large::Species::Tidalwarrior, &comp::biped_large::Species::Tidalwarrior,
), ),
); ))
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body)
.with_name("Tidal Warrior".to_string()) .with_name("Tidal Warrior".to_string())
.with_loot_drop(chosen.to_item(Some(body))), .with_loot_drop(chosen.to_item()),
] ]
}, },
3 => { 3 => {
let body = comp::Body::Golem(comp::golem::Body::random_with(
dynamic_rng,
&comp::golem::Species::ClayGolem,
));
vec![ vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32)) EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body) .with_body(comp::Body::Golem(
comp::golem::Body::random_with(
dynamic_rng,
&comp::golem::Species::ClayGolem,
),
))
.with_name("Clay Golem".to_string()) .with_name("Clay Golem".to_string())
.with_loot_drop(chosen.to_item(Some(body))), .with_loot_drop(chosen.to_item()),
] ]
}, },
4 => { 4 => {
let body = comp::Body::BipedLarge( vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::BipedLarge(
comp::biped_large::Body::random_with( comp::biped_large::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::biped_large::Species::Minotaur, &comp::biped_large::Species::Minotaur,
), ),
); ))
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body)
.with_name("Minotaur".to_string()) .with_name("Minotaur".to_string())
.with_loot_drop(chosen.to_item(Some(body))), .with_loot_drop(chosen.to_item()),
] ]
}, },
5 => { 5 => {
let body = comp::Body::BipedLarge( vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::BipedLarge(
comp::biped_large::Body::random_with( comp::biped_large::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::biped_large::Species::Mindflayer, &comp::biped_large::Species::Mindflayer,
), ),
); ))
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body)
.with_name("Mindflayer".to_string()) .with_name("Mindflayer".to_string())
.with_loot_drop(chosen.to_item(Some(body))) .with_loot_drop(chosen.to_item())
.with_skillset_config( .with_skillset_config(
common::skillset_builder::SkillSetConfig::Mindflayer, common::skillset_builder::SkillSetConfig::Mindflayer,
), ),
@ -997,13 +940,13 @@ impl Floor {
if tile_pos == miniboss_spawn_tile && tile_wcenter.xy() == wpos2d { if tile_pos == miniboss_spawn_tile && tile_wcenter.xy() == wpos2d {
let chosen = match room.difficulty { let chosen = match room.difficulty {
0 => Lottery::<LootSpec>::load_expect( 0 => Lottery::<LootSpec>::load_expect(
"common.loot_tables.wild_animal", "common.loot_tables.weapons.tier-0",
), ),
1 => Lottery::<LootSpec>::load_expect( 1 => Lottery::<LootSpec>::load_expect(
"common.loot_tables.wild_animal", "common.loot_tables.weapons.tier-1",
), ),
2 => Lottery::<LootSpec>::load_expect( 2 => Lottery::<LootSpec>::load_expect(
"common.loot_tables.wild_animal", "common.loot_tables.weapons.tier-2",
), ),
3 => Lottery::<LootSpec>::load_expect( 3 => Lottery::<LootSpec>::load_expect(
"common.loot_tables.weapons.tier-3", "common.loot_tables.weapons.tier-3",
@ -1011,71 +954,63 @@ impl Floor {
4 => Lottery::<LootSpec>::load_expect( 4 => Lottery::<LootSpec>::load_expect(
"common.loot_tables.weapons.tier-4", "common.loot_tables.weapons.tier-4",
), ),
5 => Lottery::<LootSpec>::load_expect("common.loot_tables.cultist"), 5 => {
Lottery::<LootSpec>::load_expect("common.loot_tables.cultists")
},
_ => { _ => {
Lottery::<LootSpec>::load_expect("common.loot_tables.fallback") Lottery::<LootSpec>::load_expect("common.loot_tables.fallback")
}, },
}; };
let entity = match room.difficulty { let entity = match room.difficulty {
0 => { 0 => {
let body = comp::Body::QuadrupedMedium( vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::QuadrupedMedium(
comp::quadruped_medium::Body::random_with( comp::quadruped_medium::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::quadruped_medium::Species::Bonerattler, &comp::quadruped_medium::Species::Bonerattler,
), ),
); ))
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body)
.with_name("Bonerattler".to_string()) .with_name("Bonerattler".to_string())
.with_loot_drop( .with_loot_drop(chosen.read().choose().to_item()),
chosen.read().choose().to_item(Some(body)),
),
] ]
}, },
1 => { 1 => {
let body = comp::Body::QuadrupedMedium( vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::QuadrupedMedium(
comp::quadruped_medium::Body::random_with( comp::quadruped_medium::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::quadruped_medium::Species::Bonerattler, &comp::quadruped_medium::Species::Bonerattler,
), ),
); ))
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body)
.with_name("Bonerattler".to_string()) .with_name("Bonerattler".to_string())
.with_loot_drop( .with_loot_drop(chosen.read().choose().to_item());
chosen.read().choose().to_item(Some(body))
);
3 3
] ]
}, },
2 => { 2 => {
let mut entities = Vec::new(); let mut entities = Vec::new();
let body = comp::Body::QuadrupedLow( entities.resize_with(6, || {
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::QuadrupedLow(
comp::quadruped_low::Body::random_with( comp::quadruped_low::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::quadruped_low::Species::Hakulaq, &comp::quadruped_low::Species::Hakulaq,
), ),
); ))
entities.resize_with(6, || {
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body)
.with_name("Hakulaq".to_string()) .with_name("Hakulaq".to_string())
.with_loot_drop( .with_loot_drop(chosen.read().choose().to_item())
chosen.read().choose().to_item(Some(body)),
)
}); });
entities entities
}, },
3 => { 3 => {
let mut entities = Vec::new(); let mut entities = Vec::new();
let body = comp::Body::Humanoid(comp::humanoid::Body::random());
entities.push( entities.push(
EntityInfo::at(tile_wcenter.map(|e| e as f32)) EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body) .with_body(comp::Body::Humanoid(comp::humanoid::Body::random()))
.with_name("Animal Trainer".to_string()) .with_name("Animal Trainer".to_string())
.with_loot_drop(chosen.read().choose().to_item(Some(body))) .with_loot_drop(chosen.read().choose().to_item())
.with_loadout_config(loadout_builder::LoadoutConfig::CultistAcolyte) .with_loadout_config(loadout_builder::LoadoutConfig::CultistAcolyte)
.with_skillset_config( .with_skillset_config(
common::skillset_builder::SkillSetConfig::CultistAcolyte common::skillset_builder::SkillSetConfig::CultistAcolyte
@ -1092,53 +1027,44 @@ impl Floor {
}, },
)), )),
); );
let body = comp::Body::QuadrupedMedium( entities.resize_with(entities.len() + 2, || {
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::QuadrupedMedium(
comp::quadruped_medium::Body::random_with( comp::quadruped_medium::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::quadruped_medium::Species::Darkhound, &comp::quadruped_medium::Species::Darkhound,
), ),
); ))
entities.resize_with(entities.len() + 2, || {
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body)
.with_name("Tamed Darkhound".to_string()) .with_name("Tamed Darkhound".to_string())
.with_loot_drop( .with_loot_drop(chosen.read().choose().to_item())
chosen.read().choose().to_item(Some(body)),
)
}); });
entities entities
}, },
4 => { 4 => {
let body = comp::Body::BipedLarge( vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::BipedLarge(
comp::biped_large::Body::random_with( comp::biped_large::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::biped_large::Species::Dullahan, &comp::biped_large::Species::Dullahan,
), ),
); ))
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body)
.with_name("Dullahan Guard".to_string()) .with_name("Dullahan Guard".to_string())
.with_loot_drop( .with_loot_drop(chosen.read().choose().to_item()),
chosen.read().choose().to_item(Some(body)),
),
] ]
}, },
5 => { 5 => {
let body = comp::Body::BipedSmall( let mut entities = Vec::new();
entities.resize_with(10, || {
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::BipedSmall(
comp::biped_small::Body::random_with( comp::biped_small::Body::random_with(
dynamic_rng, dynamic_rng,
&comp::biped_small::Species::Husk, &comp::biped_small::Species::Husk,
), ),
); ))
let mut entities = Vec::new();
entities.resize_with(10, || {
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(body)
.with_name("Cultist Husk".to_string()) .with_name("Cultist Husk".to_string())
.with_loot_drop( .with_loot_drop(chosen.read().choose().to_item())
chosen.read().choose().to_item(Some(body)),
)
.with_loadout_config( .with_loadout_config(
loadout_builder::LoadoutConfig::Husk, loadout_builder::LoadoutConfig::Husk,
) )