Extract item use system from inventory system module
This commit is contained in:
parent
444b692779
commit
1a95ad5650
@ -1,9 +1,11 @@
|
|||||||
|
mod item_use_system;
|
||||||
|
|
||||||
use ::specs::prelude::*;
|
use ::specs::prelude::*;
|
||||||
|
pub use item_use_system::ItemUseSystem;
|
||||||
|
|
||||||
use crate::components::*;
|
use crate::components::*;
|
||||||
use crate::game_log::GameLog;
|
use crate::game_log::GameLog;
|
||||||
use crate::particle_system::ParticleBuilder;
|
use crate::{raws, MasterDungeonMap};
|
||||||
use crate::{colors, raws, spatial, Map, MasterDungeonMap, RunState};
|
|
||||||
|
|
||||||
fn obfuscate_name(
|
fn obfuscate_name(
|
||||||
item: Entity,
|
item: Entity,
|
||||||
@ -86,345 +88,6 @@ impl<'a> System<'a> for ItemCollectionSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ItemUseSystem {}
|
|
||||||
|
|
||||||
impl<'a> System<'a> for ItemUseSystem {
|
|
||||||
#[allow(clippy::type_complexity)]
|
|
||||||
type SystemData = (
|
|
||||||
ReadExpect<'a, Entity>,
|
|
||||||
WriteExpect<'a, GameLog>,
|
|
||||||
WriteExpect<'a, Map>,
|
|
||||||
Entities<'a>,
|
|
||||||
WriteStorage<'a, WantsToUseItem>,
|
|
||||||
ReadStorage<'a, Name>,
|
|
||||||
ReadStorage<'a, Consumable>,
|
|
||||||
ReadStorage<'a, ProvidesHealing>,
|
|
||||||
ReadStorage<'a, InflictsDamage>,
|
|
||||||
WriteStorage<'a, Pools>,
|
|
||||||
WriteStorage<'a, SufferDamage>,
|
|
||||||
ReadStorage<'a, AreaOfEffect>,
|
|
||||||
WriteStorage<'a, Confusion>,
|
|
||||||
ReadStorage<'a, Equippable>,
|
|
||||||
WriteStorage<'a, Equipped>,
|
|
||||||
WriteStorage<'a, InBackpack>,
|
|
||||||
WriteExpect<'a, ParticleBuilder>,
|
|
||||||
ReadStorage<'a, Position>,
|
|
||||||
ReadStorage<'a, ProvidesFood>,
|
|
||||||
WriteStorage<'a, HungerClock>,
|
|
||||||
ReadStorage<'a, MagicMapper>,
|
|
||||||
WriteExpect<'a, RunState>,
|
|
||||||
WriteStorage<'a, EquipmentChanged>,
|
|
||||||
ReadStorage<'a, TownPortal>,
|
|
||||||
WriteStorage<'a, IdentifiedItem>,
|
|
||||||
);
|
|
||||||
|
|
||||||
#[allow(clippy::cognitive_complexity)]
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
|
||||||
let (
|
|
||||||
player_entity,
|
|
||||||
mut gamelog,
|
|
||||||
map,
|
|
||||||
entities,
|
|
||||||
mut wants_use,
|
|
||||||
names,
|
|
||||||
consumables,
|
|
||||||
healing,
|
|
||||||
inflict_damage,
|
|
||||||
mut combat_stats,
|
|
||||||
mut suffer_damage,
|
|
||||||
aoe,
|
|
||||||
mut confused,
|
|
||||||
equippable,
|
|
||||||
mut equipped,
|
|
||||||
mut backpack,
|
|
||||||
mut particle_builder,
|
|
||||||
positions,
|
|
||||||
provides_food,
|
|
||||||
mut hunger_clocks,
|
|
||||||
magic_mapper,
|
|
||||||
mut runstate,
|
|
||||||
mut dirty,
|
|
||||||
town_portal,
|
|
||||||
mut identified_item,
|
|
||||||
) = data;
|
|
||||||
|
|
||||||
for (entity, useitem) in (&entities, &wants_use).join() {
|
|
||||||
dirty
|
|
||||||
.insert(entity, EquipmentChanged {})
|
|
||||||
.expect("Unable to insert equipment change");
|
|
||||||
let mut used_item = true;
|
|
||||||
|
|
||||||
// Targeting
|
|
||||||
let mut targets: Vec<Entity> = Vec::new();
|
|
||||||
match useitem.target {
|
|
||||||
None => {
|
|
||||||
targets.push(*player_entity);
|
|
||||||
}
|
|
||||||
Some(target) => {
|
|
||||||
match aoe.get(useitem.item) {
|
|
||||||
None => {
|
|
||||||
// Single target in tile
|
|
||||||
let idx = map.xy_idx(target.x, target.y);
|
|
||||||
spatial::for_each_tile_content(idx, |mob| targets.push(mob));
|
|
||||||
}
|
|
||||||
Some(area_effect) => {
|
|
||||||
// AoE
|
|
||||||
let mut blast_tiles =
|
|
||||||
rltk::field_of_view(target, area_effect.radius, &*map);
|
|
||||||
blast_tiles.retain(|p| {
|
|
||||||
p.x > 0 && p.x < map.width - 1 && p.y > 0 && p.y < map.height - 1
|
|
||||||
});
|
|
||||||
|
|
||||||
for tile_idx in blast_tiles.iter() {
|
|
||||||
let idx = map.xy_idx(tile_idx.x, tile_idx.y);
|
|
||||||
spatial::for_each_tile_content(idx, |mob| targets.push(mob));
|
|
||||||
|
|
||||||
particle_builder.request(
|
|
||||||
tile_idx.x,
|
|
||||||
tile_idx.y,
|
|
||||||
colors::ORANGE,
|
|
||||||
colors::BLACK,
|
|
||||||
rltk::to_cp437('░'),
|
|
||||||
200.0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Identify
|
|
||||||
if entity == *player_entity {
|
|
||||||
identified_item
|
|
||||||
.insert(
|
|
||||||
entity,
|
|
||||||
IdentifiedItem {
|
|
||||||
name: names.get(useitem.item).unwrap().name.clone(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.expect("Unable to identify item");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it is equippable, then we want to equip it - and unequip whatever else was in that slot
|
|
||||||
match equippable.get(useitem.item) {
|
|
||||||
None => {}
|
|
||||||
Some(can_equip) => {
|
|
||||||
let target_slot = can_equip.slot;
|
|
||||||
let target = targets[0];
|
|
||||||
|
|
||||||
// Remove any items the target has in the item's slot
|
|
||||||
let mut to_unequip: Vec<Entity> = Vec::new();
|
|
||||||
for (item_entity, already_equipped, name) in
|
|
||||||
(&entities, &equipped, &names).join()
|
|
||||||
{
|
|
||||||
if already_equipped.owner == target && already_equipped.slot == target_slot
|
|
||||||
{
|
|
||||||
to_unequip.push(item_entity);
|
|
||||||
if target == *player_entity {
|
|
||||||
gamelog.append(format!("You unequip {}.", name.name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for item in to_unequip.iter() {
|
|
||||||
equipped.remove(*item);
|
|
||||||
backpack
|
|
||||||
.insert(*item, InBackpack { owner: target })
|
|
||||||
.expect("Unable to put unequipped item back in backpack");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wield the item
|
|
||||||
equipped
|
|
||||||
.insert(
|
|
||||||
useitem.item,
|
|
||||||
Equipped {
|
|
||||||
owner: target,
|
|
||||||
slot: target_slot,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.expect("Failed to equip item");
|
|
||||||
backpack.remove(useitem.item);
|
|
||||||
if target == *player_entity {
|
|
||||||
gamelog.append(format!(
|
|
||||||
"You equip {}.",
|
|
||||||
names.get(useitem.item).unwrap().name
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it is edible, eat it!
|
|
||||||
match provides_food.get(useitem.item) {
|
|
||||||
None => {}
|
|
||||||
Some(_) => {
|
|
||||||
used_item = true;
|
|
||||||
let target = targets[0];
|
|
||||||
|
|
||||||
if let Some(hc) = hunger_clocks.get_mut(target) {
|
|
||||||
hc.state = HungerState::WellFed;
|
|
||||||
hc.duration = 20;
|
|
||||||
|
|
||||||
gamelog.append(format!(
|
|
||||||
"You eat the {}.",
|
|
||||||
names.get(useitem.item).unwrap().name
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If its a magic mapper...
|
|
||||||
match magic_mapper.get(useitem.item) {
|
|
||||||
None => {}
|
|
||||||
Some(_) => {
|
|
||||||
used_item = true;
|
|
||||||
gamelog.append("The map is revealed to you!");
|
|
||||||
|
|
||||||
*runstate = RunState::MagicMapReveal { row: 0 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it's a town portal...
|
|
||||||
if town_portal.get(useitem.item).is_some() {
|
|
||||||
if map.depth == 1 {
|
|
||||||
gamelog.append("You are already in town, so the scroll does nothing");
|
|
||||||
} else {
|
|
||||||
used_item = true;
|
|
||||||
gamelog.append("You are teleported back to town!");
|
|
||||||
|
|
||||||
*runstate = RunState::TownPortal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the item heals, apply the healing
|
|
||||||
match healing.get(useitem.item) {
|
|
||||||
None => {}
|
|
||||||
Some(healer) => {
|
|
||||||
used_item = false;
|
|
||||||
|
|
||||||
for target in targets.iter() {
|
|
||||||
if let Some(stats) = combat_stats.get_mut(*target) {
|
|
||||||
stats.hit_points.current = i32::min(
|
|
||||||
stats.hit_points.max,
|
|
||||||
stats.hit_points.current + healer.heal_amount,
|
|
||||||
);
|
|
||||||
if entity == *player_entity {
|
|
||||||
gamelog.append(format!(
|
|
||||||
"You drink the {}, healing {} hp.",
|
|
||||||
names.get(useitem.item).unwrap().name,
|
|
||||||
healer.heal_amount
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
used_item = true;
|
|
||||||
|
|
||||||
// Visually show healing
|
|
||||||
if let Some(pos) = positions.get(*target) {
|
|
||||||
particle_builder.request(
|
|
||||||
pos.x,
|
|
||||||
pos.y,
|
|
||||||
colors::GREEN,
|
|
||||||
colors::BLACK,
|
|
||||||
rltk::to_cp437('♥'),
|
|
||||||
200.0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it inflicts damage, apply it to the target cell
|
|
||||||
match inflict_damage.get(useitem.item) {
|
|
||||||
None => {}
|
|
||||||
Some(damage) => {
|
|
||||||
used_item = false;
|
|
||||||
|
|
||||||
for mob in targets.iter() {
|
|
||||||
SufferDamage::new_damage(&mut suffer_damage, *mob, damage.damage, true);
|
|
||||||
if entity == *player_entity {
|
|
||||||
let mob_name = names.get(*mob).unwrap();
|
|
||||||
let item_name = names.get(useitem.item).unwrap();
|
|
||||||
|
|
||||||
gamelog.append(format!(
|
|
||||||
"You use {} on {}, inflicting {} hp.",
|
|
||||||
item_name.name, mob_name.name, damage.damage
|
|
||||||
));
|
|
||||||
|
|
||||||
if let Some(pos) = positions.get(*mob) {
|
|
||||||
particle_builder.request(
|
|
||||||
pos.x,
|
|
||||||
pos.y,
|
|
||||||
colors::RED,
|
|
||||||
colors::BLACK,
|
|
||||||
rltk::to_cp437('‼'),
|
|
||||||
200.0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
used_item = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can it pass along confusion? Note the use of scopes
|
|
||||||
// to escape from the borrow checker!
|
|
||||||
let mut add_confusion = Vec::new();
|
|
||||||
{
|
|
||||||
match confused.get(useitem.item) {
|
|
||||||
None => {}
|
|
||||||
Some(confusion) => {
|
|
||||||
used_item = false;
|
|
||||||
|
|
||||||
for mob in targets.iter() {
|
|
||||||
add_confusion.push((*mob, confusion.turns));
|
|
||||||
if entity == *player_entity {
|
|
||||||
let mob_name = names.get(*mob).unwrap();
|
|
||||||
let item_name = names.get(useitem.item).unwrap();
|
|
||||||
|
|
||||||
gamelog.append(format!(
|
|
||||||
"You use {} on {}, confusing them.",
|
|
||||||
item_name.name, mob_name.name
|
|
||||||
));
|
|
||||||
|
|
||||||
if let Some(pos) = positions.get(*mob) {
|
|
||||||
particle_builder.request(
|
|
||||||
pos.x,
|
|
||||||
pos.y,
|
|
||||||
colors::MAGENTA,
|
|
||||||
colors::BLACK,
|
|
||||||
rltk::to_cp437('?'),
|
|
||||||
200.0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for mob in add_confusion.iter() {
|
|
||||||
confused
|
|
||||||
.insert(mob.0, Confusion { turns: mob.1 })
|
|
||||||
.expect("Unable to add confused status");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it's a consumable, delete it on use
|
|
||||||
if used_item {
|
|
||||||
let consumable = consumables.get(useitem.item);
|
|
||||||
match consumable {
|
|
||||||
None => {}
|
|
||||||
Some(_) => {
|
|
||||||
entities
|
|
||||||
.delete(useitem.item)
|
|
||||||
.expect("Failed to consume item");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wants_use.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ItemDropSystem {}
|
pub struct ItemDropSystem {}
|
||||||
|
|
||||||
impl<'a> System<'a> for ItemDropSystem {
|
impl<'a> System<'a> for ItemDropSystem {
|
||||||
|
345
src/inventory_system/item_use_system.rs
Normal file
345
src/inventory_system/item_use_system.rs
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
use ::specs::prelude::*;
|
||||||
|
|
||||||
|
use crate::components::*;
|
||||||
|
use crate::game_log::GameLog;
|
||||||
|
use crate::particle_system::ParticleBuilder;
|
||||||
|
use crate::{colors, spatial, Map, RunState};
|
||||||
|
|
||||||
|
pub struct ItemUseSystem {}
|
||||||
|
|
||||||
|
impl<'a> System<'a> for ItemUseSystem {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
type SystemData = (
|
||||||
|
ReadExpect<'a, Entity>,
|
||||||
|
WriteExpect<'a, GameLog>,
|
||||||
|
WriteExpect<'a, Map>,
|
||||||
|
Entities<'a>,
|
||||||
|
WriteStorage<'a, WantsToUseItem>,
|
||||||
|
ReadStorage<'a, Name>,
|
||||||
|
ReadStorage<'a, Consumable>,
|
||||||
|
ReadStorage<'a, ProvidesHealing>,
|
||||||
|
ReadStorage<'a, InflictsDamage>,
|
||||||
|
WriteStorage<'a, Pools>,
|
||||||
|
WriteStorage<'a, SufferDamage>,
|
||||||
|
ReadStorage<'a, AreaOfEffect>,
|
||||||
|
WriteStorage<'a, Confusion>,
|
||||||
|
ReadStorage<'a, Equippable>,
|
||||||
|
WriteStorage<'a, Equipped>,
|
||||||
|
WriteStorage<'a, InBackpack>,
|
||||||
|
WriteExpect<'a, ParticleBuilder>,
|
||||||
|
ReadStorage<'a, Position>,
|
||||||
|
ReadStorage<'a, ProvidesFood>,
|
||||||
|
WriteStorage<'a, HungerClock>,
|
||||||
|
ReadStorage<'a, MagicMapper>,
|
||||||
|
WriteExpect<'a, RunState>,
|
||||||
|
WriteStorage<'a, EquipmentChanged>,
|
||||||
|
ReadStorage<'a, TownPortal>,
|
||||||
|
WriteStorage<'a, IdentifiedItem>,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[allow(clippy::cognitive_complexity)]
|
||||||
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
|
let (
|
||||||
|
player_entity,
|
||||||
|
mut gamelog,
|
||||||
|
map,
|
||||||
|
entities,
|
||||||
|
mut wants_use,
|
||||||
|
names,
|
||||||
|
consumables,
|
||||||
|
healing,
|
||||||
|
inflict_damage,
|
||||||
|
mut combat_stats,
|
||||||
|
mut suffer_damage,
|
||||||
|
aoe,
|
||||||
|
mut confused,
|
||||||
|
equippable,
|
||||||
|
mut equipped,
|
||||||
|
mut backpack,
|
||||||
|
mut particle_builder,
|
||||||
|
positions,
|
||||||
|
provides_food,
|
||||||
|
mut hunger_clocks,
|
||||||
|
magic_mapper,
|
||||||
|
mut runstate,
|
||||||
|
mut dirty,
|
||||||
|
town_portal,
|
||||||
|
mut identified_item,
|
||||||
|
) = data;
|
||||||
|
|
||||||
|
for (entity, useitem) in (&entities, &wants_use).join() {
|
||||||
|
dirty
|
||||||
|
.insert(entity, EquipmentChanged {})
|
||||||
|
.expect("Unable to insert equipment change");
|
||||||
|
let mut used_item = true;
|
||||||
|
|
||||||
|
// Targeting
|
||||||
|
let mut targets: Vec<Entity> = Vec::new();
|
||||||
|
match useitem.target {
|
||||||
|
None => {
|
||||||
|
targets.push(*player_entity);
|
||||||
|
}
|
||||||
|
Some(target) => {
|
||||||
|
match aoe.get(useitem.item) {
|
||||||
|
None => {
|
||||||
|
// Single target in tile
|
||||||
|
let idx = map.xy_idx(target.x, target.y);
|
||||||
|
spatial::for_each_tile_content(idx, |mob| targets.push(mob));
|
||||||
|
}
|
||||||
|
Some(area_effect) => {
|
||||||
|
// AoE
|
||||||
|
let mut blast_tiles =
|
||||||
|
rltk::field_of_view(target, area_effect.radius, &*map);
|
||||||
|
blast_tiles.retain(|p| {
|
||||||
|
p.x > 0 && p.x < map.width - 1 && p.y > 0 && p.y < map.height - 1
|
||||||
|
});
|
||||||
|
|
||||||
|
for tile_idx in blast_tiles.iter() {
|
||||||
|
let idx = map.xy_idx(tile_idx.x, tile_idx.y);
|
||||||
|
spatial::for_each_tile_content(idx, |mob| targets.push(mob));
|
||||||
|
|
||||||
|
particle_builder.request(
|
||||||
|
tile_idx.x,
|
||||||
|
tile_idx.y,
|
||||||
|
colors::ORANGE,
|
||||||
|
colors::BLACK,
|
||||||
|
rltk::to_cp437('░'),
|
||||||
|
200.0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identify
|
||||||
|
if entity == *player_entity {
|
||||||
|
identified_item
|
||||||
|
.insert(
|
||||||
|
entity,
|
||||||
|
IdentifiedItem {
|
||||||
|
name: names.get(useitem.item).unwrap().name.clone(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.expect("Unable to identify item");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is equippable, then we want to equip it - and unequip whatever else was in that slot
|
||||||
|
match equippable.get(useitem.item) {
|
||||||
|
None => {}
|
||||||
|
Some(can_equip) => {
|
||||||
|
let target_slot = can_equip.slot;
|
||||||
|
let target = targets[0];
|
||||||
|
|
||||||
|
// Remove any items the target has in the item's slot
|
||||||
|
let mut to_unequip: Vec<Entity> = Vec::new();
|
||||||
|
for (item_entity, already_equipped, name) in
|
||||||
|
(&entities, &equipped, &names).join()
|
||||||
|
{
|
||||||
|
if already_equipped.owner == target && already_equipped.slot == target_slot
|
||||||
|
{
|
||||||
|
to_unequip.push(item_entity);
|
||||||
|
if target == *player_entity {
|
||||||
|
gamelog.append(format!("You unequip {}.", name.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for item in to_unequip.iter() {
|
||||||
|
equipped.remove(*item);
|
||||||
|
backpack
|
||||||
|
.insert(*item, InBackpack { owner: target })
|
||||||
|
.expect("Unable to put unequipped item back in backpack");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wield the item
|
||||||
|
equipped
|
||||||
|
.insert(
|
||||||
|
useitem.item,
|
||||||
|
Equipped {
|
||||||
|
owner: target,
|
||||||
|
slot: target_slot,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.expect("Failed to equip item");
|
||||||
|
backpack.remove(useitem.item);
|
||||||
|
if target == *player_entity {
|
||||||
|
gamelog.append(format!(
|
||||||
|
"You equip {}.",
|
||||||
|
names.get(useitem.item).unwrap().name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is edible, eat it!
|
||||||
|
match provides_food.get(useitem.item) {
|
||||||
|
None => {}
|
||||||
|
Some(_) => {
|
||||||
|
used_item = true;
|
||||||
|
let target = targets[0];
|
||||||
|
|
||||||
|
if let Some(hc) = hunger_clocks.get_mut(target) {
|
||||||
|
hc.state = HungerState::WellFed;
|
||||||
|
hc.duration = 20;
|
||||||
|
|
||||||
|
gamelog.append(format!(
|
||||||
|
"You eat the {}.",
|
||||||
|
names.get(useitem.item).unwrap().name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If its a magic mapper...
|
||||||
|
match magic_mapper.get(useitem.item) {
|
||||||
|
None => {}
|
||||||
|
Some(_) => {
|
||||||
|
used_item = true;
|
||||||
|
gamelog.append("The map is revealed to you!");
|
||||||
|
|
||||||
|
*runstate = RunState::MagicMapReveal { row: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's a town portal...
|
||||||
|
if town_portal.get(useitem.item).is_some() {
|
||||||
|
if map.depth == 1 {
|
||||||
|
gamelog.append("You are already in town, so the scroll does nothing");
|
||||||
|
} else {
|
||||||
|
used_item = true;
|
||||||
|
gamelog.append("You are teleported back to town!");
|
||||||
|
|
||||||
|
*runstate = RunState::TownPortal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the item heals, apply the healing
|
||||||
|
match healing.get(useitem.item) {
|
||||||
|
None => {}
|
||||||
|
Some(healer) => {
|
||||||
|
used_item = false;
|
||||||
|
|
||||||
|
for target in targets.iter() {
|
||||||
|
if let Some(stats) = combat_stats.get_mut(*target) {
|
||||||
|
stats.hit_points.current = i32::min(
|
||||||
|
stats.hit_points.max,
|
||||||
|
stats.hit_points.current + healer.heal_amount,
|
||||||
|
);
|
||||||
|
if entity == *player_entity {
|
||||||
|
gamelog.append(format!(
|
||||||
|
"You drink the {}, healing {} hp.",
|
||||||
|
names.get(useitem.item).unwrap().name,
|
||||||
|
healer.heal_amount
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
used_item = true;
|
||||||
|
|
||||||
|
// Visually show healing
|
||||||
|
if let Some(pos) = positions.get(*target) {
|
||||||
|
particle_builder.request(
|
||||||
|
pos.x,
|
||||||
|
pos.y,
|
||||||
|
colors::GREEN,
|
||||||
|
colors::BLACK,
|
||||||
|
rltk::to_cp437('♥'),
|
||||||
|
200.0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it inflicts damage, apply it to the target cell
|
||||||
|
match inflict_damage.get(useitem.item) {
|
||||||
|
None => {}
|
||||||
|
Some(damage) => {
|
||||||
|
used_item = false;
|
||||||
|
|
||||||
|
for mob in targets.iter() {
|
||||||
|
SufferDamage::new_damage(&mut suffer_damage, *mob, damage.damage, true);
|
||||||
|
if entity == *player_entity {
|
||||||
|
let mob_name = names.get(*mob).unwrap();
|
||||||
|
let item_name = names.get(useitem.item).unwrap();
|
||||||
|
|
||||||
|
gamelog.append(format!(
|
||||||
|
"You use {} on {}, inflicting {} hp.",
|
||||||
|
item_name.name, mob_name.name, damage.damage
|
||||||
|
));
|
||||||
|
|
||||||
|
if let Some(pos) = positions.get(*mob) {
|
||||||
|
particle_builder.request(
|
||||||
|
pos.x,
|
||||||
|
pos.y,
|
||||||
|
colors::RED,
|
||||||
|
colors::BLACK,
|
||||||
|
rltk::to_cp437('‼'),
|
||||||
|
200.0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
used_item = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can it pass along confusion? Note the use of scopes
|
||||||
|
// to escape from the borrow checker!
|
||||||
|
let mut add_confusion = Vec::new();
|
||||||
|
{
|
||||||
|
match confused.get(useitem.item) {
|
||||||
|
None => {}
|
||||||
|
Some(confusion) => {
|
||||||
|
used_item = false;
|
||||||
|
|
||||||
|
for mob in targets.iter() {
|
||||||
|
add_confusion.push((*mob, confusion.turns));
|
||||||
|
if entity == *player_entity {
|
||||||
|
let mob_name = names.get(*mob).unwrap();
|
||||||
|
let item_name = names.get(useitem.item).unwrap();
|
||||||
|
|
||||||
|
gamelog.append(format!(
|
||||||
|
"You use {} on {}, confusing them.",
|
||||||
|
item_name.name, mob_name.name
|
||||||
|
));
|
||||||
|
|
||||||
|
if let Some(pos) = positions.get(*mob) {
|
||||||
|
particle_builder.request(
|
||||||
|
pos.x,
|
||||||
|
pos.y,
|
||||||
|
colors::MAGENTA,
|
||||||
|
colors::BLACK,
|
||||||
|
rltk::to_cp437('?'),
|
||||||
|
200.0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for mob in add_confusion.iter() {
|
||||||
|
confused
|
||||||
|
.insert(mob.0, Confusion { turns: mob.1 })
|
||||||
|
.expect("Unable to add confused status");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's a consumable, delete it on use
|
||||||
|
if used_item {
|
||||||
|
let consumable = consumables.get(useitem.item);
|
||||||
|
match consumable {
|
||||||
|
None => {}
|
||||||
|
Some(_) => {
|
||||||
|
entities
|
||||||
|
.delete(useitem.item)
|
||||||
|
.expect("Failed to consume item");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wants_use.clear();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user