diff --git a/src/damage_system.rs b/src/damage_system.rs index f5de8d8..77cb9a3 100644 --- a/src/damage_system.rs +++ b/src/damage_system.rs @@ -1,7 +1,11 @@ +use ::rltk::RandomNumberGenerator; use ::specs::prelude::*; -use crate::components::{Equipped, InBackpack, Name, Player, Pools, Position, SufferDamage}; +use crate::components::{ + Equipped, InBackpack, LootTable, Name, Player, Pools, Position, SufferDamage, +}; use crate::game_log::GameLog; +use crate::raws::{get_item_drop, spawn_named_item, SpawnType, RAWS}; use crate::{Map, RunState}; pub struct DamageSystem {} @@ -62,6 +66,7 @@ pub fn delete_the_dead(ecs: &mut World) { } // Drop everything held by dead people + let mut to_spawn: Vec<(String, Position)> = Vec::new(); { // To avoid hold of borrowed entires, use a scope let mut to_drop: Vec<(Entity, Position)> = Vec::new(); @@ -69,12 +74,15 @@ pub fn delete_the_dead(ecs: &mut World) { let mut equipped = ecs.write_storage::(); let mut carried = ecs.write_storage::(); let mut positions = ecs.write_storage::(); + let loot_tables = ecs.read_storage::(); + let mut rng = ecs.write_resource::(); for victim in dead.iter() { + let pos = positions.get(*victim); for (entity, equipped) in (&entities, &equipped).join() { if equipped.owner == *victim { // Drop their stuff - if let Some(pos) = positions.get(*victim) { + if let Some(pos) = pos { to_drop.push((entity, *pos)); } } @@ -82,11 +90,21 @@ pub fn delete_the_dead(ecs: &mut World) { for (entity, backpack) in (&entities, &carried).join() { if backpack.owner == *victim { // Drop their stuff - if let Some(pos) = positions.get(*victim) { + if let Some(pos) = pos { to_drop.push((entity, *pos)); } } } + + if let Some(table) = loot_tables.get(*victim) { + let drop_finder = + get_item_drop(&crate::raws::RAWS.lock().unwrap(), &mut rng, &table.table); + if let Some(tag) = drop_finder { + if let Some(pos) = pos { + to_spawn.push((tag, *pos)); + } + } + } } for drop in to_drop.iter() { @@ -98,6 +116,20 @@ pub fn delete_the_dead(ecs: &mut World) { } } + { + for drop in to_spawn.iter() { + spawn_named_item( + &RAWS.lock().unwrap(), + ecs, + &drop.0, + SpawnType::AtPosition { + x: drop.1.x, + y: drop.1.y, + }, + ); + } + } + for victim in dead { ecs.delete_entity(victim) .expect("Unable to delete the dead"); diff --git a/src/raws/rawmaster.rs b/src/raws/rawmaster.rs index 0bcf42f..a313e50 100644 --- a/src/raws/rawmaster.rs +++ b/src/raws/rawmaster.rs @@ -3,6 +3,7 @@ use std::collections::{HashMap, HashSet}; use ::regex::Regex; use ::specs::prelude::*; use ::specs::saveload::{MarkedBuilder, SimpleMarker}; +use rltk::RandomNumberGenerator; use crate::components::*; use crate::gamesystem::{mana_at_level, npc_hp}; @@ -530,3 +531,21 @@ pub fn get_spawn_table_for_depth(raws: &RawMaster, depth: i32) -> RandomTable { rt } + +pub fn get_item_drop( + raws: &RawMaster, + rng: &mut RandomNumberGenerator, + table: &str, +) -> Option { + if raws.loot_index.contains_key(table) { + let mut rt = RandomTable::new(); + let available_options = &raws.raws.loot_tables[raws.loot_index[table]]; + for item in available_options.drops.iter() { + rt = rt.add(item.name.clone(), item.weight); + } + + return Some(rt.roll(rng)); + } + + None +}