use hashbrown::HashSet; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use crate::static_data::{SecondaryEffect, TypeIdentifier}; use crate::StringKey; /// The move category defines what global kind of move this move is. #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] #[repr(u8)] pub enum MoveCategory { /// A physical move uses the physical attack stats and physical defense stats to calculate damage. Physical = 0, /// A special move uses the special attack stats and special defense stats to calculate damage. Special = 1, /// A status move does not do damage, and only runs a secondary effect. Status = 2, } /// The move target defines what kind of targets the move can touch. #[derive(Copy, Clone, PartialEq, Eq, Debug, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum MoveTarget { /// Adjacent allows a move to target any Pokemon that is either directly to the left or right of /// the user, opposed to the user, or left or right of the slot that is opposing the user. #[default] Adjacent = 0, /// AdjacentAlly allows a move to target any Pokemon that is directly to the left or right of /// the user. AdjacentAlly, /// AdjacentAllySelf allows a move to target any Pokemon that is either directly to the left or /// right of the user, or the user itself. AdjacentAllySelf, /// AdjacentOpponent allows a move to target any Pokemon that is either the opponent, or directly /// to the left or right of it. AdjacentOpponent, /// All makes the move target everything on the field. All, /// AllAdjacent makes the move target everything adjacent on the field. AllAdjacent, /// AllAdjacentOpponent makes the move target everything adjacent to the opponent, and the opponent. AllAdjacentOpponent, /// AllAlly targets all Pokemon on the same side as the user. AllAlly, /// AllOpponent targets all Pokemon on an opposing side from the user. AllOpponent, /// Any allows a move to target a single Pokemon, in any position. Any, /// RandomOpponent allows a move to target a single Pokemon, in a random position. RandomOpponent, /// SelfUse makes the move target the user itself. #[cfg_attr(feature = "serde", serde(rename = "Self"))] SelfUse, } /// A move is the skill Pokémon primarily use in battle. This is the data related to that. #[derive(PartialEq, Debug)] #[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct MoveData { /// The name of the move. name: StringKey, /// The attacking type of the move. move_type: TypeIdentifier, /// The category of the move. category: MoveCategory, /// The base power, not considering any modifiers, the move has. base_power: u8, /// The accuracy of the move in percentage. Should be 255 for moves that always hit. accuracy: u8, /// The number of times the move can be used. This can be modified on actually learned moves using /// PP-Ups base_usages: u8, /// How the move handles targets. target: MoveTarget, /// The priority of the move. A higher priority means the move should go before other moves. priority: i8, /// The optional secondary effect the move has. secondary_effect: Option, /// Arbitrary flags that can be applied to the move. flags: HashSet, } impl MoveData { /// Instantiates a new move. pub fn new( name: &StringKey, move_type: TypeIdentifier, category: MoveCategory, base_power: u8, accuracy: u8, base_usages: u8, target: MoveTarget, priority: i8, secondary_effect: Option, flags: HashSet, ) -> MoveData { MoveData { name: name.clone(), move_type, category, base_power, accuracy, base_usages, target, priority, secondary_effect, flags, } } /// The name of the move. pub fn name(&self) -> &StringKey { &self.name } /// The attacking type of the move. pub fn move_type(&self) -> TypeIdentifier { self.move_type } /// The category of the move. pub fn category(&self) -> MoveCategory { self.category } /// The base power, not considering any modifiers, the move has. pub fn base_power(&self) -> u8 { self.base_power } /// The accuracy of the move in percentage. Should be 255 for moves that always hit. pub fn accuracy(&self) -> u8 { self.accuracy } /// The number of times the move can be used. This can be modified on actually learned moves using /// PP-Ups pub fn base_usages(&self) -> u8 { self.base_usages } /// How the move handles targets. pub fn target(&self) -> MoveTarget { self.target } /// The priority of the move. A higher priority means the move should go before other moves. pub fn priority(&self) -> i8 { self.priority } /// The optional secondary effect the move has. pub fn secondary_effect(&self) -> &Option { &self.secondary_effect } /// Arbitrary flags that can be applied to the move. pub fn has_flag(&self, key: &StringKey) -> bool { self.flags.contains::(key) } /// Arbitrary flags that can be applied to the move. pub fn has_flag_by_hash(&self, key_hash: u32) -> bool { self.flags.contains::(&key_hash) } }