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