From 90eaeb1a7272bf18b592121cef29c9fcd8f99bd2 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sun, 2 Nov 2025 23:20:07 +0100 Subject: [PATCH] Implements experience gain --- PkmnLib.Dynamic/Libraries/DynamicLibrary.cs | 15 ++++++- .../Libraries/ExperienceGainCalculator.cs | 14 +++++++ PkmnLib.Dynamic/Libraries/LibraryLoader.cs | 2 + PkmnLib.Dynamic/Models/Pokemon.cs | 5 +++ .../ScriptHandling/Registry/ScriptRegistry.cs | 8 ++++ Plugins/PkmnLib.Plugin.Gen7/Gen7Plugin.cs | 1 + .../Battling/Gen7ExperienceGainCalculator.cs | 40 +++++++++++++++++++ 7 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 PkmnLib.Dynamic/Libraries/ExperienceGainCalculator.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Libraries/Battling/Gen7ExperienceGainCalculator.cs diff --git a/PkmnLib.Dynamic/Libraries/DynamicLibrary.cs b/PkmnLib.Dynamic/Libraries/DynamicLibrary.cs index 9fb0cc7..b59c513 100644 --- a/PkmnLib.Dynamic/Libraries/DynamicLibrary.cs +++ b/PkmnLib.Dynamic/Libraries/DynamicLibrary.cs @@ -39,6 +39,12 @@ public interface IDynamicLibrary /// ICaptureLibrary CaptureLibrary { get; } + /// + /// The experience gain calculator deals with the calculation of experience gained by a + /// Pokémon after defeating another Pokémon. + /// + IExperienceGainCalculator ExperienceGainCalculator { get; } + /// /// A holder of the script types that can be resolved by this library. /// @@ -64,12 +70,13 @@ public class DynamicLibraryImpl : IDynamicLibrary return new DynamicLibraryImpl(load.StaticLibrary, load.Registry.BattleStatCalculator!, load.Registry.DamageCalculator!, load.Registry.MiscLibrary!, load.Registry.CaptureLibrary!, load.Resolver, - load.Registry.ExplicitAIHandlers); + load.Registry.ExplicitAIHandlers, load.Registry.ExperienceGainCalculator!); } private DynamicLibraryImpl(IStaticLibrary staticLibrary, IBattleStatCalculator statCalculator, IDamageCalculator damageCalculator, IMiscLibrary miscLibrary, ICaptureLibrary captureLibrary, - ScriptResolver scriptResolver, IReadOnlyExplicitAIHandlers explicitAIHandlers) + ScriptResolver scriptResolver, IReadOnlyExplicitAIHandlers explicitAIHandlers, + IExperienceGainCalculator experienceGainCalculator) { StaticLibrary = staticLibrary; StatCalculator = statCalculator; @@ -77,6 +84,7 @@ public class DynamicLibraryImpl : IDynamicLibrary MiscLibrary = miscLibrary; ScriptResolver = scriptResolver; ExplicitAIHandlers = explicitAIHandlers; + ExperienceGainCalculator = experienceGainCalculator; CaptureLibrary = captureLibrary; } @@ -95,6 +103,9 @@ public class DynamicLibraryImpl : IDynamicLibrary /// public ICaptureLibrary CaptureLibrary { get; } + /// + public IExperienceGainCalculator ExperienceGainCalculator { get; } + /// public ScriptResolver ScriptResolver { get; } diff --git a/PkmnLib.Dynamic/Libraries/ExperienceGainCalculator.cs b/PkmnLib.Dynamic/Libraries/ExperienceGainCalculator.cs new file mode 100644 index 0000000..2fc1d37 --- /dev/null +++ b/PkmnLib.Dynamic/Libraries/ExperienceGainCalculator.cs @@ -0,0 +1,14 @@ +using PkmnLib.Dynamic.Models; + +namespace PkmnLib.Dynamic.Libraries; + +/// +/// Calculates experience gain for Pokémon battles. +/// +public interface IExperienceGainCalculator +{ + /// + /// Calculates the experience a Pokémon gains when defeating another Pokémon. + /// + uint CalculateExperienceGain(IPokemon defeatedPokemon, IPokemon victoriousPokemon); +} \ No newline at end of file diff --git a/PkmnLib.Dynamic/Libraries/LibraryLoader.cs b/PkmnLib.Dynamic/Libraries/LibraryLoader.cs index 26ef872..3401efe 100644 --- a/PkmnLib.Dynamic/Libraries/LibraryLoader.cs +++ b/PkmnLib.Dynamic/Libraries/LibraryLoader.cs @@ -36,6 +36,8 @@ public static class LibraryLoader throw new InvalidOperationException("Misc library not found in plugins."); if (registry.CaptureLibrary is null) throw new InvalidOperationException("Capture library not found in plugins."); + if (registry.ExperienceGainCalculator is null) + throw new InvalidOperationException("Experience gain calculator not found in plugins."); var scriptResolver = new ScriptResolver(registry.ScriptTypes, registry.ItemScriptTypes); return new LoadResult(registry, scriptResolver, staticLibrary); } diff --git a/PkmnLib.Dynamic/Models/Pokemon.cs b/PkmnLib.Dynamic/Models/Pokemon.cs index dad5d5e..a819330 100644 --- a/PkmnLib.Dynamic/Models/Pokemon.cs +++ b/PkmnLib.Dynamic/Models/Pokemon.cs @@ -1184,6 +1184,11 @@ public class PokemonImpl : ScriptSource, IPokemon BattleData.BattleSide.MarkFaint(BattleData.Position); BattleData.BattleSide.ForceClearPokemonFromField(BattleData.Position); + foreach (var opponent in BattleData.SeenOpponents.WhereNotNull()) + { + opponent.AddExperience(Library.ExperienceGainCalculator.CalculateExperienceGain(this, opponent)); + } + // Validate the battle state to see if the battle is over. BattleData.Battle.ValidateBattleState(); } diff --git a/PkmnLib.Dynamic/ScriptHandling/Registry/ScriptRegistry.cs b/PkmnLib.Dynamic/ScriptHandling/Registry/ScriptRegistry.cs index 756ac62..0a90089 100644 --- a/PkmnLib.Dynamic/ScriptHandling/Registry/ScriptRegistry.cs +++ b/PkmnLib.Dynamic/ScriptHandling/Registry/ScriptRegistry.cs @@ -19,6 +19,7 @@ public class ScriptRegistry private IDamageCalculator? _damageCalculator; private IMiscLibrary? _miscLibrary; private ICaptureLibrary? _captureLibrary; + private IExperienceGainCalculator? _experienceGainCalculator; /// /// Automatically register all scripts in the given assembly that have the , and @@ -110,11 +111,18 @@ public class ScriptRegistry public void RegisterCaptureLibrary(T captureLibrary) where T : ICaptureLibrary => _captureLibrary = captureLibrary; + /// + /// Register an experience gain calculator. + /// + public void RegisterExperienceGainCalculator(T experienceGainCalculator) where T : IExperienceGainCalculator => + _experienceGainCalculator = experienceGainCalculator; + internal IReadOnlyDictionary<(ScriptCategory category, StringKey name), Func