diff --git a/PkmnLib.Dynamic/AI/PokemonAI.cs b/PkmnLib.Dynamic/AI/PokemonAI.cs
index 40e5f09..fcf6805 100644
--- a/PkmnLib.Dynamic/AI/PokemonAI.cs
+++ b/PkmnLib.Dynamic/AI/PokemonAI.cs
@@ -1,3 +1,4 @@
+using JetBrains.Annotations;
using PkmnLib.Dynamic.Models;
using PkmnLib.Dynamic.Models.Choices;
using PkmnLib.Static.Moves;
@@ -8,12 +9,13 @@ namespace PkmnLib.Dynamic.AI;
///
/// The base class for implementing an AI for Pokémon.
///
+[PublicAPI]
public abstract class PokemonAI
{
///
/// The name of the AI.
///
- public StringKey Name { get; set; }
+ public StringKey Name { get; }
///
protected PokemonAI(StringKey name)
@@ -26,9 +28,11 @@ public abstract class PokemonAI
///
public abstract ITurnChoice GetChoice(IBattle battle, IPokemon pokemon);
+ ///
+ /// For a given user and move, returns the valid targets for that move.
+ ///
public IEnumerable<(byte side, byte position)> GetValidTargetsForMove(IPokemon user, ILearnedMove move)
{
- byte GetOppositeSide(byte side) => side == 0 ? (byte)1 : (byte)0;
var userBattleData = user.BattleData!;
switch (move.MoveData.Target)
{
@@ -90,5 +94,7 @@ public abstract class PokemonAI
default:
throw new ArgumentOutOfRangeException();
}
+ yield break;
+ byte GetOppositeSide(byte side) => side == 0 ? (byte)1 : (byte)0;
}
}
\ No newline at end of file
diff --git a/PkmnLib.Dynamic/Events/CaptureAttemptEvent.cs b/PkmnLib.Dynamic/Events/CaptureAttemptEvent.cs
index 3ceae0a..6ef8d64 100644
--- a/PkmnLib.Dynamic/Events/CaptureAttemptEvent.cs
+++ b/PkmnLib.Dynamic/Events/CaptureAttemptEvent.cs
@@ -3,15 +3,26 @@ using PkmnLib.Dynamic.Models;
namespace PkmnLib.Dynamic.Events;
+///
+/// Represents an event that occurs when a Pokémon capture attempt is made.
+///
public class CaptureAttemptEvent : IEventData
{
+ ///
public CaptureAttemptEvent(IPokemon target, CaptureResult result)
{
Target = target;
Result = result;
}
+ ///
+ /// The Pokémon that is being captured.
+ ///
public IPokemon Target { get; init; }
+
+ ///
+ /// The result of the capture attempt.
+ ///
public CaptureResult Result { get; init; }
///
diff --git a/PkmnLib.Dynamic/Events/DialogEvent.cs b/PkmnLib.Dynamic/Events/DialogEvent.cs
index 7633f9a..fe3fcc8 100644
--- a/PkmnLib.Dynamic/Events/DialogEvent.cs
+++ b/PkmnLib.Dynamic/Events/DialogEvent.cs
@@ -1,17 +1,27 @@
namespace PkmnLib.Dynamic.Events;
+///
+/// Represents an event that occurs when a dialog is displayed.
+///
public class DialogEvent : IEventData
{
///
public EventBatchId BatchId { get; init; } = new();
+ ///
public DialogEvent(string message, Dictionary? parameters = null)
{
Message = message;
Parameters = parameters;
}
+ ///
+ /// The message to be displayed in the dialog. This is generally a key that needs to be localized.
+ ///
public string Message { get; set; }
+ ///
+ /// Optional parameters that can be used to format the message in a localized string.
+ ///
public Dictionary? Parameters { get; set; }
}
\ No newline at end of file
diff --git a/PkmnLib.Dynamic/Events/ExperienceGainEvent.cs b/PkmnLib.Dynamic/Events/ExperienceGainEvent.cs
index 7094430..09e2b77 100644
--- a/PkmnLib.Dynamic/Events/ExperienceGainEvent.cs
+++ b/PkmnLib.Dynamic/Events/ExperienceGainEvent.cs
@@ -2,8 +2,12 @@ using PkmnLib.Dynamic.Models;
namespace PkmnLib.Dynamic.Events;
+///
+/// Represents an event that occurs when a Pokémon gains experience.
+///
public class ExperienceGainEvent : IEventData
{
+ ///
public ExperienceGainEvent(IPokemon pokemon, uint previousExperience, uint newExperience)
{
Pokemon = pokemon;
@@ -11,8 +15,19 @@ public class ExperienceGainEvent : IEventData
NewExperience = newExperience;
}
+ ///
+ /// The Pokémon that gained experience.
+ ///
public IPokemon Pokemon { get; set; }
+
+ ///
+ /// The amount of experience the Pokémon had before the gain.
+ ///
public uint PreviousExperience { get; }
+
+ ///
+ /// The amount of experience the Pokémon has after the gain.
+ ///
public uint NewExperience { get; }
///
diff --git a/PkmnLib.Dynamic/Events/FormChangeEvent.cs b/PkmnLib.Dynamic/Events/FormChangeEvent.cs
index bd90f0b..f11dddb 100644
--- a/PkmnLib.Dynamic/Events/FormChangeEvent.cs
+++ b/PkmnLib.Dynamic/Events/FormChangeEvent.cs
@@ -3,11 +3,22 @@ using PkmnLib.Static.Species;
namespace PkmnLib.Dynamic.Events;
+///
+/// Represents an event that occurs when a Pokémon changes its form.
+///
public class FormChangeEvent : IEventData
{
+ ///
+ /// The Pokémon that changed its form.
+ ///
public IPokemon Pokemon { get; }
+
+ ///
+ /// The new form of the Pokémon.
+ ///
public IForm Form { get; }
+ ///
public FormChangeEvent(IPokemon pokemon, IForm form)
{
Pokemon = pokemon;
diff --git a/PkmnLib.Dynamic/Events/Handling/EventBatchId.cs b/PkmnLib.Dynamic/Events/Handling/EventBatchId.cs
index ceb6b7c..22b9a41 100644
--- a/PkmnLib.Dynamic/Events/Handling/EventBatchId.cs
+++ b/PkmnLib.Dynamic/Events/Handling/EventBatchId.cs
@@ -10,6 +10,7 @@ namespace PkmnLib.Dynamic.Events;
///
public readonly record struct EventBatchId
{
+ ///
public EventBatchId()
{
Id = Guid.NewGuid();
diff --git a/PkmnLib.Dynamic/Events/Handling/EventData.cs b/PkmnLib.Dynamic/Events/Handling/EventData.cs
index 76ca0c0..4062393 100644
--- a/PkmnLib.Dynamic/Events/Handling/EventData.cs
+++ b/PkmnLib.Dynamic/Events/Handling/EventData.cs
@@ -1,3 +1,5 @@
+using JetBrains.Annotations;
+
namespace PkmnLib.Dynamic.Events;
///
@@ -5,6 +7,7 @@ namespace PkmnLib.Dynamic.Events;
/// display information about the battle to the user. This is the only way for the front-end to
/// know what is happening in the battle.
///
+[PublicAPI]
public interface IEventData
{
///
diff --git a/PkmnLib.Dynamic/Events/LevelUpEvent.cs b/PkmnLib.Dynamic/Events/LevelUpEvent.cs
index 62e6267..0106ff6 100644
--- a/PkmnLib.Dynamic/Events/LevelUpEvent.cs
+++ b/PkmnLib.Dynamic/Events/LevelUpEvent.cs
@@ -2,8 +2,12 @@ using PkmnLib.Dynamic.Models;
namespace PkmnLib.Dynamic.Events;
+///
+/// Represents an event that occurs when a Pokémon gains enough experience points to level up.
+///
public class LevelUpEvent : IEventData
{
+ ///
public LevelUpEvent(IPokemon pokemon, int previousLevel, int newLevel)
{
Pokemon = pokemon;
@@ -11,10 +15,19 @@ public class LevelUpEvent : IEventData
NewLevel = newLevel;
}
+ ///
+ /// The new level of the Pokémon after leveling up.
+ ///
public int NewLevel { get; set; }
+ ///
+ /// The previous level of the Pokémon before leveling up.
+ ///
public int PreviousLevel { get; set; }
+ ///
+ /// The Pokémon that leveled up.
+ ///
public IPokemon Pokemon { get; set; }
///
diff --git a/PkmnLib.Dynamic/Events/SpeciesChangeEvent.cs b/PkmnLib.Dynamic/Events/SpeciesChangeEvent.cs
index 4307cbf..504a17e 100644
--- a/PkmnLib.Dynamic/Events/SpeciesChangeEvent.cs
+++ b/PkmnLib.Dynamic/Events/SpeciesChangeEvent.cs
@@ -3,12 +3,27 @@ using PkmnLib.Static.Species;
namespace PkmnLib.Dynamic.Events;
+///
+/// Represents an event that occurs when a Pokémon changes to a different species.
+///
public class SpeciesChangeEvent : IEventData
{
+ ///
+ /// The Pokémon that changed species.
+ ///
public IPokemon Pokemon { get; }
+
+ ///
+ /// The new species of the Pokémon.
+ ///
public ISpecies Species { get; }
+
+ ///
+ /// The new form of the Pokémon, if applicable.
+ ///
public IForm Form { get; }
+ ///
public SpeciesChangeEvent(IPokemon pokemon, ISpecies species, IForm form)
{
Pokemon = pokemon;
diff --git a/PkmnLib.Dynamic/Libraries/CaptureLibrary.cs b/PkmnLib.Dynamic/Libraries/CaptureLibrary.cs
index fcb045d..c575899 100644
--- a/PkmnLib.Dynamic/Libraries/CaptureLibrary.cs
+++ b/PkmnLib.Dynamic/Libraries/CaptureLibrary.cs
@@ -3,8 +3,12 @@ using PkmnLib.Static;
namespace PkmnLib.Dynamic.Libraries;
+///
+/// Represents the result of a capture attempt.
+///
public record struct CaptureResult
{
+ ///
public CaptureResult(bool IsCaught, int Shakes, bool CriticalCapture)
{
this.IsCaught = IsCaught;
@@ -12,14 +16,35 @@ public record struct CaptureResult
this.CriticalCapture = CriticalCapture;
}
+ ///
+ /// Indicates whether the capture was successful.
+ ///
public bool IsCaught { get; init; }
+
+ ///
+ /// The number of shakes the Poké Ball made before the capture attempt was successful or failed.
+ ///
public int Shakes { get; init; }
+
+ ///
+ /// Indicates whether a critical capture occurred. A critical capture is a special case where the Poké Ball
+ /// shakes only once and then captures the Pokémon.
+ ///
public bool CriticalCapture { get; init; }
+ ///
+ /// Creates a indicating a failed capture attempt.
+ ///
public static CaptureResult Failed => new(false, 0, false);
}
+///
+/// Interface for a library that handles Pokémon capture mechanics.
+///
public interface ICaptureLibrary
{
+ ///
+ /// Attempts to capture a Pokémon using a specified item (e.g., Poké Ball).
+ ///
CaptureResult TryCapture(IPokemon target, IItem captureItem, IBattleRandom random);
}
\ No newline at end of file
diff --git a/PkmnLib.Dynamic/Libraries/MiscLibrary.cs b/PkmnLib.Dynamic/Libraries/MiscLibrary.cs
index 7549d4b..aa433f1 100644
--- a/PkmnLib.Dynamic/Libraries/MiscLibrary.cs
+++ b/PkmnLib.Dynamic/Libraries/MiscLibrary.cs
@@ -20,5 +20,8 @@ public interface IMiscLibrary
///
TimeOfDay GetTimeOfDay();
+ ///
+ /// Returns whether the given Pokemon can flee from the battle.
+ ///
bool CanFlee(IBattle battle, IFleeChoice fleeChoice);
}
\ No newline at end of file
diff --git a/PkmnLib.Dynamic/Models/Battle.cs b/PkmnLib.Dynamic/Models/Battle.cs
index ba7db5a..bfc83a6 100644
--- a/PkmnLib.Dynamic/Models/Battle.cs
+++ b/PkmnLib.Dynamic/Models/Battle.cs
@@ -93,6 +93,10 @@ public interface IBattle : IScriptSource, IDeepCloneable
///
void ValidateBattleState();
+ ///
+ /// Checks whether a Pokemon has a forced turn choice. If it does, this returns true and the choice
+ /// is set in the out parameter. If it does not, this returns false and the out parameter is null.
+ ///
bool HasForcedTurn(IPokemon pokemon, [NotNullWhen(true)] out ITurnChoice? choice);
///
@@ -117,6 +121,9 @@ public interface IBattle : IScriptSource, IDeepCloneable
///
bool SetWeather(StringKey? weatherName, int duration);
+ ///
+ /// Volatile scripts are scripts that are not permanent and can be removed by other scripts.
+ ///
public IScriptSet Volatile { get; }
///
@@ -124,8 +131,15 @@ public interface IBattle : IScriptSource, IDeepCloneable
///
StringKey? WeatherName { get; }
+ ///
+ /// Sets the current terrain for the battle. If null is passed, this clears the terrain.
+ ///
+ ///
void SetTerrain(StringKey? terrainName);
+ ///
+ /// Gets the current terrain of the battle. If no terrain is present, this returns null.
+ ///
StringKey? TerrainName { get; }
///
@@ -134,6 +148,9 @@ public interface IBattle : IScriptSource, IDeepCloneable
///
IReadOnlyList> PreviousTurnChoices { get; }
+ ///
+ /// Attempts to capture a Pokemon. This will use the current RNG to determine whether the capture is successful.
+ ///
CaptureResult AttempCapture(byte sideIndex, byte position, IItem item);
}
@@ -350,7 +367,11 @@ public class BattleImpl : ScriptSource, IBattle
EventHook.Invoke(new EndTurnEvent());
}
- private ScriptContainer _weatherScript = new();
+ private readonly ScriptContainer _weatherScript = new();
+
+ ///
+ /// The script that handles the current weather of the battle.
+ ///
public IReadOnlyScriptContainer WeatherScript => _weatherScript;
///
@@ -377,6 +398,7 @@ public class BattleImpl : ScriptSource, IBattle
// TODO: Trigger weather change script hooks
}
+ ///
public IScriptSet Volatile { get; } = new ScriptSet();
///
diff --git a/PkmnLib.Dynamic/Models/BattleChoiceQueue.cs b/PkmnLib.Dynamic/Models/BattleChoiceQueue.cs
index 7ea9b9f..bdbf276 100644
--- a/PkmnLib.Dynamic/Models/BattleChoiceQueue.cs
+++ b/PkmnLib.Dynamic/Models/BattleChoiceQueue.cs
@@ -16,6 +16,10 @@ public class BattleChoiceQueue : IDeepCloneable
{
private readonly ITurnChoice?[] _choices;
private int _currentIndex;
+
+ ///
+ /// Returns the last choice that was executed.
+ ///
public ITurnChoice? LastRanChoice { get; private set; }
///
@@ -122,9 +126,15 @@ public class BattleChoiceQueue : IDeepCloneable
internal IReadOnlyList GetChoices() => _choices;
+ ///
+ /// This returns the first choice that matches the predicate, or null if none was found.
+ ///
public ITurnChoice? FirstOrDefault(Func predicate) =>
_choices.Skip(_currentIndex).WhereNotNull().FirstOrDefault(predicate);
+ ///
+ /// Removes a choice from the queue.
+ ///
public void Remove(ITurnChoice choice)
{
var index = Array.FindIndex(_choices, _currentIndex, x => x == choice);
diff --git a/PkmnLib.Dynamic/Models/BattleRandom.cs b/PkmnLib.Dynamic/Models/BattleRandom.cs
index ff7cca7..c1c840c 100644
--- a/PkmnLib.Dynamic/Models/BattleRandom.cs
+++ b/PkmnLib.Dynamic/Models/BattleRandom.cs
@@ -19,10 +19,18 @@ public interface IBattleRandom : IRandom, IDeepCloneable
///
public class BattleRandomImpl : RandomImpl, IBattleRandom
{
+ ///
+ ///
+ /// This constructor is used to instantiate the class when no seed is provided. It uses a time-dependent default seed value.
+ ///
public BattleRandomImpl()
{
}
+ ///
+ ///
+ /// This constructor is used to instantiate the class with a specific seed value.
+ ///
public BattleRandomImpl(int seed) : base(seed)
{
}
diff --git a/PkmnLib.Dynamic/Models/BattleSide.cs b/PkmnLib.Dynamic/Models/BattleSide.cs
index a3365b1..d975487 100644
--- a/PkmnLib.Dynamic/Models/BattleSide.cs
+++ b/PkmnLib.Dynamic/Models/BattleSide.cs
@@ -142,9 +142,19 @@ public interface IBattleSide : IScriptSource, IDeepCloneable
///
IItem? GetLastConsumedItem(byte battleDataPosition);
+ ///
+ /// Marks a Pokémon as fainted. This is used to track the last turn a Pokémon in a position fainted.
+ ///
void MarkFaint(byte position);
+ ///
+ /// Gets the last turn a Pokémon in a specific position fainted.
+ ///
uint? GetLastFaintTurn(byte position);
+
+ ///
+ /// Gets the last turn a Pokémon in any position fainted.
+ ///
uint? GetLastFaintTurn();
}
diff --git a/PkmnLib.Dynamic/Models/Choices/ItemChoice.cs b/PkmnLib.Dynamic/Models/Choices/ItemChoice.cs
index e7634e5..e4ff6da 100644
--- a/PkmnLib.Dynamic/Models/Choices/ItemChoice.cs
+++ b/PkmnLib.Dynamic/Models/Choices/ItemChoice.cs
@@ -27,6 +27,7 @@ public interface IItemChoice : ITurnChoice
///
public class ItemChoice : TurnChoice, IItemChoice
{
+ ///
public ItemChoice(IPokemon user, IItem item, byte? targetSide, byte? targetPosition) : base(user)
{
Item = item;
@@ -34,6 +35,9 @@ public class ItemChoice : TurnChoice, IItemChoice
TargetPosition = targetPosition;
}
+ ///
+ /// The item that is used.
+ ///
public IItem Item { get; }
///
diff --git a/PkmnLib.Dynamic/Models/Choices/PassChoice.cs b/PkmnLib.Dynamic/Models/Choices/PassChoice.cs
index ec99f0c..5290fd3 100644
--- a/PkmnLib.Dynamic/Models/Choices/PassChoice.cs
+++ b/PkmnLib.Dynamic/Models/Choices/PassChoice.cs
@@ -9,8 +9,10 @@ public interface IPassChoice : ITurnChoice
{
}
+///
public class PassChoice : TurnChoice, IPassChoice
{
+ ///
public PassChoice(IPokemon user) : base(user)
{
}
diff --git a/PkmnLib.Dynamic/Models/Choices/SwitchChoice.cs b/PkmnLib.Dynamic/Models/Choices/SwitchChoice.cs
index 02bfdad..538aaf0 100644
--- a/PkmnLib.Dynamic/Models/Choices/SwitchChoice.cs
+++ b/PkmnLib.Dynamic/Models/Choices/SwitchChoice.cs
@@ -16,6 +16,7 @@ public interface ISwitchChoice : ITurnChoice
///
public class SwitchChoice : TurnChoice, ISwitchChoice
{
+ ///
public SwitchChoice(IPokemon user, IPokemon switchTo) : base(user)
{
SwitchTo = switchTo;
diff --git a/PkmnLib.Dynamic/Models/ExecutingMove.cs b/PkmnLib.Dynamic/Models/ExecutingMove.cs
index e440021..757bb03 100644
--- a/PkmnLib.Dynamic/Models/ExecutingMove.cs
+++ b/PkmnLib.Dynamic/Models/ExecutingMove.cs
@@ -140,8 +140,14 @@ public interface IExecutingMove : IScriptSource
///
IMoveChoice MoveChoice { get; }
+ ///
+ /// Returns all the hits of this move.
+ ///
IReadOnlyList Hits { get; }
+ ///
+ /// The battle this move is being executed in.
+ ///
IBattle Battle { get; }
}
@@ -189,6 +195,9 @@ public class ExecutingMoveImpl : ScriptSource, IExecutingMove
///
public ScriptContainer Script => MoveChoice.Script;
+ ///
+ /// The volatile scripts that are applicable to this move.
+ ///
public IScriptSet Volatile => MoveChoice.Volatile;
///
diff --git a/PkmnLib.Dynamic/Models/LearnedMove.cs b/PkmnLib.Dynamic/Models/LearnedMove.cs
index 74637cb..49423a9 100644
--- a/PkmnLib.Dynamic/Models/LearnedMove.cs
+++ b/PkmnLib.Dynamic/Models/LearnedMove.cs
@@ -101,6 +101,7 @@ public class LearnedMoveImpl : ILearnedMove
CurrentPp = MaxPp;
}
+ ///
public LearnedMoveImpl(IMoveData moveData, MoveLearnMethod learnMethod, byte pp) : this(moveData, learnMethod)
{
CurrentPp = pp;
diff --git a/PkmnLib.Dynamic/Models/Pokemon.cs b/PkmnLib.Dynamic/Models/Pokemon.cs
index e96e8cf..d851011 100644
--- a/PkmnLib.Dynamic/Models/Pokemon.cs
+++ b/PkmnLib.Dynamic/Models/Pokemon.cs
@@ -202,6 +202,9 @@ public interface IPokemon : IScriptSource, IDeepCloneable
///
bool IsCaught { get; }
+ ///
+ /// Marks the Pokemon as caught. This makes it so that the Pokemon is not considered valid in battle anymore.
+ ///
public void MarkAsCaught();
///
@@ -395,6 +398,9 @@ public interface IPokemon : IScriptSource, IDeepCloneable
///
void SetTypes(IReadOnlyList types);
+ ///
+ /// Changes the ability of the Pokémon.
+ ///
void ChangeAbility(IAbility ability);
///
@@ -449,8 +455,14 @@ public interface IPokemonBattleData : IDeepCloneable
///
void MarkItemAsConsumed(IItem item);
+ ///
+ /// The turn the Pokémon switched in.
+ ///
uint SwitchInTurn { get; internal set; }
+ ///
+ /// The side the Pokémon is on.
+ ///
IBattleSide BattleSide { get; }
}
@@ -483,6 +495,7 @@ public class PokemonImpl : ScriptSource, IPokemon
CurrentHealth = BoostedStats.Hp;
}
+ ///
public PokemonImpl(IDynamicLibrary library, SerializedPokemon serializedPokemon)
{
Library = library;
diff --git a/PkmnLib.Dynamic/Models/PokemonParty.cs b/PkmnLib.Dynamic/Models/PokemonParty.cs
index def8511..13b903b 100644
--- a/PkmnLib.Dynamic/Models/PokemonParty.cs
+++ b/PkmnLib.Dynamic/Models/PokemonParty.cs
@@ -8,7 +8,14 @@ namespace PkmnLib.Dynamic.Models;
///
public interface IPokemonParty : IReadOnlyList, IDeepCloneable
{
+ ///
+ /// Event that is triggered when a Pokemon is swapped into the party.
+ ///
event EventHandler<(IPokemon?, int index)>? OnSwapInto;
+
+ ///
+ /// Event that is triggered when two Pokemon are swapped in the party.
+ ///
event EventHandler<(int index1, int index2)>? OnSwap;
///
diff --git a/PkmnLib.Dynamic/Models/Serialized/SerializedPokemon.cs b/PkmnLib.Dynamic/Models/Serialized/SerializedPokemon.cs
index c814ee2..5743e6d 100644
--- a/PkmnLib.Dynamic/Models/Serialized/SerializedPokemon.cs
+++ b/PkmnLib.Dynamic/Models/Serialized/SerializedPokemon.cs
@@ -129,22 +129,23 @@ public record SerializedLearnedMove
public required byte CurrentPp { get; set; }
}
+///
+/// A serialized stats is a representation of a Pokémon's stats that can be easily serialized and deserialized.
+///
public record SerializedStats
{
+ ///
public SerializedStats()
{
}
- public SerializedStats(ImmutableStatisticSet stats)
+ ///
+ public SerializedStats(ImmutableStatisticSet stats) : this(stats.Hp, stats.Attack, stats.Defense,
+ stats.SpecialAttack, stats.SpecialDefense, stats.Speed)
{
- Hp = stats.Hp;
- Attack = stats.Attack;
- Defense = stats.Defense;
- SpecialAttack = stats.SpecialAttack;
- SpecialDefense = stats.SpecialDefense;
- Speed = stats.Speed;
}
+ ///
public SerializedStats(long hp, long attack, long defense, long specialAttack, long specialDefense, long speed)
{
Hp = hp;
@@ -155,13 +156,39 @@ public record SerializedStats
Speed = speed;
}
+ ///
+ /// The health points stat value.
+ ///
public long Hp { get; set; }
+
+ ///
+ /// The physical attack stat value.
+ ///
public long Attack { get; set; }
+
+ ///
+ /// The physical defense stat value.
+ ///
public long Defense { get; set; }
+
+ ///
+ /// The special attack stat value.
+ ///
public long SpecialAttack { get; set; }
+
+ ///
+ /// The special defense stat value.
+ ///
public long SpecialDefense { get; set; }
+
+ ///
+ /// The speed stat value.
+ ///
public long Speed { get; set; }
+ ///
+ /// Converts the serialized stats to an .
+ ///
public IndividualValueStatisticSet ToIndividualValueStatisticSet()
{
if (Hp < 0 || Attack < 0 || Defense < 0 || SpecialAttack < 0 || SpecialDefense < 0 || Speed < 0)
@@ -174,6 +201,10 @@ public record SerializedStats
(byte)SpecialDefense, (byte)Speed);
}
+ ///
+ /// Converts the serialized stats to an .
+ ///
+ ///
public EffortValueStatisticSet ToEffortValueStatisticSet()
{
if (Hp < 0 || Attack < 0 || Defense < 0 || SpecialAttack < 0 || SpecialDefense < 0 || Speed < 0)
diff --git a/PkmnLib.Dynamic/ScriptHandling/IWeatherScript.cs b/PkmnLib.Dynamic/ScriptHandling/IWeatherScript.cs
index a701b30..4d2e9da 100644
--- a/PkmnLib.Dynamic/ScriptHandling/IWeatherScript.cs
+++ b/PkmnLib.Dynamic/ScriptHandling/IWeatherScript.cs
@@ -1,6 +1,12 @@
namespace PkmnLib.Dynamic.ScriptHandling;
+///
+/// Helper interface for weather scripts.
+///
public interface IWeatherScript
{
+ ///
+ /// Sets the number of turns the weather will last.
+ ///
public void SetTurns(int turns);
}
\ No newline at end of file
diff --git a/PkmnLib.Dynamic/ScriptHandling/ItemScript.cs b/PkmnLib.Dynamic/ScriptHandling/ItemScript.cs
index 1ab921c..f5639e9 100644
--- a/PkmnLib.Dynamic/ScriptHandling/ItemScript.cs
+++ b/PkmnLib.Dynamic/ScriptHandling/ItemScript.cs
@@ -4,13 +4,20 @@ using PkmnLib.Static.Utils;
namespace PkmnLib.Dynamic.ScriptHandling;
+///
+/// Base class for item scripts.
+///
public abstract class ItemScript : IDeepCloneable
{
+ ///
protected ItemScript(IItem item)
{
Item = item;
}
+ ///
+ /// The item associated with this script.
+ ///
protected IItem Item { get; private set; }
///
diff --git a/PkmnLib.Dynamic/ScriptHandling/PokeballScript.cs b/PkmnLib.Dynamic/ScriptHandling/PokeballScript.cs
index e697434..dae0942 100644
--- a/PkmnLib.Dynamic/ScriptHandling/PokeballScript.cs
+++ b/PkmnLib.Dynamic/ScriptHandling/PokeballScript.cs
@@ -3,6 +3,9 @@ using PkmnLib.Static;
namespace PkmnLib.Dynamic.ScriptHandling;
+///
+/// Base class for Pokéball scripts.
+///
public abstract class PokeballScript : ItemScript
{
///
@@ -10,6 +13,9 @@ public abstract class PokeballScript : ItemScript
{
}
+ ///
+ /// Returns the catch rate of the Pokéball against the given target Pokémon.
+ ///
public abstract byte GetCatchRate(IPokemon target);
///
diff --git a/PkmnLib.Dynamic/ScriptHandling/Registry/ItemScriptAttribute.cs b/PkmnLib.Dynamic/ScriptHandling/Registry/ItemScriptAttribute.cs
index 118c18b..a8f3519 100644
--- a/PkmnLib.Dynamic/ScriptHandling/Registry/ItemScriptAttribute.cs
+++ b/PkmnLib.Dynamic/ScriptHandling/Registry/ItemScriptAttribute.cs
@@ -3,6 +3,9 @@ using PkmnLib.Static.Utils;
namespace PkmnLib.Dynamic.ScriptHandling.Registry;
+///
+/// Attribute to mark a class as an item script.
+///
[AttributeUsage(AttributeTargets.Class), MeansImplicitUse]
public class ItemScriptAttribute : Attribute
{
diff --git a/PkmnLib.Dynamic/ScriptHandling/Registry/Plugin.cs b/PkmnLib.Dynamic/ScriptHandling/Registry/Plugin.cs
index f1b60d5..2508269 100644
--- a/PkmnLib.Dynamic/ScriptHandling/Registry/Plugin.cs
+++ b/PkmnLib.Dynamic/ScriptHandling/Registry/Plugin.cs
@@ -8,10 +8,12 @@ namespace PkmnLib.Dynamic.ScriptHandling.Registry;
[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)]
public abstract class Plugin
{
+ ///
protected Plugin()
{
}
+ ///
protected Plugin(PluginConfiguration configuration)
{
}
@@ -33,6 +35,9 @@ public abstract class Plugin
public abstract void Register(ScriptRegistry registry);
}
+///
+/// Base class for plugin configuration.
+///
public abstract class PluginConfiguration
{
}
\ No newline at end of file
diff --git a/PkmnLib.Dynamic/ScriptHandling/Script.cs b/PkmnLib.Dynamic/ScriptHandling/Script.cs
index 4419f53..924a9ab 100644
--- a/PkmnLib.Dynamic/ScriptHandling/Script.cs
+++ b/PkmnLib.Dynamic/ScriptHandling/Script.cs
@@ -18,6 +18,9 @@ public abstract class Script : IDeepCloneable
private int _suppressCount;
+ ///
+ /// Remove the script from its owner.
+ ///
public void RemoveSelf()
{
OnRemoveEvent?.Invoke(this);
@@ -62,6 +65,10 @@ public abstract class Script : IDeepCloneable
///
public void Unsuppress() => _suppressCount--;
+ ///
+ /// This function is ran before any hook is invoked. This allows for suppressing certain categories
+ /// of scripts. This is useful for example to prevent certain effects from running.
+ ///
public virtual void OnBeforeAnyHookInvoked(ref List? suppressedCategories)
{
}
@@ -95,6 +102,10 @@ public abstract class Script : IDeepCloneable
{
}
+ ///
+ /// Force a certain move choice to be selected. If the choice is set, the Pokemon will be forced
+ /// to use it, and will not be able to select any other choice.
+ ///
public virtual void ForceTurnSelection(byte sideIndex, byte position, ref ITurnChoice? choice)
{
}
@@ -140,6 +151,9 @@ public abstract class Script : IDeepCloneable
{
}
+ ///
+ /// This function allows you to change the targets of a move choice before the move starts.
+ ///
public virtual void ChangeIncomingTargets(IMoveChoice moveChoice, ref IReadOnlyList targets)
{
}
@@ -230,6 +244,9 @@ public abstract class Script : IDeepCloneable
{
}
+ ///
+ /// This function allows the script to override how effective a move is on a target.
+ ///
public virtual void ChangeIncomingEffectiveness(IExecutingMove executingMove, IPokemon target, byte hitIndex,
ref float effectiveness)
{
@@ -504,6 +521,10 @@ public abstract class Script : IDeepCloneable
{
}
+ ///
+ /// This function is triggered on a Pokemon and its parents when the given Pokemon switches out
+ /// of the battlefield.
+ ///
public virtual void OnSwitchOut(IPokemon oldPokemon, byte position)
{
}
@@ -559,10 +580,16 @@ public abstract class Script : IDeepCloneable
{
}
+ ///
+ /// This function allows a script to block an incoming hit.
+ ///
public virtual void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
{
}
+ ///
+ /// This function allows a script to block an outgoing hit.
+ ///
public virtual void BlockOutgoingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
{
}
@@ -582,23 +609,44 @@ public abstract class Script : IDeepCloneable
{
}
+ ///
+ /// This function allows a script to prevent a held item from being consumed.
+ ///
public virtual void PreventHeldItemConsume(IPokemon pokemon, IItem heldItem, ref bool prevented)
{
}
+ ///
+ /// This function allows a script to change any kind of damage that is incoming.
+ ///
public virtual void ChangeIncomingDamage(IPokemon pokemon, DamageSource source, ref uint damage)
{
}
+ ///
+ /// This function allows a script to change the accuracy of a move used. The value for accuracy is in percentage.
+ /// A custom case goes when 255 is returned, in which case the entire accuracy check is skipped, and the move
+ /// will always hit.
+ ///
+ ///
+ ///
+ ///
+ ///
public virtual void ChangeAccuracy(IExecutingMove executingMove, IPokemon target, byte hitIndex,
ref int modifiedAccuracy)
{
}
+ ///
+ /// This function allows a script to change the weather duration of a weather effect.
+ ///
public virtual void ChangeWeatherDuration(StringKey weatherName, ref int duration)
{
}
+ ///
+ /// This function allows a script to prevent a Pokemon from being healed.
+ ///
public virtual void PreventHeal(IPokemon pokemon, uint heal, bool allowRevive, ref bool prevented)
{
}
diff --git a/PkmnLib.Dynamic/ScriptHandling/ScriptCategory.cs b/PkmnLib.Dynamic/ScriptHandling/ScriptCategory.cs
index 7003919..22755ab 100644
--- a/PkmnLib.Dynamic/ScriptHandling/ScriptCategory.cs
+++ b/PkmnLib.Dynamic/ScriptHandling/ScriptCategory.cs
@@ -55,6 +55,9 @@ public enum ScriptCategory
///
Weather = 7,
+ ///
+ /// A special script for terrain, for use on battles.
+ ///
Terrain = 8,
///
diff --git a/PkmnLib.Dynamic/ScriptHandling/ScriptContainer.cs b/PkmnLib.Dynamic/ScriptHandling/ScriptContainer.cs
index f20e213..7500809 100644
--- a/PkmnLib.Dynamic/ScriptHandling/ScriptContainer.cs
+++ b/PkmnLib.Dynamic/ScriptHandling/ScriptContainer.cs
@@ -4,6 +4,10 @@ using PkmnLib.Static.Utils;
namespace PkmnLib.Dynamic.ScriptHandling;
+///
+/// A holder class for a script. This is used so we can cache a list of these, and iterate over them, even when
+/// the underlying script changes.
+///
public interface IReadOnlyScriptContainer : IEnumerable, IDeepCloneable
{
///
@@ -17,10 +21,7 @@ public interface IReadOnlyScriptContainer : IEnumerable, IDeepC
public Script? Script { get; }
}
-///
-/// A holder class for a script. This is used so we can cache a list of these, and iterate over them, even when
-/// the underlying script changes.
-///
+///
public class ScriptContainer : IReadOnlyScriptContainer
{
///
@@ -73,6 +74,11 @@ public class ScriptContainer : IReadOnlyScriptContainer
return script;
}
+ ///
+ /// Removes the script from this container, but does not call .
+ /// Be very careful with this, as it can lead to unexpected behavior. An example of a valid use is Baton-Pass,
+ /// where scripts are being removed to be added to another Pokemon, so we want them to remain active.
+ ///
public void ClearWithoutRemoving()
{
Script = null;
diff --git a/PkmnLib.Dynamic/ScriptHandling/ScriptExecution.cs b/PkmnLib.Dynamic/ScriptHandling/ScriptExecution.cs
index 0ef88a4..06154d8 100644
--- a/PkmnLib.Dynamic/ScriptHandling/ScriptExecution.cs
+++ b/PkmnLib.Dynamic/ScriptHandling/ScriptExecution.cs
@@ -64,6 +64,9 @@ public static class ScriptExecution
}
}
+ ///
+ /// Executes a script on an item.
+ ///
public static void RunItemScript(this IItem item, ScriptResolver scriptResolver, IPokemon? target)
{
if (!scriptResolver.TryResolveBattleItemScript(item, out var itemScript))
diff --git a/PkmnLib.Static/Item.cs b/PkmnLib.Static/Item.cs
index a8b1115..57b5f3e 100644
--- a/PkmnLib.Static/Item.cs
+++ b/PkmnLib.Static/Item.cs
@@ -106,11 +106,25 @@ public interface IItem : INamedValue
///
ImmutableHashSet Flags { get; }
+ ///
+ /// The effect of the item when used outside of battle.
+ ///
ISecondaryEffect? Effect { get; }
+
+ ///
+ /// The effect of the item when used in battle.
+ ///
ISecondaryEffect? BattleEffect { get; }
+ ///
+ /// A set of arbitrary data that can be set on the item.
+ ///
IReadOnlyDictionary AdditionalData { get; }
+ ///
+ /// Tries to get additional data from the item. If the data is not present, the value will be null.
+ /// If the data is present, but cannot be converted to the requested type, the value will be null.
+ ///
bool TryGetAdditionalData(StringKey key, out T? value);
///
diff --git a/PkmnLib.Static/Libraries/TypeLibrary.cs b/PkmnLib.Static/Libraries/TypeLibrary.cs
index a67e7b9..85c924d 100644
--- a/PkmnLib.Static/Libraries/TypeLibrary.cs
+++ b/PkmnLib.Static/Libraries/TypeLibrary.cs
@@ -28,6 +28,9 @@ public interface IReadOnlyTypeLibrary
///
float GetEffectiveness(TypeIdentifier attacking, IEnumerable defending);
+ ///
+ /// Gets the effectiveness for a single attacking type against all defending types.
+ ///
IEnumerable<(TypeIdentifier type, float effectiveness)> GetAllEffectivenessFromAttacking(TypeIdentifier attacking);
}
diff --git a/PkmnLib.Static/Species/Ability.cs b/PkmnLib.Static/Species/Ability.cs
index 63aac23..eb40b39 100644
--- a/PkmnLib.Static/Species/Ability.cs
+++ b/PkmnLib.Static/Species/Ability.cs
@@ -19,6 +19,9 @@ public interface IAbility : INamedValue
///
IReadOnlyDictionary Parameters { get; }
+ ///
+ /// Checks whether the ability has a specific flag.
+ ///
bool HasFlag(StringKey key);
}
@@ -44,6 +47,9 @@ public class AbilityImpl : IAbility
///
public IReadOnlyDictionary Parameters { get; }
+ ///
+ /// A collection of arbitrary flags that can be used to mark the ability with specific properties.
+ ///
public ImmutableHashSet Flags;
///
diff --git a/PkmnLib.Static/StatisticSet.cs b/PkmnLib.Static/StatisticSet.cs
index fc81dc7..0cc188c 100644
--- a/PkmnLib.Static/StatisticSet.cs
+++ b/PkmnLib.Static/StatisticSet.cs
@@ -51,6 +51,7 @@ public record ImmutableStatisticSet where T : struct
Speed = speed;
}
+ ///
public ImmutableStatisticSet(ImmutableStatisticSet set)
{
Hp = set.Hp;
@@ -97,6 +98,7 @@ public record StatisticSet : ImmutableStatisticSet, IEnumerable<(Statistic
{
}
+ ///
public StatisticSet(StatisticSet set) : base(set)
{
}
@@ -174,8 +176,16 @@ public record StatisticSet : ImmutableStatisticSet, IEnumerable<(Statistic
return true;
}
+ ///
+ /// Gets a statistic that is not one of the standard statistics. This can be used for sets where there are
+ /// additional statistics, such as evasion or accuracy.
+ ///
protected virtual T GetUnknownStat(Statistic stat) => throw new ArgumentException($"Invalid statistic {stat}");
+ ///
+ /// Sets a statistic that is not one of the standard statistics. This can be used for sets where there are
+ /// additional statistics, such as evasion or accuracy.
+ ///
protected virtual void SetUnknownStat(Statistic stat, T value)
{
throw new ArgumentException($"Invalid statistic {stat}");
@@ -249,10 +259,14 @@ public abstract record ClampedStatisticSet : StatisticSet where T : struct
Speed = Clamp(Speed, Min, Max);
}
+ ///
protected ClampedStatisticSet(ClampedStatisticSet set) : base(set)
{
}
+ ///
+ /// Clamps a value to be between the minimum and maximum values.
+ ///
protected static T Clamp(T value, T min, T max)
{
if (value.CompareTo(min) < 0)
@@ -314,6 +328,9 @@ public record StatBoostStatisticSet : ClampedStatisticSet
private sbyte _evasion;
+ ///
+ /// The evasion stat value.
+ ///
public sbyte Evasion
{
get => _evasion;
@@ -322,6 +339,9 @@ public record StatBoostStatisticSet : ClampedStatisticSet
private sbyte _accuracy;
+ ///
+ /// The accuracy stat value.
+ ///
public sbyte Accuracy
{
get => _accuracy;
@@ -403,6 +423,7 @@ public record IndividualValueStatisticSet : ClampedStatisticSet
{
}
+ ///
public IndividualValueStatisticSet(IndividualValueStatisticSet ivs) : base(ivs)
{
}
@@ -430,6 +451,7 @@ public record EffortValueStatisticSet : ClampedStatisticSet
{
}
+ ///
public EffortValueStatisticSet(EffortValueStatisticSet evs) : base(evs)
{
}
diff --git a/PkmnLib.Static/Utils/DictionaryHelpers.cs b/PkmnLib.Static/Utils/DictionaryHelpers.cs
index 06f78bf..11362fd 100644
--- a/PkmnLib.Static/Utils/DictionaryHelpers.cs
+++ b/PkmnLib.Static/Utils/DictionaryHelpers.cs
@@ -1,12 +1,14 @@
namespace PkmnLib.Static.Utils;
+///
+/// Helpers for working with dictionaries.
+///
public static class DictionaryHelpers
{
+ ///
+ /// Gets the value for a key in a dictionary, or returns a default value if the key is not found.
+ ///
public static TValue GetOrDefault(this IDictionary dictionary, TKey key,
- TValue defaultValue)
- {
- if (dictionary.TryGetValue(key, out var value))
- return value;
- return defaultValue;
- }
+ TValue defaultValue) =>
+ dictionary.TryGetValue(key, out var value) ? value : defaultValue;
}
\ No newline at end of file
diff --git a/PkmnLib.Static/Utils/EnumerableHelpers.cs b/PkmnLib.Static/Utils/EnumerableHelpers.cs
index e1fd84e..ef55297 100644
--- a/PkmnLib.Static/Utils/EnumerableHelpers.cs
+++ b/PkmnLib.Static/Utils/EnumerableHelpers.cs
@@ -34,6 +34,9 @@ public static class EnumerableHelpers
return -1;
}
+ ///
+ /// Removes all elements from a list that match the given predicate.
+ ///
public static void RemoveAll(this IList list, Func predicate)
{
for (var i = list.Count - 1; i >= 0; i--)
diff --git a/PkmnLib.Static/Utils/NumericHelpers.cs b/PkmnLib.Static/Utils/NumericHelpers.cs
index 3fbb86e..d6424cc 100644
--- a/PkmnLib.Static/Utils/NumericHelpers.cs
+++ b/PkmnLib.Static/Utils/NumericHelpers.cs
@@ -50,12 +50,18 @@ public static class NumericHelpers
return result > short.MaxValue ? short.MaxValue : (short)result;
}
+ ///
+ /// Multiplies two values. If this overflows, returns .
+ ///
public static uint MultiplyOrMax(this uint value, uint multiplier)
{
var result = (ulong)value * multiplier;
return result > uint.MaxValue ? uint.MaxValue : (uint)result;
}
+ ///
+ /// Multiplies two values. If this overflows, returns .
+ ///
public static uint MultiplyOrMax(this uint value, float multiplier)
{
var result = value * multiplier;
diff --git a/PkmnLib.Tests/PkmnLib.Tests.csproj b/PkmnLib.Tests/PkmnLib.Tests.csproj
index a4fe053..a8ea84b 100644
--- a/PkmnLib.Tests/PkmnLib.Tests.csproj
+++ b/PkmnLib.Tests/PkmnLib.Tests.csproj
@@ -4,9 +4,14 @@
net9.0
enable
enable
-
false
true
+
+
+
+
+ CA1822
+