Implements species/form changing
This commit is contained in:
parent
656c208e5f
commit
213dfdb69e
|
@ -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; }
|
||||
}
|
|
@ -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.
|
||||
/// </summary>
|
||||
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>
|
||||
/// Change the form of the Pokemon.
|
||||
/// </summary>
|
||||
void ChangeForm(IForm form);
|
||||
void ChangeForm(IForm form, EventBatchId batchId = default);
|
||||
|
||||
/// <summary>
|
||||
/// Whether the Pokemon is useable in a battle.
|
||||
|
@ -305,7 +305,9 @@ public interface IPokemon : IScriptSource
|
|||
/// </summary>
|
||||
void MarkOpponentAsSeen(IPokemon pokemon);
|
||||
|
||||
// TODO: (de)serialize
|
||||
/// <summary>
|
||||
/// Converts the data structure to a serializable format.
|
||||
/// </summary>
|
||||
SerializedPokemon Serialize();
|
||||
}
|
||||
|
||||
|
@ -426,7 +428,8 @@ public class PokemonImpl : ScriptSource, IPokemon
|
|||
|
||||
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");
|
||||
StatusScript.Set(statusScript);
|
||||
}
|
||||
|
@ -439,7 +442,7 @@ public class PokemonImpl : ScriptSource, IPokemon
|
|||
public ISpecies Species { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IForm Form { get; }
|
||||
public IForm Form { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ISpecies? DisplaySpecies { get; set; }
|
||||
|
@ -457,7 +460,7 @@ public class PokemonImpl : ScriptSource, IPokemon
|
|||
public uint PersonalityValue { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Gender Gender { get; }
|
||||
public Gender Gender { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte Coloring { get; }
|
||||
|
@ -623,18 +626,82 @@ public class PokemonImpl : ScriptSource, IPokemon
|
|||
/// <inheritdoc />
|
||||
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 />
|
||||
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 />
|
||||
/// <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>
|
||||
public bool IsUsable => !IsCaught && !IsEgg && !IsFainted;
|
||||
|
||||
|
@ -644,7 +711,7 @@ public class PokemonImpl : ScriptSource, IPokemon
|
|||
/// <inheritdoc />
|
||||
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)
|
||||
return;
|
||||
// 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>
|
||||
/// This function is ran when this script starts being in effect.
|
||||
/// </summary>
|
||||
public virtual void OnInitialize(IDynamicLibrary library, IReadOnlyDictionary<StringKey, object>? parameters)
|
||||
public virtual void OnInitialize(IDynamicLibrary library, IReadOnlyDictionary<StringKey, object?>? parameters)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue