356 lines
15 KiB
C#
356 lines
15 KiB
C#
using System.Collections.Generic;
|
|
using PkmnLibSharp.DynamicData.Libraries;
|
|
using PkmnLibSharp.StaticData;
|
|
using PkmnLibSharp.Utils;
|
|
using Form = PkmnLibSharp.StaticData.Form;
|
|
using Interface = PkmnLibSharp.FFI.DynamicData.Pokemon;
|
|
using Item = PkmnLibSharp.StaticData.Item;
|
|
using Species = PkmnLibSharp.StaticData.Species;
|
|
|
|
namespace PkmnLibSharp.DynamicData
|
|
{
|
|
/// <summary>
|
|
/// The data of a Pokemon.
|
|
/// </summary>
|
|
public class Pokemon : HandleType
|
|
{
|
|
/// <inheritdoc cref="Pokemon"/>
|
|
protected Pokemon(FFIHandle handle) : base(handle)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Instantiates a new Pokemon.
|
|
/// </summary>
|
|
/// <param name="dynamicLibrary">The library the Pokemon should fetch its data from</param>
|
|
/// <param name="species">The species of the Pokemon</param>
|
|
/// <param name="form">The form the Pokemon should be</param>
|
|
/// <param name="hiddenAbility">Whether or not the ability the Pokemon has is hidden</param>
|
|
/// <param name="abilityIndex">The index of the ability</param>
|
|
/// <param name="level">The level of the Pokemon</param>
|
|
/// <param name="uid">The unique identifier of the Pokemon</param>
|
|
/// <param name="gender">The gender of the Pokemon</param>
|
|
/// <param name="coloring">The coloring of the Pokemon. This should be 0 for regular, 1 for shiny, and any other value for custom implementations</param>
|
|
/// <param name="nature">The nature of the Pokemon</param>
|
|
public static Pokemon Create(DynamicLibrary dynamicLibrary, Species species, Form form, bool hiddenAbility,
|
|
byte abilityIndex, LevelInt level, uint uid, Gender gender, byte coloring, string nature)
|
|
{
|
|
var handle = Interface.pokemon_new(dynamicLibrary.Handle, species.Handle, form.Handle,
|
|
hiddenAbility.ForeignBool(), abilityIndex, level, uid, gender, coloring, nature.ToPtr())
|
|
.Result();
|
|
return Resolver.Instance.ResolvePokemon(handle.Resolve());
|
|
}
|
|
|
|
private DynamicLibrary? _library;
|
|
|
|
/// <summary>
|
|
/// The library data the Pokemon uses.
|
|
/// </summary>
|
|
public DynamicLibrary Library =>
|
|
_library ??= Resolver.Instance.ResolveDynamicLibrary(Interface.pokemon_library(Handle).Resolve());
|
|
|
|
/// <summary>
|
|
/// The species of the Pokemon.
|
|
/// </summary>
|
|
public Species Species => Resolver.Instance.ResolveSpecies(Interface.pokemon_species(Handle).Resolve());
|
|
|
|
/// <summary>
|
|
/// The form of the Pokemon.
|
|
/// </summary>
|
|
public Form Form => Resolver.Instance.ResolveForm(Interface.pokemon_form(Handle).Resolve());
|
|
|
|
/// <summary>
|
|
/// The species that should be displayed to the user. This handles stuff like the Illusion ability.
|
|
/// </summary>
|
|
public Species DisplaySpecies =>
|
|
Resolver.Instance.ResolveSpecies(Interface.pokemon_display_species(Handle).Resolve());
|
|
|
|
/// <summary>
|
|
/// The form that should be displayed to the user. This handles stuff like the Illusion ability.
|
|
/// </summary>
|
|
public Form DisplayForm => Resolver.Instance.ResolveForm(Interface.pokemon_display_form(Handle).Resolve());
|
|
|
|
/// <summary>
|
|
/// The level of the Pokemon.
|
|
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Level">See also</a>
|
|
/// </summary>
|
|
public LevelInt Level => Interface.pokemon_level(Handle);
|
|
|
|
/// <summary>
|
|
/// The experience of the Pokemon.
|
|
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Experience">See also</a>
|
|
/// </summary>
|
|
public uint Experience => Interface.pokemon_experience(Handle);
|
|
|
|
/// <summary>
|
|
/// The personality value of the Pokemon.
|
|
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Personality_value">See also</a>
|
|
/// </summary>
|
|
public uint PersonalityValue => Interface.pokemon_personality_value(Handle);
|
|
|
|
/// <summary>
|
|
/// The gender of the Pokemon.
|
|
/// </summary>
|
|
public Gender Gender => Interface.pokemon_gender(Handle);
|
|
|
|
/// <summary>
|
|
/// The coloring of the Pokemon. If this is 1, the Pokemon is shiny, otherwise it is not. This can
|
|
/// also be used for other custom coloring schemes.
|
|
/// </summary>
|
|
public byte Coloring => Interface.pokemon_coloring(Handle);
|
|
|
|
/// <summary>
|
|
/// Whether or not the Pokemon is shiny.
|
|
/// </summary>
|
|
public bool IsShiny => Coloring == 1;
|
|
|
|
/// <summary>
|
|
/// Gets the held item of a Pokemon. If the Pokemon does not have a held item, this will return null.
|
|
/// </summary>
|
|
public Item? HeldItem
|
|
{
|
|
get
|
|
{
|
|
var ptr = Interface.pokemon_held_item(Handle);
|
|
return ptr.IsNull ? null : Resolver.Instance.ResolveItem(ptr.Resolve());
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks whether the Pokemon is holding an item with a specific name.
|
|
/// </summary>
|
|
/// <param name="name">The name of the item to check for</param>
|
|
public bool HasHeldItem(string name) => Interface.pokemon_has_held_item(Handle, name.ToPtr()) == 1;
|
|
|
|
/// <summary>
|
|
/// Changes the held item of the Pokemon. Returns the previously held item.
|
|
/// </summary>
|
|
/// <param name="item">The new item to use. If this is given null, it will call <see cref="RemoveHeldItem"/></param>
|
|
public Item? SetHeldItem(Item? item)
|
|
{
|
|
if (item == null)
|
|
{
|
|
return RemoveHeldItem();
|
|
}
|
|
|
|
var handle = Interface.pokemon_set_held_item(Handle, item.Handle);
|
|
return handle.IsNull ? null : Resolver.Instance.ResolveItem(handle.Resolve());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the held item from the Pokemon. Returns the previously held item.
|
|
/// </summary>
|
|
/// <returns>The previous held item. If no item was previously held, this returns null</returns>
|
|
public Item? RemoveHeldItem()
|
|
{
|
|
var handle = Interface.pokemon_remove_held_item(Handle);
|
|
return handle.IsNull ? null : Resolver.Instance.ResolveItem(handle.Resolve());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Makes the Pokemon uses its held item.
|
|
/// </summary>
|
|
/// <returns>Whether or not the held item was successfully consumed</returns>
|
|
public bool ConsumeHeldItem() => Interface.pokemon_consume_held_item(Handle).Result() == 1;
|
|
|
|
/// <summary>
|
|
/// The current health of the Pokemon.
|
|
/// </summary>
|
|
public uint CurrentHealth => Interface.pokemon_current_health(Handle);
|
|
|
|
/// <summary>
|
|
/// The max health of the Pokemon.
|
|
/// </summary>
|
|
public uint MaxHealth => Interface.pokemon_max_health(Handle);
|
|
|
|
/// <summary>
|
|
/// The current weight of the Pokemon.
|
|
/// </summary>
|
|
public float Weight => Interface.pokemon_weight(Handle);
|
|
|
|
/// <summary>
|
|
/// The current height of the Pokemon.
|
|
/// </summary>
|
|
public float Height => Interface.pokemon_height(Handle);
|
|
|
|
/// <summary>
|
|
/// An optional nickname of the Pokemon. If the Pokemon does not have a nickname, this will return null.
|
|
/// </summary>
|
|
public string? Nickname => Interface.pokemon_nickname(Handle).Result().PtrString();
|
|
|
|
/// <summary>
|
|
/// Whether the actual ability the Pokemon has (so not its potentially overriden ability) is a hidden ability.
|
|
/// </summary>
|
|
public bool HasHiddenAbility => Interface.pokemon_real_ability_is_hidden(Handle) == 1;
|
|
|
|
/// <summary>
|
|
/// The index of the actual ability the Pokemon has (so not its potentially overriden ability).
|
|
/// </summary>
|
|
public byte AbilityIndex => Interface.pokemon_real_ability_index(Handle);
|
|
|
|
private ExternValueArray<TypeIdentifier>? _types;
|
|
|
|
/// <summary>
|
|
/// An array of the types of the Pokemon.
|
|
/// </summary>
|
|
public IReadOnlyList<TypeIdentifier> Types =>
|
|
_types ??= new ExternValueArray<TypeIdentifier>(() => Interface.pokemon_types_length(Handle),
|
|
arg => Interface.pokemon_types_get(Handle, arg).Result());
|
|
|
|
private ExternValueArray<LearnedMove?>? _moves;
|
|
|
|
/// <summary>
|
|
/// The moves the Pokemon has learned and can use.
|
|
/// </summary>
|
|
public IReadOnlyList<LearnedMove?> LearnedMoves =>
|
|
_moves ??= new ExternValueArray<LearnedMove?>(() => 4, arg =>
|
|
{
|
|
var ptr = Interface.pokemon_learned_move_get(Handle, arg);
|
|
return ptr.IsNull ? null : Resolver.Instance.ResolveLearnedMove(ptr.Resolve());
|
|
});
|
|
|
|
private StatisticSet<uint>? _flatStats;
|
|
|
|
/// <summary>
|
|
/// The stats of the Pokemon when disregarding any stat boosts.
|
|
/// </summary>
|
|
public StatisticSet<uint> FlatStats =>
|
|
_flatStats ??= Resolver.Instance.ResolveStatisticSet<uint>(Interface.pokemon_flat_stats(Handle).Resolve());
|
|
|
|
private StatisticSet<uint>? _boostedStats;
|
|
|
|
/// <summary>
|
|
/// The stats of the Pokemon including the stat boosts.
|
|
/// </summary>
|
|
public StatisticSet<uint> BoostedStats =>
|
|
_boostedStats ??=
|
|
Resolver.Instance.ResolveStatisticSet<uint>(Interface.pokemon_boosted_stats(Handle).Resolve());
|
|
|
|
/// <summary>
|
|
/// Get the stat boosts for a specific stat. Between -6 and 6.
|
|
/// </summary>
|
|
public sbyte GetStatBoost(Statistic statistic) => Interface.pokemon_get_stat_boost(Handle, statistic);
|
|
|
|
/// <summary>
|
|
/// Gets an individual value of the Pokemon.
|
|
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Individual_values">See also</a>
|
|
/// </summary>
|
|
public byte GetIndividualValue(Statistic statistic) =>
|
|
Interface.pokemon_get_individual_value(Handle, statistic);
|
|
|
|
/// <summary>
|
|
/// Gets an effort value of the Pokemon.
|
|
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Effort_values">See also</a>
|
|
/// </summary>
|
|
public byte GetEffortValue(Statistic statistic) => Interface.pokemon_get_effort_value(Handle, statistic);
|
|
|
|
/// <summary>
|
|
/// Modifies an individual value of the Pokemon.
|
|
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Individual_values">See also</a>
|
|
/// </summary>
|
|
public void SetIndividualValue(Statistic statistic, byte value) =>
|
|
Interface.pokemon_set_individual_value(Handle, statistic, value).Result();
|
|
|
|
/// <summary>
|
|
/// Modifies a effort value of the Pokemon.
|
|
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Effort_values">See also</a>
|
|
/// </summary>
|
|
public void SetEffortValue(Statistic statistic, byte value) =>
|
|
Interface.pokemon_set_effort_value(Handle, statistic, value).Result();
|
|
|
|
// TODO: Battle getter
|
|
|
|
/// <summary>
|
|
/// Get the index of the side of the battle the Pokemon is in. If the Pokemon
|
|
/// is not on the battlefield, this always returns 0.
|
|
/// </summary>
|
|
public byte BattleSideIndex => Interface.pokemon_get_battle_side_index(Handle);
|
|
|
|
/// <summary>
|
|
/// Get the index of the slot on the side of the battle the Pokemon is in. If the Pokemon
|
|
/// is not on the battlefield, this always returns 0.
|
|
/// </summary>
|
|
public byte BattleIndex => Interface.pokemon_get_battle_index(Handle);
|
|
|
|
/// <summary>
|
|
/// Returns whether something overrides the ability.
|
|
/// </summary>
|
|
public bool IsAbilityOverriden => Interface.pokemon_is_ability_overriden(Handle) == 1;
|
|
|
|
/// <summary>
|
|
/// Returns the currently active ability.
|
|
/// </summary>
|
|
public Ability ActiveAbility =>
|
|
Resolver.Instance.ResolveAbility(Interface.pokemon_active_ability(Handle).Result().Resolve());
|
|
|
|
/// <summary>
|
|
/// Whether or not the Pokemon is allowed to gain experience.
|
|
/// </summary>
|
|
public bool AllowedExperienceGain => Interface.pokemon_allowed_experience_gain(Handle) == 1;
|
|
/// <summary>
|
|
/// The nature of the Pokemon.
|
|
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Nature">See also</a>
|
|
/// </summary>
|
|
public Nature Nature => Resolver.Instance.ResolveNature(Interface.pokemon_nature(Handle).Resolve());
|
|
|
|
/// <summary>
|
|
/// Calculates the flat stats on the Pokemon. This should be called when for example the base
|
|
/// stats, level, nature, IV, or EV changes. This has a side effect of recalculating the boosted
|
|
/// stats, as those depend on the flat stats.
|
|
/// </summary>
|
|
public void RecalculateFlatStats() => Interface.pokemon_recalculate_flat_stats(Handle).Result();
|
|
|
|
/// <summary>
|
|
/// Calculates the boosted stats on the Pokemon. This should be called when a stat boost changes.
|
|
/// </summary>
|
|
public void RecalculateBoostedStats() => Interface.pokemon_recalculate_boosted_stats(Handle).Result();
|
|
|
|
/// <summary>
|
|
/// Change the species of the Pokemon.
|
|
/// </summary>
|
|
public void ChangeSpecies(Species species, Form form) =>
|
|
Interface.pokemon_change_species(Handle, species.Handle, form.Handle).Result();
|
|
|
|
/// <summary>
|
|
/// Change the form of the Pokemon.
|
|
/// </summary>
|
|
public void ChangeForm(Form form) => Interface.pokemon_change_form(Handle, form.Handle).Result();
|
|
|
|
/// <summary>
|
|
/// Whether or not the Pokemon is useable in a battle.
|
|
/// </summary>
|
|
public bool IsUsable => Interface.pokemon_is_usable(Handle) == 1;
|
|
/// <summary>
|
|
/// Returns whether the Pokemon is fainted.
|
|
/// </summary>
|
|
public bool IsFainted => Interface.pokemon_is_fainted(Handle) == 1;
|
|
/// <summary>
|
|
/// Whether or not the Pokemon is on the battlefield.
|
|
/// </summary>
|
|
public bool IsOnBattleField => Interface.pokemon_is_on_battlefield(Handle) == 1;
|
|
|
|
/// <summary>
|
|
/// Damages the Pokemon by a certain amount of damage, from a damage source.
|
|
/// </summary>
|
|
public void Damage(uint amount, DamageSource source) =>
|
|
Interface.pokemon_damage(Handle, amount, source).Result();
|
|
|
|
/// <summary>
|
|
/// Heals the Pokemon by a specific amount. Unless allow_revive is set to true, this will not
|
|
/// heal if the Pokemon has 0 health. If the amount healed is 0, this will return false.
|
|
/// </summary>
|
|
public bool Heal(uint amount, bool allowRevive) =>
|
|
Interface.pokemon_heal(Handle, amount, allowRevive.ForeignBool()) == 1;
|
|
|
|
/// <summary>
|
|
/// Learn a move.
|
|
/// </summary>
|
|
public void LearnMove(string moveName, MoveLearnMethod learnMethod) =>
|
|
Interface.pokemon_learn_move(Handle, moveName.ToPtr(), learnMethod).Result();
|
|
|
|
/// <summary>
|
|
/// Removes the current non-volatile status from the Pokemon.
|
|
/// </summary>
|
|
public void ClearStatus() => Interface.pokemon_clear_status(Handle);
|
|
}
|
|
} |