Implement cursed items
This commit is contained in:
parent
8819fabcca
commit
9a0e931897
@ -42,3 +42,6 @@ pub struct EquipmentChanged {}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct TownPortal {}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct CursedItem {}
|
||||
|
23
src/gui.rs
23
src/gui.rs
@ -9,23 +9,34 @@ pub use enums::*;
|
||||
use tooltip::draw_tooltips;
|
||||
|
||||
use crate::components::{
|
||||
Attribute, Attributes, Consumable, Equipped, HungerClock, HungerState, InBackpack, Item,
|
||||
MagicItem, MagicItemClass, Name, ObfuscatedName, Pools, Vendor, Viewshed,
|
||||
Attribute, Attributes, Consumable, CursedItem, Equipped, HungerClock, HungerState, InBackpack,
|
||||
Item, MagicItem, MagicItemClass, Name, ObfuscatedName, Pools, Vendor, Viewshed,
|
||||
};
|
||||
use crate::game_log::GameLog;
|
||||
use crate::rex_assets::RexAssets;
|
||||
use crate::{camera, colors, Map, MasterDungeonMap, RunState, State, VendorMode};
|
||||
|
||||
pub fn get_item_color(ecs: &World, item: Entity) -> RGB {
|
||||
let dm = ecs.fetch::<crate::map::MasterDungeonMap>();
|
||||
|
||||
// If the item is cursed, and you have identified it, display it in red
|
||||
if let Some(name) = ecs.read_storage::<Name>().get(item) {
|
||||
if ecs.read_storage::<CursedItem>().get(item).is_some()
|
||||
&& dm.identified_items.contains(&name.name)
|
||||
{
|
||||
return colors::RED;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(magic) = ecs.read_storage::<MagicItem>().get(item) {
|
||||
match magic.class {
|
||||
return match magic.class {
|
||||
MagicItemClass::Common => colors::EQUIP_COMMON,
|
||||
MagicItemClass::Rare => colors::EQUIP_RARE,
|
||||
MagicItemClass::Legendary => colors::EQUIP_LEGEND,
|
||||
}
|
||||
} else {
|
||||
colors::WHITE
|
||||
};
|
||||
}
|
||||
|
||||
colors::WHITE
|
||||
}
|
||||
|
||||
pub fn get_item_display_name(ecs: &World, item: Entity) -> String {
|
||||
|
@ -1,6 +1,7 @@
|
||||
use ::specs::prelude::*;
|
||||
|
||||
use crate::components::{Equipped, InBackpack, WantsToRemoveItem};
|
||||
use crate::components::{CursedItem, Equipped, InBackpack, Name, WantsToRemoveItem};
|
||||
use crate::GameLog;
|
||||
|
||||
pub struct ItemRemoveSystem {}
|
||||
|
||||
@ -11,12 +12,25 @@ impl<'a> System<'a> for ItemRemoveSystem {
|
||||
WriteStorage<'a, WantsToRemoveItem>,
|
||||
WriteStorage<'a, Equipped>,
|
||||
WriteStorage<'a, InBackpack>,
|
||||
ReadStorage<'a, CursedItem>,
|
||||
WriteExpect<'a, GameLog>,
|
||||
ReadStorage<'a, Name>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (entities, mut wants_remove, mut equipped, mut backpack) = data;
|
||||
let (entities, mut wants_remove, mut equipped, mut backpack, cursed, mut gamelog, names) =
|
||||
data;
|
||||
|
||||
for (entity, to_remove) in (&entities, &wants_remove).join() {
|
||||
if cursed.get(to_remove.item).is_some() {
|
||||
gamelog.append(format!(
|
||||
"You cannot remove {}, it is cursed",
|
||||
names.get(to_remove.item).unwrap().name
|
||||
));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
equipped.remove(to_remove.item);
|
||||
backpack
|
||||
.insert(to_remove.item, InBackpack { owner: entity })
|
||||
|
@ -1,6 +1,10 @@
|
||||
use ::specs::prelude::*;
|
||||
|
||||
use crate::components::{EquipmentChanged, Equippable, Equipped, InBackpack, Name, WantsToUseItem};
|
||||
use crate::components::{
|
||||
CursedItem, EquipmentChanged, Equippable, Equipped, IdentifiedItem, InBackpack, Name,
|
||||
WantsToUseItem,
|
||||
};
|
||||
|
||||
use crate::GameLog;
|
||||
|
||||
pub struct ItemEquipOnUse {}
|
||||
@ -17,6 +21,8 @@ impl<'a> System<'a> for ItemEquipOnUse {
|
||||
WriteStorage<'a, Equipped>,
|
||||
WriteStorage<'a, InBackpack>,
|
||||
WriteStorage<'a, EquipmentChanged>,
|
||||
WriteStorage<'a, IdentifiedItem>,
|
||||
ReadStorage<'a, CursedItem>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
@ -30,6 +36,8 @@ impl<'a> System<'a> for ItemEquipOnUse {
|
||||
mut equipped,
|
||||
mut backpack,
|
||||
mut dirty,
|
||||
mut identified_item,
|
||||
cursed,
|
||||
) = data;
|
||||
|
||||
let mut remove_use = Vec::new();
|
||||
@ -40,38 +48,65 @@ impl<'a> System<'a> for ItemEquipOnUse {
|
||||
let target_slot = can_equip.slot;
|
||||
|
||||
// Remove any items the target has in the item's slot
|
||||
let mut can_equip = true;
|
||||
let mut log_entries: Vec<String> = Vec::new();
|
||||
let mut to_unequip = 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 un-equip {}.", name.name));
|
||||
if cursed.get(item_entity).is_some() {
|
||||
can_equip = false;
|
||||
gamelog
|
||||
.append(format!("You cannot un-equip {}, it is cursed.", name.name))
|
||||
} else {
|
||||
to_unequip.push(item_entity);
|
||||
if target == *player_entity {
|
||||
log_entries.push(format!("You un-equip {}.", name.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for item in to_unequip.iter() {
|
||||
equipped.remove(*item);
|
||||
backpack
|
||||
.insert(*item, InBackpack { owner: target })
|
||||
.expect("Unable to move equipped item to backpack.");
|
||||
}
|
||||
|
||||
// Wield the item
|
||||
equipped
|
||||
.insert(
|
||||
useitem.item,
|
||||
Equipped {
|
||||
owner: target,
|
||||
slot: target_slot,
|
||||
},
|
||||
)
|
||||
.expect("Unable to equip item");
|
||||
backpack.remove(useitem.item);
|
||||
if target == *player_entity {
|
||||
gamelog.append(format!(
|
||||
"You equip {}.",
|
||||
names.get(useitem.item).unwrap().name
|
||||
));
|
||||
if can_equip {
|
||||
// Identify the item
|
||||
if target == *player_entity {
|
||||
identified_item
|
||||
.insert(
|
||||
target,
|
||||
IdentifiedItem {
|
||||
name: names.get(useitem.item).unwrap().name.clone(),
|
||||
},
|
||||
)
|
||||
.expect("Unable to identify item.");
|
||||
}
|
||||
|
||||
for item in to_unequip.iter() {
|
||||
equipped.remove(*item);
|
||||
backpack
|
||||
.insert(*item, InBackpack { owner: target })
|
||||
.expect("Unable to move equipped item to backpack.");
|
||||
}
|
||||
|
||||
for entry in log_entries.iter() {
|
||||
gamelog.append(entry);
|
||||
}
|
||||
|
||||
// Wield the item
|
||||
equipped
|
||||
.insert(
|
||||
useitem.item,
|
||||
Equipped {
|
||||
owner: target,
|
||||
slot: target_slot,
|
||||
},
|
||||
)
|
||||
.expect("Unable to equip item");
|
||||
backpack.remove(useitem.item);
|
||||
if target == *player_entity {
|
||||
gamelog.append(format!(
|
||||
"You equip {}.",
|
||||
names.get(useitem.item).unwrap().name
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Done with item
|
||||
|
@ -64,6 +64,7 @@ fn init_state() -> State {
|
||||
Chasing,
|
||||
Confusion,
|
||||
Consumable,
|
||||
CursedItem,
|
||||
Door,
|
||||
DMSerializationHelper,
|
||||
EntityMoved,
|
||||
|
@ -47,4 +47,5 @@ pub struct Wearable {
|
||||
pub struct MagicItem {
|
||||
pub class: String,
|
||||
pub naming: String,
|
||||
pub cursed: Option<bool>,
|
||||
}
|
||||
|
@ -429,6 +429,12 @@ pub fn spawn_named_item(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(cursed) = magic.cursed {
|
||||
if cursed {
|
||||
eb = eb.with(CursedItem {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Some(eb.build());
|
||||
|
@ -69,6 +69,7 @@ pub fn save_game(ecs: &mut World) {
|
||||
Chasing,
|
||||
Confusion,
|
||||
Consumable,
|
||||
CursedItem,
|
||||
Door,
|
||||
DMSerializationHelper,
|
||||
EntityMoved,
|
||||
@ -186,6 +187,7 @@ pub fn load_game(ecs: &mut World) {
|
||||
Chasing,
|
||||
Confusion,
|
||||
Consumable,
|
||||
CursedItem,
|
||||
Door,
|
||||
DMSerializationHelper,
|
||||
EntityMoved,
|
||||
|
Loading…
Reference in New Issue
Block a user