use serde::{Serialize, Deserialize}; use std::collections::BTreeMap; use crate::{ language, static_content::species::SpeciesType, static_content::possession_type::PossessionType, }; use super::session::Session; #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub enum BuffCause { WaitingTask { task_code: String, task_type: String }, ByItem { item_code: String, item_type: String } } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub enum BuffImpact { ChangeStat { stat: StatType, magnitude: i16 }, ChangeSkill { skill: SkillType, magnitude: i16 } } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub struct Buff { pub description: String, pub cause: BuffCause, pub impacts: Vec } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum SkillType { Appraise, Blades, Bombs, Chemistry, Climb, Clubs, Craft, Dodge, Fish, Fists, Flails, Focus, Fuck, Hack, Locksmith, Medic, Persuade, Pilot, Pistols, Quickdraw, Repair, Ride, Rifles, Scavenge, Science, Sneak, Spears, Swim, Teach, Throw, Track, Wrestle, Whips } impl SkillType { pub fn values() -> Vec { use SkillType::*; vec!( Appraise, Blades, Bombs, Chemistry, Climb, Clubs, Craft, Dodge, Fish, Fists, Flails, Focus, Fuck, Hack, Locksmith, Medic, Persuade, Pilot, Pistols, Quickdraw, Repair, Ride, Rifles, Scavenge, Science, Sneak, Spears, Swim, Teach, Throw, Track, Wrestle, Whips ) } pub fn display(&self) -> &'static str { use SkillType::*; match self { Appraise => "appraise", Blades => "blades", Bombs => "bombs", Chemistry => "chemistry", Climb => "climb", Clubs => "clubs", Craft => "craft", Dodge => "dodge", Fish => "fish", Fists => "fists", Flails => "flails", Focus => "focus", Fuck => "fuck", Hack => "hack", Locksmith => "locksmith", Medic => "medic", Persuade => "persuade", Pilot => "pilot", Pistols => "pistols", Quickdraw => "quickdraw", Repair => "repair", Ride => "ride", Rifles => "rifles", Scavenge => "scavenge", Science => "science", Sneak => "sneak", Spears => "spears", Swim => "swim", Teach => "teach", Throw => "throw", Track => "track", Wrestle => "wrestle", Whips => "whips" } } } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum StatType { Brains, Senses, Brawn, Reflexes, Endurance, Cool } impl StatType { pub fn values() -> Vec { use StatType::*; vec!( Brains, Senses, Brawn, Reflexes, Endurance, Cool ) } } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub struct Pronouns { pub subject: String, pub object: String, pub intensive: String, pub possessive: String, // And some miscellaneous details to determine context pub is_plural: bool, // ... are instead of ... is pub is_proper: bool, // When naming, just ... instead of The ... } impl Pronouns { pub fn default_inanimate() -> Pronouns { Pronouns { subject: "it".to_owned(), object: "it".to_owned(), intensive: "itself".to_owned(), possessive: "its".to_owned(), is_plural: false, is_proper: true, } } pub fn default_animate() -> Pronouns { Pronouns { subject: "they".to_owned(), object: "them".to_owned(), intensive: "themselves".to_owned(), possessive: "their".to_owned(), is_plural: true, is_proper: true, } } #[allow(dead_code)] pub fn default_male() -> Pronouns { Pronouns { subject: "he".to_owned(), object: "him".to_owned(), intensive: "himself".to_owned(), possessive: "his".to_owned(), is_plural: false, is_proper: true, } } #[allow(dead_code)] pub fn default_female() -> Pronouns { Pronouns { subject: "she".to_owned(), object: "her".to_owned(), intensive: "herself".to_owned(), possessive: "her".to_owned(), is_plural: false, is_proper: true, } } } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub enum Subattack { Normal, Powerattacking, Feinting, Grabbing, Wrestling } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub enum LocationActionType { Normal, Sitting, Reclining, Worn, // Clothing etc... Wielded, Attacking(Subattack) } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub enum Sex { Male, Female, } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub enum ItemFlag { NoSay, NoSeeContents, DroppedItemsDontExpire } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] #[serde(default)] pub struct ActiveCombat { pub attacking: Option, pub attacked_by: Vec } impl Default for ActiveCombat { fn default() -> Self { Self { attacking: None, attacked_by: vec!() } } } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, PartialOrd)] #[serde(default)] pub struct Item { pub item_code: String, pub item_type: String, pub possession_type: Option, pub display: String, pub display_less_explicit: Option, pub details: Option, pub details_less_explicit: Option, pub aliases: Vec, pub location: String, // Item reference as item_type/item_code. pub action_type: LocationActionType, pub presence_target: Option, // e.g. what are they sitting on. pub is_static: bool, pub is_dead: bool, pub is_challenge_attack_only: bool, pub species: SpeciesType, pub health: u64, pub total_xp: u64, pub total_stats: BTreeMap, pub total_skills: BTreeMap, pub temporary_buffs: Vec, pub pronouns: Pronouns, pub flags: Vec, pub sex: Option, pub active_combat: Option, pub weight: u64, pub charges: u8 } impl Item { pub fn display_for_sentence(&self, explicit_ok: bool, pluralise: usize, caps: bool) -> String { let mut buf = String::new(); if self.is_dead { if pluralise > 1 { buf.push_str("the bodies of "); } else { buf.push_str("the body of "); } } let singular = if explicit_ok { &self.display } else { self.display_less_explicit.as_ref().unwrap_or(&self.display) }; if !self.pronouns.is_proper && pluralise == 1 { buf.push_str(language::indefinite_article(&singular)); buf.push(' '); } if pluralise > 1 { buf.push_str(&format!("{} ", pluralise)); } if pluralise > 1 { buf.push_str(&language::pluralise(singular)); } else { buf.push_str(singular); } if caps { language::caps_first(&buf) } else { buf } } pub fn display_for_session<'l>(self: &'l Self, session: &Session) -> String { self.display_for_sentence(!session.less_explicit_mode, 1, false) } pub fn details_for_session<'l>(self: &'l Self, session: &Session) -> Option<&'l str>{ self.details.as_ref() .map(|dets| session.explicit_if_allowed( dets.as_str(), self.details_less_explicit.as_ref().map(String::as_str) ) ) } } impl Default for Item { fn default() -> Self { Self { item_code: "unset".to_owned(), item_type: "unset".to_owned(), possession_type: None, display: "Item".to_owned(), display_less_explicit: None, details: None, details_less_explicit: None, aliases: vec!(), location: "room/storage".to_owned(), action_type: LocationActionType::Normal, presence_target: None, is_static: false, is_dead: false, is_challenge_attack_only: true, species: SpeciesType::Human, health: 24, total_xp: 0, total_stats: BTreeMap::new(), total_skills: BTreeMap::new(), temporary_buffs: Vec::new(), pronouns: Pronouns::default_inanimate(), flags: vec!(), sex: None, active_combat: Some(Default::default()), weight: 0, charges: 0, } } }