use crate::{ assets::{self, Asset}, comp::CharacterAbility, effect::Effect, terrain::{Block, BlockKind}, }; //use rand::prelude::*; use rand::seq::SliceRandom; use specs::{Component, FlaggedStorage}; use specs_idvs::IDVStorage; use std::{fs::File, io::BufReader, time::Duration, vec::Vec}; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum SwordKind { Scimitar, Rapier, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ToolKind { Sword(SwordKind), Axe, Hammer, Bow, Dagger, Staff, Shield, Debug(DebugKind), } impl ToolData { pub fn equip_time(&self) -> Duration { Duration::from_millis(self.equip_time_millis) } pub fn get_abilities(&self) -> Vec { use CharacterAbility::*; use DebugKind::*; use ToolKind::*; match self.kind { Sword(_) => vec![TimedCombo { buildup_duration: Duration::from_millis(1000), recover_duration: Duration::from_millis(500), tool: *self, }], Axe => vec![BasicAttack { buildup_duration: Duration::from_millis(1000), recover_duration: Duration::from_millis(500), }], Hammer => vec![BasicAttack { buildup_duration: Duration::from_millis(1000), recover_duration: Duration::from_millis(500), }], Bow => vec![BasicAttack { buildup_duration: Duration::from_millis(1000), recover_duration: Duration::from_millis(500), }], Dagger => vec![BasicAttack { buildup_duration: Duration::from_millis(1000), recover_duration: Duration::from_millis(500), }], Staff => vec![BasicAttack { buildup_duration: Duration::from_millis(1000), recover_duration: Duration::from_millis(500), }], Shield => vec![BasicAttack { buildup_duration: Duration::from_millis(1000), recover_duration: Duration::from_millis(500), }], Debug(kind) => match kind { Boost => vec![], Possess => vec![], }, _ => vec![], } } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum DebugKind { Boost, Possess, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Armor { // TODO: Don't make armor be a body part. Wearing enemy's head is funny but also a creepy // thing to do. Helmet, Shoulders, Chestplate, Belt, Gloves, Pants, Boots, Back, Tabard, Gem, Necklace, } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Consumable { Apple, Cheese, Potion, Mushroom, Velorite, VeloriteFrag, PotionMinor, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Utility { Collar, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Ingredient { Flower, Grass, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct ToolData { pub kind: ToolKind, equip_time_millis: u64, attack_buildup_millis: u64, attack_recover_millis: u64, range: u64, pub base_damage: u64, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ItemKind { Tool(ToolData), Armor { kind: Armor, power: u32 }, Consumable { kind: Consumable, effect: Effect }, Utility { kind: Utility }, Ingredient(Ingredient), } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Item { name: String, description: String, pub kind: ItemKind, } impl Asset for Item { const ENDINGS: &'static [&'static str] = &["ron"]; fn parse(buf_reader: BufReader) -> Result { Ok(ron::de::from_reader(buf_reader).unwrap()) } } impl Item { pub fn name(&self) -> &str { &self.name } pub fn description(&self) -> &str { &self.description } pub fn try_reclaim_from_block(block: Block) -> Option { match block.kind() { BlockKind::Apple => Some(assets::load_expect_cloned("common.items.apple")), BlockKind::Mushroom => Some(assets::load_expect_cloned("common.items.mushroom")), BlockKind::Velorite => Some(assets::load_expect_cloned("common.items.velorite")), BlockKind::BlueFlower => Some(assets::load_expect_cloned("common.items.flowers.blue")), BlockKind::PinkFlower => Some(assets::load_expect_cloned("common.items.flowers.pink")), BlockKind::PurpleFlower => { Some(assets::load_expect_cloned("common.items.flowers.purple")) }, BlockKind::RedFlower => Some(assets::load_expect_cloned("common.items.flowers.red")), BlockKind::WhiteFlower => { Some(assets::load_expect_cloned("common.items.flowers.white")) }, BlockKind::YellowFlower => { Some(assets::load_expect_cloned("common.items.flowers.yellow")) }, BlockKind::Sunflower => Some(assets::load_expect_cloned("common.items.flowers.sun")), BlockKind::LongGrass => Some(assets::load_expect_cloned("common.items.grasses.long")), BlockKind::MediumGrass => { Some(assets::load_expect_cloned("common.items.grasses.medium")) }, BlockKind::ShortGrass => Some(assets::load_expect_cloned("common.items.grasses.short")), BlockKind::Chest => Some(assets::load_expect_cloned( [ "common.items.apple", "common.items.velorite", "common.items.veloritefrag", "common.items.cheese", "common.items.potion_minor", "common.items.collar", "common.items.weapons.starter_sword", "common.items.weapons.starter_axe", "common.items.weapons.starter_hammer", "common.items.weapons.starter_bow", "common.items.weapons.starter_staff", ] .choose(&mut rand::thread_rng()) .unwrap(), // Can't fail )), _ => None, } } } impl Component for Item { type Storage = FlaggedStorage>; }