diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index f5cde9e..29fd77f 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -10,7 +10,7 @@ "rollForward": false }, "jetbrains.resharper.globaltools": { - "version": "2024.3.6", + "version": "2025.1.1", "commands": [ "jb" ], diff --git a/Directory.Build.props b/Directory.Build.props index 0ebcca0..e802dc8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,6 +4,7 @@ + nullable true diff --git a/PkmnLib.Dynamic/Models/Battle.cs b/PkmnLib.Dynamic/Models/Battle.cs index bfc83a6..c792161 100644 --- a/PkmnLib.Dynamic/Models/Battle.cs +++ b/PkmnLib.Dynamic/Models/Battle.cs @@ -172,6 +172,7 @@ public class BattleImpl : ScriptSource, IBattle CanFlee = canFlee; NumberOfSides = numberOfSides; PositionsPerSide = positionsPerSide; + Volatile = new ScriptSet(this); var sides = new IBattleSide[numberOfSides]; for (byte i = 0; i < numberOfSides; i++) sides[i] = new BattleSideImpl(i, positionsPerSide, this); @@ -399,7 +400,7 @@ public class BattleImpl : ScriptSource, IBattle } /// - public IScriptSet Volatile { get; } = new ScriptSet(); + public IScriptSet Volatile { get; } /// public StringKey? WeatherName => WeatherScript.Script?.Name; diff --git a/PkmnLib.Dynamic/Models/BattleChoiceQueue.cs b/PkmnLib.Dynamic/Models/BattleChoiceQueue.cs index bdbf276..1cc8c48 100644 --- a/PkmnLib.Dynamic/Models/BattleChoiceQueue.cs +++ b/PkmnLib.Dynamic/Models/BattleChoiceQueue.cs @@ -132,6 +132,9 @@ public class BattleChoiceQueue : IDeepCloneable public ITurnChoice? FirstOrDefault(Func predicate) => _choices.Skip(_currentIndex).WhereNotNull().FirstOrDefault(predicate); + public IEnumerable Where(Func predicate) => + _choices.Skip(_currentIndex).WhereNotNull().Where(predicate); + /// /// Removes a choice from the queue. /// diff --git a/PkmnLib.Dynamic/Models/BattleSide.cs b/PkmnLib.Dynamic/Models/BattleSide.cs index d975487..3d9673f 100644 --- a/PkmnLib.Dynamic/Models/BattleSide.cs +++ b/PkmnLib.Dynamic/Models/BattleSide.cs @@ -174,7 +174,7 @@ public class BattleSideImpl : ScriptSource, IBattleSide _fillablePositions[i] = true; } Battle = battle; - VolatileScripts = new ScriptSet(); + VolatileScripts = new ScriptSet(this); } /// diff --git a/PkmnLib.Dynamic/Models/Choices/MoveChoice.cs b/PkmnLib.Dynamic/Models/Choices/MoveChoice.cs index 206931d..8d7dd53 100644 --- a/PkmnLib.Dynamic/Models/Choices/MoveChoice.cs +++ b/PkmnLib.Dynamic/Models/Choices/MoveChoice.cs @@ -55,6 +55,7 @@ public class MoveChoice : TurnChoice, IMoveChoice ChosenMove = usedMove; TargetSide = targetSide; TargetPosition = targetPosition; + Volatile = new ScriptSet(this); var secondaryEffect = usedMove.MoveData.SecondaryEffect; if (secondaryEffect != null) @@ -86,7 +87,7 @@ public class MoveChoice : TurnChoice, IMoveChoice public Dictionary? AdditionalData { get; } /// - public IScriptSet Volatile { get; } = new ScriptSet(); + public IScriptSet Volatile { get; } /// public override int ScriptCount => 2 + User.ScriptCount; diff --git a/PkmnLib.Dynamic/Models/LearnedMove.cs b/PkmnLib.Dynamic/Models/LearnedMove.cs index 49423a9..c84af85 100644 --- a/PkmnLib.Dynamic/Models/LearnedMove.cs +++ b/PkmnLib.Dynamic/Models/LearnedMove.cs @@ -37,6 +37,11 @@ public enum MoveLearnMethod /// The move is learned when the Pokémon changes form. /// FormChange, + + /// + /// The move is learned by using a move sketch. + /// + Sketch, } /// diff --git a/PkmnLib.Dynamic/Models/Pokemon.cs b/PkmnLib.Dynamic/Models/Pokemon.cs index d851011..cc14e3f 100644 --- a/PkmnLib.Dynamic/Models/Pokemon.cs +++ b/PkmnLib.Dynamic/Models/Pokemon.cs @@ -487,6 +487,7 @@ public class PokemonImpl : ScriptSource, IPokemon WeightInKg = form.Weight; HeightInMeters = form.Height; Happiness = species.BaseHappiness; + Volatile = new ScriptSet(this); if (!library.StaticLibrary.Natures.TryGet(natureName, out var nature)) throw new KeyNotFoundException($"Nature {natureName} not found."); Nature = nature; @@ -532,6 +533,7 @@ public class PokemonImpl : ScriptSource, IPokemon AbilityIndex = form.FindAbilityIndex(ability) ?? throw new KeyNotFoundException( $"Ability {ability.Name} not found on species {species.Name} form {form.Name}."); + Volatile = new ScriptSet(this); _learnedMoves = serializedPokemon.Moves.Select(move => { if (move == null) @@ -736,7 +738,7 @@ public class PokemonImpl : ScriptSource, IPokemon public ScriptContainer StatusScript { get; } = new(); /// - public IScriptSet Volatile { get; } = new ScriptSet(); + public IScriptSet Volatile { get; } /// public bool HasHeldItem(StringKey itemName) => HeldItem?.Name == itemName; @@ -1097,6 +1099,11 @@ public class PokemonImpl : ScriptSource, IPokemon { if (!Library.ScriptResolver.TryResolve(ScriptCategory.Status, status, null, out var statusScript)) throw new KeyNotFoundException($"Status script {status} not found"); + var preventStatus = false; + this.RunScriptHook(script => script.PreventStatusChange(this, status, ref preventStatus)); + if (preventStatus) + return false; + StatusScript.Set(statusScript); return true; } diff --git a/PkmnLib.Dynamic/PkmnLib.Dynamic.csproj b/PkmnLib.Dynamic/PkmnLib.Dynamic.csproj index beac537..bf8ac7c 100644 --- a/PkmnLib.Dynamic/PkmnLib.Dynamic.csproj +++ b/PkmnLib.Dynamic/PkmnLib.Dynamic.csproj @@ -4,7 +4,6 @@ netstandard2.1 12 enable - nullable enable diff --git a/PkmnLib.Dynamic/ScriptHandling/Script.cs b/PkmnLib.Dynamic/ScriptHandling/Script.cs index 924a9ab..bb8a4c3 100644 --- a/PkmnLib.Dynamic/ScriptHandling/Script.cs +++ b/PkmnLib.Dynamic/ScriptHandling/Script.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using PkmnLib.Dynamic.Models; using PkmnLib.Dynamic.Models.Choices; using PkmnLib.Dynamic.ScriptHandling.Registry; @@ -12,6 +13,7 @@ namespace PkmnLib.Dynamic.ScriptHandling; /// changes. This allows for easily defining generational differences, and add effects that the /// developer might require. /// +[DebuggerDisplay("{Category} - {Name}")] public abstract class Script : IDeepCloneable { internal event Action