using System.Collections.Immutable; using PkmnLib.Static.Utils; namespace PkmnLib.Static.Moves; /// <summary> /// The move category defines what global kind of move this move is. /// </summary> public enum MoveCategory { /// <summary> /// A physical move uses the physical attack stats and physical defense stats to calculate damage. /// </summary> Physical = 0, /// <summary> /// A special move uses the special attack stats and special defense stats to calculate damage. /// </summary> Special = 1, /// <summary> /// A status move does not do damage, and only runs a secondary effect. /// </summary> Status = 2, } /// <summary> /// The move target defines what kind of targets the move can touch. /// </summary> public enum MoveTarget { /// <summary> /// Adjacent allows a move to target any Pokémon 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. /// </summary> Adjacent = 0, /// <summary> /// AdjacentAlly allows a move to target any Pokémon that is directly to the left or right of /// the user. /// </summary> AdjacentAlly, /// <summary> /// AdjacentAllySelf allows a move to target any Pokémon that is either directly to the left or /// right of the user, or the user itself. /// </summary> AdjacentAllySelf, /// <summary> /// AdjacentOpponent allows a move to target any Pokémon that is either the opponent, or directly /// to the left or right of it. /// </summary> AdjacentOpponent, /// <summary> /// All makes the move target everything on the field. /// </summary> All, /// <summary> /// AllAdjacent makes the move target everything adjacent on the field. /// </summary> AllAdjacent, /// <summary> /// AllAdjacentOpponent makes the move target everything adjacent to the opponent, and the opponent. /// </summary> AllAdjacentOpponent, /// <summary> /// AllAlly targets all Pokémon on the same side as the user. /// </summary> AllAlly, /// <summary> /// AllOpponent targets all Pokémon on an opposing side from the user. /// </summary> AllOpponent, /// <summary> /// Any allows a move to target a single Pokémon, in any position. /// </summary> Any, /// <summary> /// RandomOpponent allows a move to target a single Pokémon, in a random position. /// </summary> RandomOpponent, /// <summary> /// SelfUse makes the move target the user itself. /// </summary> SelfUse, } /// <summary> /// A move is the skill Pokémon primarily use in battle. This is the data related to that. /// </summary> public interface IMoveData : INamedValue { /// <summary> /// The attacking type of the move. /// </summary> TypeIdentifier MoveType { get; } /// <summary> /// The category of the move. /// </summary> MoveCategory Category { get; } /// <summary> /// The base power, not considering any modifiers, the move has. /// </summary> byte BasePower { get; } /// <summary> /// The accuracy of the move in percentage. Should be 255 for moves that always hit. /// </summary> byte Accuracy { get; } /// <summary> /// The number of times the move can be used. This can be modified on actually learned moves using PP-Ups /// </summary> byte BaseUsages { get; } /// <summary> /// How the move handles targets. /// </summary> MoveTarget Target { get; } /// <summary> /// The priority of the move. A higher priority means the move should go before other moves. /// </summary> sbyte Priority { get; } /// <summary> /// The optional secondary effect the move has. /// </summary> ISecondaryEffect? SecondaryEffect { get; } /// <summary> /// Arbitrary flags that can be applied to the move. /// </summary> bool HasFlag(string key); } /// <inheritdoc /> public class MoveDataImpl : IMoveData { /// <inheritdoc cref="MoveDataImpl" /> public MoveDataImpl(StringKey name, TypeIdentifier moveType, MoveCategory category, byte basePower, byte accuracy, byte baseUsages, MoveTarget target, sbyte priority, ISecondaryEffect? secondaryEffect, IEnumerable<StringKey> flags) { Name = name; MoveType = moveType; Category = category; BasePower = basePower; Accuracy = accuracy; BaseUsages = baseUsages; Target = target; Priority = priority; SecondaryEffect = secondaryEffect; _flags = [..flags]; } /// <inheritdoc /> public StringKey Name { get; } /// <inheritdoc /> public TypeIdentifier MoveType { get; } /// <inheritdoc /> public MoveCategory Category { get; } /// <inheritdoc /> public byte BasePower { get; } /// <inheritdoc /> public byte Accuracy { get; } /// <inheritdoc /> public byte BaseUsages { get; } /// <inheritdoc /> public MoveTarget Target { get; } /// <inheritdoc /> public sbyte Priority { get; } /// <inheritdoc /> public ISecondaryEffect? SecondaryEffect { get; } private readonly ImmutableHashSet<StringKey> _flags; /// <inheritdoc /> public bool HasFlag(string key) => _flags.Contains(key); }