Move loot tables to entityconfigs

* Moved all entities in dungeons to assets
This commit is contained in:
juliancoffee 2021-06-09 01:07:48 +03:00
parent a4cc1e24ee
commit 057aa7fecf
42 changed files with 373 additions and 256 deletions

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Crazy Sheep"),
body: Some(RandomWith("sheep")),
loot: Some(LootTable("common.loot_tables.fallback")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -0,0 +1,20 @@
EntityConfig (
name: Some("Yan Hus"),
body: Some(RandomWith("humanoid")),
loot: Some(LootTable("common.loot_tables.fallback")),
main_tool: Some(Choice([
(1.0, Some(Item("common.items.weapons.tool.broom"))),
(1.0, Some(Item("common.items.weapons.tool.hoe"))),
(1.0, Some(Item("common.items.weapons.tool.pickaxe"))),
(1.0, Some(Item("common.items.weapons.tool.rake"))),
(1.0, Some(Item("common.items.weapons.tool.shovel-0"))),
(1.0, Some(Item("common.items.weapons.tool.shovel-1"))),
(1.0, Some(Item("common.items.weapons.bow.bone-1"))),
])),
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Big Goose"),
body: Some(RandomWith("goose")),
loot: Some(LootTable("common.loot_tables.fallback")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Harvester"),
body: Some(RandomWith("harvester")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-0.boss")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Gnarling Stalker"),
body: Some(RandomWith("gnarling")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-0.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.gnarling.adlet_bow")),
second_tool: None,

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Deadwood"),
body: Some(RandomWith("deadwood")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-0.miniboss")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Gnarling Mugger"),
body: Some(RandomWith("gnarling")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-0.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.gnarling.wooden_spear")),
second_tool: None,

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Gnarling Shaman"),
body: Some(RandomWith("gnarling")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-0.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.gnarling.gnoll_staff")),
second_tool: None,

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Yeti"),
body: Some(RandomWith("yeti")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-1.boss")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Adlet Tracker"),
body: Some(RandomWith("adlet")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-1.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.adlet.adlet_bow")),
second_tool: None,

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Rat"),
body: Some(RandomWith("rat")),
loot: Some(LootTable("common.loot_tables.creature.quad_small.generic")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Adlet Hunter"),
body: Some(RandomWith("adlet")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-1.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.adlet.wooden_spear")),
second_tool: None,

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Adlet Shaman"),
body: Some(RandomWith("adlet")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-1.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.adlet.gnoll_staff")),
second_tool: None,

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Tidal Warrior"),
body: Some(RandomWith("tidalwarrior")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-2.boss")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Sahagin Sniper"),
body: Some(RandomWith("sahagin")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-2.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.sahagin.adlet_bow")),
second_tool: None,

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Hakulaq"),
body: Some(RandomWith("hakulaq")),
loot: Some(LootTable("common.loot_tables.creature.quad_low.fanged")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Sahagin Spearman"),
body: Some(RandomWith("sahagin")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-2.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.sahagin.wooden_spear")),
second_tool: None,

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Sahagin Sorcerer"),
body: Some(RandomWith("sahagin")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-2.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.sahagin.gnoll_staff")),
second_tool: None,

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Bonerattler"),
body: Some(RandomWith("bonerattler")),
loot: Some(LootTable("common.loot_tables.creature.quad_medium.carapace")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Clay Golem"),
body: Some(RandomWith("claygolem")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-3.boss")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Haniwa Archer"),
body: Some(RandomWith("haniwa")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-3.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.haniwa.adlet_bow")),
second_tool: None,

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Haniwa Sentry"),
body: None,
loot: Some(Item("common.items.crafting_ing.stones")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Haniwa Guard"),
body: Some(RandomWith("haniwa")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-3.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.haniwa.wooden_spear")),
second_tool: None,

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Haniwa Sorcerer"),
body: Some(RandomWith("haniwa")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-3.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.haniwa.gnoll_staff")),
second_tool: None,

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Minotaur"),
body: Some(RandomWith("minotaur")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-4.boss")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Myrmidon Marksman"),
body: Some(RandomWith("myrmidon")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-4.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.myrmidon.adlet_bow")),
second_tool: None,

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Dullahan"),
body: Some(RandomWith("dullahan")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-4.miniboss")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Myrmidon Hoplite"),
body: Some(RandomWith("myrmidon")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-4.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.myrmidon.wooden_spear")),
second_tool: None,

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Myrmidon Wizard"),
body: Some(RandomWith("myrmidon")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-4.enemy")),
main_tool: Some(Item("common.items.npc_weapons.biped_small.myrmidon.gnoll_staff")),
second_tool: None,

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Beastmaster"),
body: Some(RandomWith("humanoid")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-5.miniboss")),
main_tool: Some(Choice([
(1.0, Some(Item("common.items.weapons.axe.malachite_axe-0"))),
(1.0, Some(Item("common.items.weapons.sword.bloodsteel-1"))),
@ -10,6 +12,6 @@ EntityConfig (
second_tool: None,
loadout_asset: Some("common.loadout.dungeon.tier-5.beastmaster"),
// TODO: make skillset for him, I'm just too lazy
// TODO: make own skillset for him?
skillset_asset: Some("common.skillset.dungeon.tier-5.enemy"),
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Mindflayer"),
body: Some(RandomWith("mindflayer")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-5.boss")),
main_tool: None,
second_tool: None,

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Tamed Darkhound"),
body: Some(RandomWith("darkhound")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-5.minion")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Cultist Husk"),
body: Some(RandomWith("husk")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-5.minion")),
main_tool: None,
second_tool: None,

View File

@ -0,0 +1,12 @@
EntityConfig (
name: Some("Possessed Turret"),
body: None,
loot: Some(Item("common.items.crafting_ing.twigs")),
main_tool: None,
second_tool: None,
loadout_asset: None,
skillset_asset: None,
)

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Cultist Warlock"),
body: Some(RandomWith("humanoid")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-5.enemy")),
main_tool: Some(Item("common.items.weapons.staff.cultist_staff")),
second_tool: None,

View File

@ -2,6 +2,8 @@ EntityConfig (
name: Some("Cultist Warlord"),
body: Some(RandomWith("humanoid")),
loot: Some(LootTable("common.loot_tables.dungeon.tier-5.enemy")),
main_tool: Some(Choice([
(1.0, Some(Item("common.items.weapons.axe_1h.orichalcum-0"))),
(2.0, Some(Item("common.items.weapons.sword.cultist"))),

View File

@ -4,8 +4,7 @@ EntityConfig (
/// Body
/// Can be Exact (Body with all fields e.g BodyType, Species, Hair color and such)
/// or Random (will use random if available for this Body)
/// or RandomWith (will use random_with if available for this Body)
/// or RandomWith (will generate random body or species)
body: Some(RandomWith("humanoid")),
/// Main and second tools
@ -24,7 +23,7 @@ EntityConfig (
/// Loot
/// Can be Item (with asset_specifier for item)
/// or LootTable (with asset_specifier for loot table)
// loot: LootTable("common.loot_tables.humanoids"),
loot: Some(LootTable("common.loot_tables.humanoids")),
/// Meta Info (level, alignment, agency, etc)
// meta: {},

View File

@ -3,6 +3,8 @@ EntityConfig (
// body is specified outsite
body: None,
loot: None,
main_tool: Some(Item("common.items.weapons.sword.iron-4")),
second_tool: None,

View File

@ -3,6 +3,9 @@ EntityConfig (
// body is specified outsite
body: None,
// considering giving some gold/gems/materials?
loot: None,
main_tool: Some(Item("common.items.weapons.bow.eldwood-0")),
second_tool: None,

View File

@ -3,6 +3,8 @@ EntityConfig (
// body is specified outsite
body: None,
loot: None,
main_tool: Some(Choice([
(1.0, Some(Item("common.items.weapons.tool.broom"))),
(1.0, Some(Item("common.items.weapons.tool.hoe"))),

View File

@ -5,6 +5,7 @@ use crate::{
inventory::loadout_builder::{ItemSpec, LoadoutBuilder},
Alignment, Body, Item,
},
lottery::{LootSpec, Lottery},
npc::{self, NPC_NAMES},
trade,
trade::SiteInformation,
@ -17,10 +18,17 @@ enum BodyKind {
RandomWith(String),
}
#[derive(Debug, Deserialize, Clone)]
enum LootKind {
Item(String),
LootTable(String),
}
#[derive(Debug, Deserialize, Clone)]
struct EntityConfig {
name: Option<String>,
body: Option<BodyKind>,
loot: Option<LootKind>,
main_tool: Option<ItemSpec>,
second_tool: Option<ItemSpec>,
loadout_asset: Option<String>,
@ -93,6 +101,7 @@ impl EntityInfo {
let EntityConfig {
name,
body,
loot,
main_tool,
second_tool,
loadout_asset,
@ -116,6 +125,19 @@ impl EntityInfo {
}
}
if let Some(loot) = loot {
match loot {
LootKind::Item(asset) => {
self = self.with_loot_drop(Item::new_from_asset_expect(&asset));
},
LootKind::LootTable(asset) => {
let table = Lottery::<LootSpec>::load_expect(&asset);
let drop = table.read().choose().to_item();
self = self.with_loot_drop(drop);
},
}
}
let rng = &mut rand::thread_rng();
if let Some(main_tool) =
main_tool.and_then(|i| i.try_to_item(asset_specifier.unwrap_or("??"), rng))
@ -318,6 +340,7 @@ mod tests {
skillset_asset,
name: _name,
body,
loot,
} = config;
if let Some(main_tool) = main_tool {
@ -335,7 +358,20 @@ mod tests {
string.parse::<npc::NpcBody>().unwrap_or_else(|err| {
panic!("failed to parse body {:?}. Err: {:?}", &string, err)
});
std::mem::drop(body_creator());
let _ = body_creator();
},
}
}
if let Some(loot) = loot {
match loot {
LootKind::Item(asset) => {
std::mem::drop(Item::new_from_asset_expect(&asset));
},
LootKind::LootTable(asset) => {
// we need to just load it check if it exists,
// because all loot tables are tested in Lottery module
let _ = Lottery::<LootSpec>::load_expect(&asset);
},
}
}

View File

@ -9,11 +9,10 @@ use crate::{
};
use common::{
assets::{AssetExt, AssetHandle},
assets::AssetHandle,
astar::Astar,
comp::{self},
generation::{ChunkSupplement, EntityInfo},
lottery::{LootSpec, Lottery},
store::{Id, Store},
terrain::{Block, BlockKind, SpriteKind, Structure, StructuresGroup, TerrainChunkSize},
vol::{BaseVol, ReadVol, RectSizedVol, RectVolSize, WriteVol},
@ -567,7 +566,7 @@ impl Floor {
3 => enemy_3(dynamic_rng, raw_entity),
4 => enemy_4(dynamic_rng, raw_entity),
5 => enemy_5(dynamic_rng, raw_entity),
_ => enemy_fallback(dynamic_rng, raw_entity),
_ => enemy_fallback(raw_entity),
};
supplement.add_entity(
entity.with_alignment(comp::Alignment::Enemy).with_level(
@ -597,13 +596,13 @@ impl Floor {
if tile_pos == boss_spawn_tile && tile_wcenter.xy() == wpos2d {
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),
0 => boss_0(tile_wcenter),
1 => boss_1(tile_wcenter),
2 => boss_2(tile_wcenter),
3 => boss_3(tile_wcenter),
4 => boss_4(tile_wcenter),
5 => boss_5(tile_wcenter),
_ => boss_fallback(tile_wcenter),
};
for entity in entities {
@ -640,13 +639,13 @@ impl Floor {
if tile_pos == miniboss_spawn_tile && tile_wcenter.xy() == wpos2d {
let entities = match room.difficulty {
0 => mini_boss_0(dynamic_rng, tile_wcenter),
1 => mini_boss_1(dynamic_rng, tile_wcenter),
2 => mini_boss_2(dynamic_rng, tile_wcenter),
3 => mini_boss_3(dynamic_rng, tile_wcenter),
4 => mini_boss_4(dynamic_rng, tile_wcenter),
0 => mini_boss_0(tile_wcenter),
1 => mini_boss_1(tile_wcenter),
2 => mini_boss_2(tile_wcenter),
3 => mini_boss_3(tile_wcenter),
4 => mini_boss_4(tile_wcenter),
5 => mini_boss_5(dynamic_rng, tile_wcenter),
_ => mini_boss_fallback(dynamic_rng, tile_wcenter),
_ => mini_boss_fallback(tile_wcenter),
};
for entity in entities {
@ -923,292 +922,150 @@ impl Floor {
}
fn enemy_0(dynamic_rng: &mut impl Rng, entity: EntityInfo) -> EntityInfo {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-0.enemy");
let gnarling = entity
.with_loot_drop(chosen.read().choose().to_item());
match dynamic_rng.gen_range(0..5) {
0 => gnarling.with_asset_expect("common.entity.dungeon.tier-0.bow"),
1 => gnarling.with_asset_expect("common.entity.dungeon.tier-0.staff"),
_ => gnarling.with_asset_expect("common.entity.dungeon.tier-0.spear"),
0 => entity.with_asset_expect("common.entity.dungeon.tier-0.bow"),
1 => entity.with_asset_expect("common.entity.dungeon.tier-0.staff"),
_ => entity.with_asset_expect("common.entity.dungeon.tier-0.spear"),
}
}
fn enemy_1(dynamic_rng: &mut impl Rng, entity: EntityInfo) -> EntityInfo {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-1.enemy");
let adlet = entity
.with_loot_drop(chosen.read().choose().to_item());
match dynamic_rng.gen_range(0..5) {
0 => adlet.with_asset_expect("common.entity.dungeon.tier-1.bow"),
1 => adlet.with_asset_expect("common.entity.dungeon.tier-1.staff"),
_ => adlet.with_asset_expect("common.entity.dungeon.tier-1.spear"),
0 => entity.with_asset_expect("common.entity.dungeon.tier-1.bow"),
1 => entity.with_asset_expect("common.entity.dungeon.tier-1.staff"),
_ => entity.with_asset_expect("common.entity.dungeon.tier-1.spear"),
}
}
fn enemy_2(dynamic_rng: &mut impl Rng, entity: EntityInfo) -> EntityInfo {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-2.enemy");
let sahagin = entity
.with_loot_drop(chosen.read().choose().to_item());
match dynamic_rng.gen_range(0..5) {
0 => sahagin.with_asset_expect("common.entity.dungeon.tier-2.bow"),
1 => sahagin.with_asset_expect("common.entity.dungeon.tier-2.staff"),
_ => sahagin.with_asset_expect("common.entity.dungeon.tier-2.spear"),
0 => entity.with_asset_expect("common.entity.dungeon.tier-2.bow"),
1 => entity.with_asset_expect("common.entity.dungeon.tier-2.staff"),
_ => entity.with_asset_expect("common.entity.dungeon.tier-2.spear"),
}
}
fn enemy_3(dynamic_rng: &mut impl Rng, entity: EntityInfo) -> EntityInfo {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-3.enemy");
match dynamic_rng.gen_range(0..4) {
match dynamic_rng.gen_range(0..5) {
0 => entity
.with_body(comp::Body::Object(comp::object::Body::HaniwaSentry))
.with_name("Haniwa Sentry".to_string())
.with_loot_drop(comp::Item::new_from_asset_expect(
"common.items.crafting_ing.stones",
)),
_ => {
let haniwa = entity
.with_loot_drop(chosen.read().choose().to_item());
match dynamic_rng.gen_range(0..5) {
0 => haniwa.with_asset_expect("common.entity.dungeon.tier-3.bow"),
1 => haniwa.with_asset_expect("common.entity.dungeon.tier-3.staff"),
_ => haniwa.with_asset_expect("common.entity.dungeon.tier-3.spear"),
}
},
.with_asset_expect("common.entity.dungeon.tier-3.sentry"),
1 => entity.with_asset_expect("common.entity.dungeon.tier-3.bow"),
2 => entity.with_asset_expect("common.entity.dungeon.tier-3.staff"),
_ => entity.with_asset_expect("common.entity.dungeon.tier-3.spear"),
}
}
fn enemy_4(dynamic_rng: &mut impl Rng, entity: EntityInfo) -> EntityInfo {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-4.enemy");
let myrmidon = entity
.with_loot_drop(chosen.read().choose().to_item());
match dynamic_rng.gen_range(0..5) {
0 => myrmidon.with_asset_expect("common.entity.dungeon.tier-4.bow"),
1 => myrmidon.with_asset_expect("common.entity.dungeon.tier-4.staff"),
_ => myrmidon.with_asset_expect("common.entity.dungeon.tier-4.spear"),
0 => entity.with_asset_expect("common.entity.dungeon.tier-4.bow"),
1 => entity.with_asset_expect("common.entity.dungeon.tier-4.staff"),
_ => entity.with_asset_expect("common.entity.dungeon.tier-4.spear"),
}
}
fn enemy_5(dynamic_rng: &mut impl Rng, entity: EntityInfo) -> EntityInfo {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-5.enemy");
match dynamic_rng.gen_range(0..6) {
0 => entity
.with_body(comp::Body::Object(comp::object::Body::Crossbow))
.with_name("Possessed Turret".to_string())
.with_loot_drop(comp::Item::new_from_asset_expect(
"common.items.crafting_ing.twigs",
)),
1 => entity
.with_loot_drop(chosen.read().choose().to_item())
.with_asset_expect("common.entity.dungeon.tier-5.warlock"),
_ => entity
.with_loot_drop(chosen.read().choose().to_item())
.with_asset_expect("common.entity.dungeon.tier-5.warlord"),
.with_asset_expect("common.entity.dungeon.tier-5.turret"),
1 => entity.with_asset_expect("common.entity.dungeon.tier-5.warlock"),
_ => entity.with_asset_expect("common.entity.dungeon.tier-5.warlord"),
}
}
fn enemy_fallback(_dynamic_rng: &mut impl Rng, entity: EntityInfo) -> EntityInfo {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.fallback");
entity
.with_name("Humanoid")
.with_loot_drop(chosen.read().choose().to_item())
.with_main_tool(comp::Item::new_from_asset_expect(
"common.items.weapons.bow.bone-1",
))
fn enemy_fallback(entity: EntityInfo) -> EntityInfo {
entity.with_asset_expect("common.entity.dungeon.fallback.enemy")
}
fn boss_0(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-0.boss");
fn boss_0(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
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()),
.with_asset_expect("common.entity.dungeon.tier-0.boss"),
]
}
fn boss_1(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-1.boss");
fn boss_1(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
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()),
.with_asset_expect("common.entity.dungeon.tier-1.boss"),
]
}
fn boss_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-2.boss");
fn boss_2(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
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()),
.with_asset_expect("common.entity.dungeon.tier-2.boss"),
]
}
fn boss_3(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-3.boss");
fn boss_3(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
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())
.with_asset_expect("common.entity.dungeon.tier-3.boss")
});
entities
}
fn boss_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-4.boss");
fn boss_4(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
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()),
.with_asset_expect("common.entity.dungeon.tier-4.boss"),
]
}
fn boss_5(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-5.boss");
fn boss_5(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
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_loot_drop(chosen.read().choose().to_item())
.with_asset_expect("common.entity.dungeon.tier-5.boss"),
]
}
fn boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
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<i32>) -> Vec<EntityInfo> {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-0.miniboss");
fn boss_fallback(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::QuadrupedLow(
comp::quadruped_low::Body::random_with(
dynamic_rng,
&comp::quadruped_low::Species::Deadwood,
),
))
.with_name("Deadwood".to_string())
.with_loot_drop(chosen.read().choose().to_item()),
.with_asset_expect("common.entity.dungeon.fallback.boss"),
]
}
fn mini_boss_1(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.creature.quad_small.generic");
fn mini_boss_0(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_asset_expect("common.entity.dungeon.tier-0.miniboss"),
]
}
fn mini_boss_1(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let mut entities = Vec::new();
entities.resize_with(8, || {
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::Rat,
),
))
.with_name("Rat".to_string())
.with_loot_drop(chosen.read().choose().to_item())
.with_asset_expect("common.entity.dungeon.tier-1.rat")
});
entities
}
fn mini_boss_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.creature.quad_low.fanged");
fn mini_boss_2(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let mut entities = Vec::new();
entities.resize_with(6, || {
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::QuadrupedLow(
comp::quadruped_low::Body::random_with(
dynamic_rng,
&comp::quadruped_low::Species::Hakulaq,
),
))
.with_name("Hakulaq".to_string())
.with_loot_drop(chosen.read().choose().to_item())
.with_asset_expect("common.entity.dungeon.tier-2.hakulaq")
});
entities
}
fn mini_boss_3(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let chosen =
Lottery::<LootSpec>::load_expect("common.loot_tables.creature.quad_medium.carapace");
fn mini_boss_3(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
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(
dynamic_rng,
&comp::quadruped_medium::Species::Bonerattler,
),
))
.with_name("Bonerattler".to_string())
.with_loot_drop(chosen.read().choose().to_item())
.with_asset_expect("common.entity.dungeon.tier-3.bonerattler")
});
entities
}
fn mini_boss_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let chosen = Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-4.miniboss");
fn mini_boss_4(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
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::Dullahan,
),
))
.with_name("Dullahan Guard".to_string())
.with_loot_drop(chosen.read().choose().to_item()),
.with_asset_expect("common.entity.dungeon.tier-4.miniboss"),
]
}
@ -1216,40 +1073,18 @@ fn mini_boss_5(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<Entit
let mut entities = Vec::new();
match dynamic_rng.gen_range(0..2) {
0 => {
let trainer_loot =
Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-5.miniboss");
let hound_loot =
Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-5.minion");
entities.push(
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::Humanoid(comp::humanoid::Body::random()))
.with_loot_drop(trainer_loot.read().choose().to_item())
.with_asset_expect("common.entity.dungeon.tier-5.beastmaster"),
);
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(
dynamic_rng,
&comp::quadruped_medium::Species::Darkhound,
),
))
.with_name("Tamed Darkhound".to_string())
.with_loot_drop(hound_loot.read().choose().to_item())
.with_asset_expect("common.entity.dungeon.tier-5.hound")
});
},
_ => {
let chosen =
Lottery::<LootSpec>::load_expect("common.loot_tables.dungeon.tier-5.minion");
entities.resize_with(10, || {
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_body(comp::Body::BipedSmall(
comp::biped_small::Body::random_with(
dynamic_rng,
&comp::biped_small::Species::Husk,
),
))
.with_loot_drop(chosen.read().choose().to_item())
.with_asset_expect("common.entity.dungeon.tier-5.husk")
});
},
@ -1257,11 +1092,10 @@ fn mini_boss_5(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<Entit
entities
}
fn mini_boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
fn mini_boss_fallback(tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
vec![
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),
)),
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_asset_expect("common.entity.dungeon.fallback.miniboss"),
]
}
@ -1271,18 +1105,18 @@ mod tests {
#[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);
boss_0(tile_wcenter);
boss_1(tile_wcenter);
boss_2(tile_wcenter);
boss_3(tile_wcenter);
boss_4(tile_wcenter);
boss_5(tile_wcenter);
boss_fallback(tile_wcenter);
}
#[test]
// FIXME: Uses random, test may be not great
fn test_creating_enemies() {
let mut dynamic_rng = rand::thread_rng();
let raw_entity = EntityInfo::at(Vec3::new(0.0, 0.0, 0.0));
@ -1292,19 +1126,20 @@ mod tests {
enemy_3(&mut dynamic_rng, raw_entity.clone());
enemy_4(&mut dynamic_rng, raw_entity.clone());
enemy_5(&mut dynamic_rng, raw_entity.clone());
enemy_fallback(&mut dynamic_rng, raw_entity);
enemy_fallback(raw_entity);
}
#[test]
// FIXME: Uses random, test may be not great
fn test_creating_minibosses() {
let mut dynamic_rng = rand::thread_rng();
let tile_wcenter = Vec3::new(0, 0, 0);
mini_boss_0(&mut dynamic_rng, tile_wcenter);
mini_boss_1(&mut dynamic_rng, tile_wcenter);
mini_boss_2(&mut dynamic_rng, tile_wcenter);
mini_boss_3(&mut dynamic_rng, tile_wcenter);
mini_boss_4(&mut dynamic_rng, tile_wcenter);
mini_boss_0(tile_wcenter);
mini_boss_1(tile_wcenter);
mini_boss_2(tile_wcenter);
mini_boss_3(tile_wcenter);
mini_boss_4(tile_wcenter);
mini_boss_5(&mut dynamic_rng, tile_wcenter);
mini_boss_fallback(&mut dynamic_rng, tile_wcenter);
mini_boss_fallback(tile_wcenter);
}
}