NPCs can drop nothing

This commit is contained in:
ubruntu 2021-09-01 23:17:36 +00:00 committed by Samuel Keiffer
parent 82886dcd3f
commit bbc366e1b3
13 changed files with 63 additions and 46 deletions

View File

@ -59,6 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Glider dimensions somewhat increased overall
- Dungeon difficulty level starts at 1 instead of 0
- The radius of the safe zone around the starting town has been doubled
- NPCs can sometimes drop no loot at all
### Removed

View File

@ -1,5 +1,4 @@
[
(0.1, Item("common.items.food.meat.bird_large_raw")),
(1.0, Item("common.items.crafting_ing.animal_misc.phoenix_feather")),
]

View File

@ -1,4 +1,5 @@
[
(1.0, Item("common.items.food.meat.tough_raw")),
(3.0, Item("common.items.crafting_ing.hide.carapace")),
]

View File

@ -1,5 +1,4 @@
[
(4.0, LootTable("common.loot_tables.creature.quad_low.generic")),
(2.0, Item("common.items.crafting_ing.animal_misc.sharp_fang")),
]

View File

@ -1,5 +1,4 @@
[
(1.0, ItemQuantity("common.items.crafting_ing.animal_misc.fur", 1, 3)),
(0.25, LootTable("common.loot_tables.creature.quad_low.generic")),
]

View File

@ -0,0 +1,4 @@
[
// No loot is dropped
(1.0, None),
]

View File

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

View File

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

View File

@ -795,7 +795,7 @@ impl Item {
pub fn slot_mut(&mut self, slot: usize) -> Option<&mut InvSlot> { self.slots.get_mut(slot) }
pub fn try_reclaim_from_block(block: Block) -> Option<Self> {
Some(block.get_sprite()?.collectible_id()?.to_item())
block.get_sprite()?.collectible_id()?.to_item()
}
pub fn ability_spec(&self) -> Option<&AbilitySpec> { self.item_def.ability_spec.as_ref() }

View File

@ -113,6 +113,7 @@ impl From<Vec<(f32, LootSpec<String>)>> for ProbabilityFile {
.collect::<Vec<_>>()
.into_iter()
},
LootSpec::None => Vec::new().into_iter(),
})
.collect(),
}

View File

@ -255,12 +255,16 @@ impl EntityInfo {
match loot {
LootKind::Item(asset) => {
self = self.with_loot_drop(Item::new_from_asset_expect(&asset));
if let Ok(item) = Item::new_from_asset(&asset) {
self = self.with_loot_drop(item);
}
},
LootKind::LootTable(asset) => {
let table = Lottery::<LootSpec<String>>::load_expect(&asset);
let drop = table.read().choose().to_item();
if let Ok(table) = Lottery::<LootSpec<String>>::load(&asset) {
if let Some(drop) = table.read().choose().to_item() {
self = self.with_loot_drop(drop);
}
}
},
LootKind::Uninit => {},
}

View File

@ -84,26 +84,32 @@ pub enum LootSpec<T: AsRef<str>> {
ItemQuantity(T, u32, u32),
/// Loot table
LootTable(T),
/// No loot given
None,
}
impl<T: AsRef<str>> LootSpec<T> {
pub fn to_item(&self) -> Item {
pub fn to_item(&self) -> Option<Item> {
match self {
Self::Item(item) => Item::new_from_asset_expect(item.as_ref()),
Self::Item(item) => Item::new_from_asset(item.as_ref()).ok(),
Self::ItemQuantity(item, lower, upper) => {
let range = *lower..=*upper;
let quantity = thread_rng().gen_range(range);
let mut item = Item::new_from_asset_expect(item.as_ref());
if let Ok(mut item) = Item::new_from_asset(item.as_ref()) {
// TODO: Handle multiple of an item that is unstackable
if item.set_amount(quantity).is_err() {
warn!("Tried to set quantity on non stackable item");
}
item
Some(item)
} else {
None
}
},
Self::LootTable(table) => Lottery::<LootSpec<String>>::load_expect(table.as_ref())
.read()
.choose()
.to_item(),
Self::None => None,
}
}
}
@ -141,6 +147,7 @@ mod tests {
Lottery::<LootSpec<String>>::load_expect_cloned(loot_table);
validate_table_contents(loot_table);
},
LootSpec::None => {},
}
}
}

View File

@ -529,14 +529,13 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
})
};
let item = {
if let Some(item) = {
let mut item_drops = state.ecs().write_storage::<comp::ItemDrop>();
item_drops.remove(entity).map_or_else(
|| lottery().read().choose().to_item(),
|item_drop| item_drop.0,
|item_drop| Some(item_drop.0),
)
};
} {
let pos = state.ecs().read_storage::<comp::Pos>().get(entity).cloned();
let vel = state.ecs().read_storage::<comp::Vel>().get(entity).cloned();
if let Some(pos) = pos {
@ -565,6 +564,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
"Entity doesn't have a position, no bag is being dropped"
)
}
}
true
} else {