diff --git a/PkmnLib.Dynamic/Events/EvolutionEvent.cs b/PkmnLib.Dynamic/Events/EvolutionEvent.cs new file mode 100644 index 0000000..36d05fa --- /dev/null +++ b/PkmnLib.Dynamic/Events/EvolutionEvent.cs @@ -0,0 +1,28 @@ +using PkmnLib.Dynamic.Models; +using PkmnLib.Static.Species; + +namespace PkmnLib.Dynamic.Events; + +public record EvolutionEvent : IEventData +{ + public IPokemon Pokemon { get; } + public ISpecies Species { get; } + public IForm OriginalForm { get; } + public ISpecies NewSpecies { get; } + public IForm NewForm { get; } + public IEvolution Evolution { get; } + + public EvolutionEvent(IPokemon pokemon, ISpecies species, IForm originalForm, ISpecies newSpecies, IForm newForm, + IEvolution evolution) + { + Pokemon = pokemon; + Species = species; + NewSpecies = newSpecies; + Evolution = evolution; + OriginalForm = originalForm; + NewForm = newForm; + } + + /// + public EventBatchId BatchId { get; init; } +} \ No newline at end of file diff --git a/PkmnLib.Dynamic/Models/Pokemon.cs b/PkmnLib.Dynamic/Models/Pokemon.cs index 39e797d..dad5d5e 100644 --- a/PkmnLib.Dynamic/Models/Pokemon.cs +++ b/PkmnLib.Dynamic/Models/Pokemon.cs @@ -204,7 +204,7 @@ public interface IPokemon : IScriptSource, IDeepCloneable /// /// Marks the Pokemon as caught. This makes it so that the Pokemon is not considered valid in battle anymore. /// - public void MarkAsCaught(); + void MarkAsCaught(); /// /// The script for the held item. @@ -293,7 +293,7 @@ public interface IPokemon : IScriptSource, IDeepCloneable /// /// Suppresses the ability of the Pokémon. /// - public void SuppressAbility(); + void SuppressAbility(); /// /// Returns the currently active ability. @@ -313,15 +313,21 @@ public interface IPokemon : IScriptSource, IDeepCloneable /// void RecalculateBoostedStats(); + /// + /// Evolves the Pokemon to a specific evolution. This will not check whether the evolution is valid, so + /// you should check that before calling this method. + /// + bool EvolveTo(IEvolution evolution, EventHook? eventHook = null); + /// /// Change the species of the Pokemon. /// - void ChangeSpecies(ISpecies species, IForm form); + void ChangeSpecies(ISpecies species, IForm form, EventHook? eventHook = null); /// /// Change the form of the Pokemon. /// - void ChangeForm(IForm form, EventBatchId batchId = default); + void ChangeForm(IForm form, EventBatchId batchId = default, EventHook? eventHook = null); /// /// Whether the Pokemon is useable in a battle. @@ -606,7 +612,7 @@ public class PokemonImpl : ScriptSource, IPokemon public IDynamicLibrary Library { get; } /// - public ISpecies Species { get; } + public ISpecies Species { get; private set; } /// public IForm Form { get; private set; } @@ -985,8 +991,25 @@ public class PokemonImpl : ScriptSource, IPokemon public void RecalculateBoostedStats() => Library.StatCalculator.CalculateBoostedStats(this, BoostedStats); /// - public void ChangeSpecies(ISpecies species, IForm form) + public bool EvolveTo(IEvolution evolution, EventHook? eventHook = null) { + if (!Species.EvolutionData.Contains(evolution)) + return false; + if (!Library.StaticLibrary.Species.TryGet(evolution.ToSpecies, out var species)) + return false; + + // TODO: Consider how forms work with evolution items. + var newForm = species.GetDefaultForm(); + eventHook?.Invoke(new EvolutionEvent(this, Species, Form, species, newForm, evolution)); + + ChangeSpecies(species, newForm, eventHook); + return true; + } + + /// + public void ChangeSpecies(ISpecies species, IForm form, EventHook? eventHook = null) + { + eventHook ??= BattleData?.Battle.EventHook; if (Species == species) { if (form != Form) @@ -1007,18 +1030,20 @@ public class PokemonImpl : ScriptSource, IPokemon } var batchId = new EventBatchId(); - BattleData?.Battle.EventHook.Invoke(new SpeciesChangeEvent(this, species, form) + eventHook?.Invoke(new SpeciesChangeEvent(this, species, form) { BatchId = batchId, }); + Species = species; ChangeForm(form, batchId); } /// - public void ChangeForm(IForm form, EventBatchId batchId = default) + public void ChangeForm(IForm form, EventBatchId batchId = default, EventHook? eventHook = null) { if (form == Form) return; + eventHook ??= BattleData?.Battle.EventHook; var oldAbility = Form.GetAbility(AbilityIndex); @@ -1068,7 +1093,7 @@ public class PokemonImpl : ScriptSource, IPokemon // TODO: form specific moves? - BattleData?.Battle.EventHook.Invoke(new FormChangeEvent(this, form) + eventHook?.Invoke(new FormChangeEvent(this, form) { BatchId = batchId, }); diff --git a/PkmnLib.Dynamic/ScriptHandling/ItemScript.cs b/PkmnLib.Dynamic/ScriptHandling/ItemScript.cs index 28c0149..4f8aa4f 100644 --- a/PkmnLib.Dynamic/ScriptHandling/ItemScript.cs +++ b/PkmnLib.Dynamic/ScriptHandling/ItemScript.cs @@ -46,12 +46,12 @@ public abstract class ItemScript : IDeepCloneable /// /// Returns whether the item can be held by a Pokémon. /// - public virtual bool IsHoldable => false; + public virtual bool IsHoldable => true; /// /// Returns whether the item can be held by the given target. /// - public virtual bool CanTargetHold(IPokemon pokemon) => false; + public virtual bool CanTargetHold(IPokemon pokemon) => true; /// /// Handles the use of the item. diff --git a/PkmnLib.Dynamic/ScriptHandling/ScriptResolver.cs b/PkmnLib.Dynamic/ScriptHandling/ScriptResolver.cs index 9ff076c..f84cfc6 100644 --- a/PkmnLib.Dynamic/ScriptHandling/ScriptResolver.cs +++ b/PkmnLib.Dynamic/ScriptHandling/ScriptResolver.cs @@ -12,6 +12,7 @@ public class ScriptResolver private IReadOnlyDictionary<(ScriptCategory, StringKey), Func