Implements species/form changing
This commit is contained in:
parent
656c208e5f
commit
213dfdb69e
19
PkmnLib.Dynamic/Events/FormChangeEvent.cs
Normal file
19
PkmnLib.Dynamic/Events/FormChangeEvent.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using PkmnLib.Dynamic.Models;
|
||||||
|
using PkmnLib.Static.Species;
|
||||||
|
|
||||||
|
namespace PkmnLib.Dynamic.Events;
|
||||||
|
|
||||||
|
public class FormChangeEvent : IEventData
|
||||||
|
{
|
||||||
|
public IPokemon Pokemon { get; }
|
||||||
|
public IForm Form { get; }
|
||||||
|
|
||||||
|
public FormChangeEvent(IPokemon pokemon, IForm form)
|
||||||
|
{
|
||||||
|
Pokemon = pokemon;
|
||||||
|
Form = form;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public EventBatchId BatchId { get; init; }
|
||||||
|
}
|
21
PkmnLib.Dynamic/Events/SpeciesChangeEvent.cs
Normal file
21
PkmnLib.Dynamic/Events/SpeciesChangeEvent.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using PkmnLib.Dynamic.Models;
|
||||||
|
using PkmnLib.Static.Species;
|
||||||
|
|
||||||
|
namespace PkmnLib.Dynamic.Events;
|
||||||
|
|
||||||
|
public class SpeciesChangeEvent : IEventData
|
||||||
|
{
|
||||||
|
public IPokemon Pokemon { get; }
|
||||||
|
public ISpecies Species { get; }
|
||||||
|
public IForm Form { get; }
|
||||||
|
|
||||||
|
public SpeciesChangeEvent(IPokemon pokemon, ISpecies species, IForm form)
|
||||||
|
{
|
||||||
|
Pokemon = pokemon;
|
||||||
|
Species = species;
|
||||||
|
Form = form;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public EventBatchId BatchId { get; init; }
|
||||||
|
}
|
@ -19,4 +19,10 @@ public enum DamageSource
|
|||||||
/// The damage is done because of struggling.
|
/// The damage is done because of struggling.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Struggle = 2,
|
Struggle = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The damage is done because of a form change.
|
||||||
|
/// This happens when the form of a Pokemon changes, and it has less max HP than it had before.
|
||||||
|
/// </summary>
|
||||||
|
FormChange = 3,
|
||||||
}
|
}
|
@ -246,7 +246,7 @@ public interface IPokemon : IScriptSource
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change the form of the Pokemon.
|
/// Change the form of the Pokemon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void ChangeForm(IForm form);
|
void ChangeForm(IForm form, EventBatchId batchId = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the Pokemon is useable in a battle.
|
/// Whether the Pokemon is useable in a battle.
|
||||||
@ -305,7 +305,9 @@ public interface IPokemon : IScriptSource
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void MarkOpponentAsSeen(IPokemon pokemon);
|
void MarkOpponentAsSeen(IPokemon pokemon);
|
||||||
|
|
||||||
// TODO: (de)serialize
|
/// <summary>
|
||||||
|
/// Converts the data structure to a serializable format.
|
||||||
|
/// </summary>
|
||||||
SerializedPokemon Serialize();
|
SerializedPokemon Serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,7 +428,8 @@ public class PokemonImpl : ScriptSource, IPokemon
|
|||||||
|
|
||||||
if (serializedPokemon.Status != null)
|
if (serializedPokemon.Status != null)
|
||||||
{
|
{
|
||||||
if (!library.ScriptResolver.TryResolve(ScriptCategory.Status, serializedPokemon.Status, out var statusScript))
|
if (!library.ScriptResolver.TryResolve(ScriptCategory.Status, serializedPokemon.Status,
|
||||||
|
out var statusScript))
|
||||||
throw new KeyNotFoundException($"Status script {serializedPokemon.Status} not found");
|
throw new KeyNotFoundException($"Status script {serializedPokemon.Status} not found");
|
||||||
StatusScript.Set(statusScript);
|
StatusScript.Set(statusScript);
|
||||||
}
|
}
|
||||||
@ -439,7 +442,7 @@ public class PokemonImpl : ScriptSource, IPokemon
|
|||||||
public ISpecies Species { get; }
|
public ISpecies Species { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IForm Form { get; }
|
public IForm Form { get; private set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ISpecies? DisplaySpecies { get; set; }
|
public ISpecies? DisplaySpecies { get; set; }
|
||||||
@ -457,7 +460,7 @@ public class PokemonImpl : ScriptSource, IPokemon
|
|||||||
public uint PersonalityValue { get; }
|
public uint PersonalityValue { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Gender Gender { get; }
|
public Gender Gender { get; private set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public byte Coloring { get; }
|
public byte Coloring { get; }
|
||||||
@ -623,18 +626,82 @@ public class PokemonImpl : ScriptSource, IPokemon
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void ChangeSpecies(ISpecies species, IForm form)
|
public void ChangeSpecies(ISpecies species, IForm form)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (Species == species)
|
||||||
|
{
|
||||||
|
if (form != Form)
|
||||||
|
ChangeForm(form, new EventBatchId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Pokémon is genderless, but its new species is not, we want to set its gender
|
||||||
|
if (Gender != Gender.Genderless && species.GenderRate < 0.0)
|
||||||
|
{
|
||||||
|
var random = (IRandom?)BattleData?.Battle.Random ?? new RandomImpl();
|
||||||
|
Gender = species.GetRandomGender(random);
|
||||||
|
}
|
||||||
|
// Else if the new species is genderless, but the Pokémon has a gender, make the creature genderless.
|
||||||
|
else if (species.GenderRate < 0.0 && Gender != Gender.Genderless)
|
||||||
|
{
|
||||||
|
Gender = Gender.Genderless;
|
||||||
|
}
|
||||||
|
|
||||||
|
var batchId = new EventBatchId();
|
||||||
|
BattleData?.Battle.EventHook.Invoke(new SpeciesChangeEvent(this, species, form)
|
||||||
|
{
|
||||||
|
BatchId = batchId,
|
||||||
|
});
|
||||||
|
ChangeForm(form, batchId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void ChangeForm(IForm form)
|
public void ChangeForm(IForm form, EventBatchId batchId)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (form == Form)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var oldAbility = Form.GetAbility(AbilityIndex);
|
||||||
|
|
||||||
|
Form = form;
|
||||||
|
Types = form.Types.ToList();
|
||||||
|
WeightInKg = form.Weight;
|
||||||
|
HeightInMeters = form.Height;
|
||||||
|
var newAbility = Form.GetAbility(AbilityIndex);
|
||||||
|
|
||||||
|
if (OverrideAbility == null && oldAbility != newAbility)
|
||||||
|
{
|
||||||
|
AbilityScript.Clear();
|
||||||
|
if (!Library.StaticLibrary.Abilities.TryGet(newAbility, out var ability))
|
||||||
|
throw new KeyNotFoundException($"Ability {newAbility} not found.");
|
||||||
|
if (Library.ScriptResolver.TryResolve(ScriptCategory.Ability, newAbility, out var abilityScript))
|
||||||
|
{
|
||||||
|
AbilityScript.Set(abilityScript);
|
||||||
|
abilityScript.OnInitialize(Library, ability.Parameters);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AbilityScript.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var oldHealth = BoostedStats.Hp;
|
||||||
|
RecalculateFlatStats();
|
||||||
|
var diffHealth = (long)BoostedStats.Hp - oldHealth;
|
||||||
|
if (diffHealth > 0)
|
||||||
|
{
|
||||||
|
Heal((uint)diffHealth, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: form specific moves?
|
||||||
|
|
||||||
|
BattleData?.Battle.EventHook.Invoke(new FormChangeEvent(this, form)
|
||||||
|
{
|
||||||
|
BatchId = batchId,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Currently this checks the Pokemon is not an egg, not caught, and not fainted.
|
/// Currently this checks the Pokémon is not an egg, not caught, and not fainted.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public bool IsUsable => !IsCaught && !IsEgg && !IsFainted;
|
public bool IsUsable => !IsCaught && !IsEgg && !IsFainted;
|
||||||
|
|
||||||
@ -644,7 +711,7 @@ public class PokemonImpl : ScriptSource, IPokemon
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Damage(uint damage, DamageSource source, EventBatchId batchId)
|
public void Damage(uint damage, DamageSource source, EventBatchId batchId)
|
||||||
{
|
{
|
||||||
// If the Pokemon is already fainted, we don't need to do anything.
|
// If the Pokémon is already fainted, we don't need to do anything.
|
||||||
if (IsFainted)
|
if (IsFainted)
|
||||||
return;
|
return;
|
||||||
// If the damage is more than the current health, we cap it at the current health, to prevent
|
// If the damage is more than the current health, we cap it at the current health, to prevent
|
||||||
|
@ -67,7 +67,7 @@ public abstract class Script
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// This function is ran when this script starts being in effect.
|
/// This function is ran when this script starts being in effect.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void OnInitialize(IDynamicLibrary library, IReadOnlyDictionary<StringKey, object>? parameters)
|
public virtual void OnInitialize(IDynamicLibrary library, IReadOnlyDictionary<StringKey, object?>? parameters)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user