Documents all public classes, adds PokemonParty
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
a8a6b775b3
commit
d03569aa3f
|
@ -1,5 +1,8 @@
|
|||
namespace PkmnLibSharp.DynamicData
|
||||
{
|
||||
/// <summary>
|
||||
/// A source of damage.
|
||||
/// </summary>
|
||||
public enum DamageSource : byte
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -4,10 +4,17 @@ using Interface = PkmnLibSharp.FFI.DynamicData.LearnedMove;
|
|||
|
||||
namespace PkmnLibSharp.DynamicData
|
||||
{
|
||||
/// <summary>
|
||||
/// A learned move is the data attached to a Pokemon for a move it has learned. It has information
|
||||
/// such as the remaining amount of users, how it has been learned, etc.
|
||||
/// </summary>
|
||||
public class LearnedMove : HandleType
|
||||
{
|
||||
private LearnedMove(FFIHandle handle) : base(handle){}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new learned move.
|
||||
/// </summary>
|
||||
public static LearnedMove Create(MoveData moveData, MoveLearnMethod learnMethod)
|
||||
{
|
||||
var handle = Interface.learned_move_new(moveData.Handle, learnMethod);
|
||||
|
@ -53,6 +60,9 @@ namespace PkmnLibSharp.DynamicData
|
|||
public void RestoreUses(byte amount) => Interface.learned_move_restore_uses(Handle, amount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The different ways a move can be learned.
|
||||
/// </summary>
|
||||
public enum MoveLearnMethod : byte
|
||||
{
|
||||
/// We do not know the learn method.
|
||||
|
|
|
@ -4,19 +4,30 @@ using Interface = PkmnLibSharp.FFI.DynamicData.Libraries.BattleStatCalculator;
|
|||
|
||||
namespace PkmnLibSharp.DynamicData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// A battle stat calculator is used to calculate stats for a Pokemon.
|
||||
/// </summary>
|
||||
public abstract class BattleStatCalculator : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="BattleStatCalculator"/>
|
||||
protected BattleStatCalculator(FFIHandle handle) : base(handle){}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A basic implementation of the Gen 7 stat calculator.
|
||||
/// </summary>
|
||||
public class Gen7BattleStatCalculator : BattleStatCalculator
|
||||
{
|
||||
/// <inheritdoc cref="Gen7BattleStatCalculator"/>
|
||||
protected Gen7BattleStatCalculator(FFIHandle handle) : base(handle){}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Gen 7 battle stat calculator
|
||||
/// </summary>
|
||||
public static Gen7BattleStatCalculator Create()
|
||||
{
|
||||
var handle = Interface.gen_7_battle_stat_calculator_new();
|
||||
return Resolver.Instance.ResolveGen7BattleStatCalculator(handle.Resolve());
|
||||
return (Gen7BattleStatCalculator)Resolver.Instance.ResolveBattleStatCalculator(handle.Resolve());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,23 +4,38 @@ using Interface = PkmnLibSharp.FFI.DynamicData.Libraries.DamageLibrary;
|
|||
|
||||
namespace PkmnLibSharp.DynamicData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// A damage library holds the functions related to the calculation of damage.
|
||||
/// </summary>
|
||||
public abstract class DamageLibrary : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="DamageLibrary"/>
|
||||
protected DamageLibrary(FFIHandle ptr) : base(ptr)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The implementation of a Damage Library for generation 7.
|
||||
/// </summary>
|
||||
public class Gen7DamageLibrary : DamageLibrary
|
||||
{
|
||||
/// <inheritdoc cref="Gen7DamageLibrary"/>
|
||||
public Gen7DamageLibrary(FFIHandle ptr) : base(ptr)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new generation 7 damage library
|
||||
/// </summary>
|
||||
/// <param name="hasRandomness">
|
||||
/// Whether or not a random damage modifier (0.85x - 1.00x) is applied to the calculated damage
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public static Gen7DamageLibrary Create(bool hasRandomness)
|
||||
{
|
||||
var handle = Interface.gen_7_damage_library_new((byte)(hasRandomness ? 1 : 0));
|
||||
return Resolver.Instance.ResolveGen7DamageLibrary(handle.Resolve());
|
||||
return (Gen7DamageLibrary)Resolver.Instance.ResolveDamageLibrary(handle.Resolve());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,12 +4,20 @@ using Interface = PkmnLibSharp.FFI.DynamicData.Libraries.DynamicLibrary;
|
|||
|
||||
namespace PkmnLibSharp.DynamicData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// The dynamic library stores a static data library, as well as holding different libraries and
|
||||
/// calculators that might be customized between different generations and implementations.
|
||||
/// </summary>
|
||||
public class DynamicLibrary : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="DynamicLibrary"/>
|
||||
protected DynamicLibrary(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new DynamicLibrary with given libraries.
|
||||
/// </summary>
|
||||
public static DynamicLibrary Create(StaticData.Libraries.StaticData staticData,
|
||||
BattleStatCalculator statCalculator, DamageLibrary damageLibrary, MiscLibrary miscLibrary,
|
||||
ScriptResolver scriptResolver)
|
||||
|
@ -21,6 +29,9 @@ namespace PkmnLibSharp.DynamicData.Libraries
|
|||
return lib;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The static data is the immutable storage data for this library.
|
||||
/// </summary>
|
||||
public StaticData.Libraries.StaticData StaticData { get; private set; } = null!;
|
||||
}
|
||||
}
|
|
@ -4,23 +4,34 @@ using Interface = PkmnLibSharp.FFI.DynamicData.Libraries.MiscLibrary;
|
|||
|
||||
namespace PkmnLibSharp.DynamicData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// The misc library holds several misc functions required for the battle to run.
|
||||
/// </summary>
|
||||
public abstract class MiscLibrary : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="MiscLibrary"/>
|
||||
protected MiscLibrary(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A gen 7 implementation for the MiscLibrary.
|
||||
/// </summary>
|
||||
public class Gen7MiscLibrary : MiscLibrary
|
||||
{
|
||||
/// <inheritdoc cref="Gen7MiscLibrary"/>
|
||||
protected Gen7MiscLibrary(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new MiscLibrary.
|
||||
/// </summary>
|
||||
public static Gen7MiscLibrary Create()
|
||||
{
|
||||
var handle = Interface.gen_7_misc_library_new();
|
||||
return Resolver.Instance.ResolveGen7MiscLibrary(handle.Resolve());
|
||||
return (Gen7MiscLibrary)Resolver.Instance.ResolveMiscLibrary(handle.Resolve());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,8 +5,14 @@ using Interface = PkmnLibSharp.FFI.DynamicData.Libraries.ScriptResolver;
|
|||
|
||||
namespace PkmnLibSharp.DynamicData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// A script resolver deals with the resolving of scripts. These scripts are non-hardcoded
|
||||
/// implementations of different effects in Pokemon. This allows for things such as generational
|
||||
/// differences, and custom implementations.
|
||||
/// </summary>
|
||||
public abstract class ScriptResolver : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="ScriptResolver"/>
|
||||
protected ScriptResolver(FFIHandle handle) : base(handle){}
|
||||
}
|
||||
|
||||
|
@ -15,8 +21,12 @@ namespace PkmnLibSharp.DynamicData.Libraries
|
|||
/// </summary>
|
||||
public class EmptyScriptResolver : ScriptResolver
|
||||
{
|
||||
/// <inheritdoc cref="EmptyScriptResolver"/>
|
||||
protected EmptyScriptResolver(FFIHandle handle) : base(handle){}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty script resolver.
|
||||
/// </summary>
|
||||
public static EmptyScriptResolver Create()
|
||||
{
|
||||
var handle = Interface.empty_script_resolver_new();
|
||||
|
|
|
@ -4,16 +4,23 @@ using Interface = PkmnLibSharp.FFI.DynamicData.Libraries.ScriptResolver;
|
|||
|
||||
namespace PkmnLibSharp.DynamicData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// A WebAssembly script resolver implements the dynamic scripts functionality with WebAssembly.
|
||||
/// </summary>
|
||||
public class WasmScriptResolver : ScriptResolver
|
||||
{
|
||||
/// <inheritdoc cref="WasmScriptResolver"/>
|
||||
protected WasmScriptResolver(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new WebAssemblyScriptResolver.
|
||||
/// </summary>
|
||||
public static WasmScriptResolver Create()
|
||||
{
|
||||
var handle = Interface.webassembly_script_resolver_new();
|
||||
return Resolver.Instance.ResolveWasmScriptResolver(handle.Resolve());
|
||||
return (WasmScriptResolver)Resolver.Instance.ResolveScriptResolver(handle.Resolve());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using PkmnLibSharp.DynamicData.Libraries;
|
||||
using PkmnLibSharp.StaticData;
|
||||
using PkmnLibSharp.Utils;
|
||||
|
@ -8,20 +9,40 @@ using Species = PkmnLibSharp.StaticData.Species;
|
|||
|
||||
namespace PkmnLibSharp.DynamicData
|
||||
{
|
||||
/// <summary>
|
||||
/// The data of a Pokemon.
|
||||
/// </summary>
|
||||
public class Pokemon : HandleType
|
||||
{
|
||||
protected Pokemon(FFIHandle handle) : base(handle){}
|
||||
|
||||
public static Pokemon Create(DynamicLibrary dynamicLibrary, Species species, Form form, bool hiddenAbility, byte abilityIndex,
|
||||
LevelInt level, uint uid, Gender gender, byte coloring, string nature)
|
||||
/// <inheritdoc cref="Pokemon"/>
|
||||
protected Pokemon(FFIHandle handle) : base(handle)
|
||||
{
|
||||
var handle = Interface.pokemon_new(dynamicLibrary.Handle, species.Handle, form.Handle, hiddenAbility.ForeignBool(),
|
||||
abilityIndex, level, uid, gender, coloring, nature.ToPtr())
|
||||
}
|
||||
|
||||
/// <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>
|
||||
|
@ -49,13 +70,43 @@ namespace PkmnLibSharp.DynamicData
|
|||
/// </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);
|
||||
public uint UniqueIdentifier => Interface.pokemon_unique_identifier(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
|
||||
|
@ -65,91 +116,241 @@ namespace PkmnLibSharp.DynamicData
|
|||
}
|
||||
}
|
||||
|
||||
/// <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;
|
||||
|
||||
public void SetHeldItem(Item? item)
|
||||
/// <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)
|
||||
RemoveHeldItem();
|
||||
else
|
||||
Interface.pokemon_set_held_item(Handle, item.Handle);
|
||||
{
|
||||
return RemoveHeldItem();
|
||||
}
|
||||
|
||||
var handle = Interface.pokemon_set_held_item(Handle, item.Handle);
|
||||
return handle.IsNull ? null : Resolver.Instance.ResolveItem(handle.Resolve());
|
||||
}
|
||||
|
||||
public void RemoveHeldItem() => Interface.pokemon_remove_held_item(Handle);
|
||||
/// <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;
|
||||
public 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());
|
||||
|
||||
public LearnedMove? LearnedMove(ulong index)
|
||||
{
|
||||
var ptr = Interface.pokemon_learned_move_get(Handle, index);
|
||||
return ptr.IsNull ? null : Resolver.Instance.ResolveLearnedMove(ptr.Resolve());
|
||||
}
|
||||
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());
|
||||
_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);
|
||||
public byte GetIndividualValue(Statistic statistic) => Interface.pokemon_get_individual_value(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;
|
||||
|
||||
public void Damage(uint amount, DamageSource source) => Interface.pokemon_damage(Handle, amount, source).Result();
|
||||
/// <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);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,9 @@ using PkmnLibSharp.Utils;
|
|||
|
||||
namespace PkmnLibSharp.DynamicData
|
||||
{
|
||||
/// <summary>
|
||||
/// A builder class for creating <see cref="Pokemon"/> instances.
|
||||
/// </summary>
|
||||
public class PokemonBuilder
|
||||
{
|
||||
private static readonly Random DefaultRandom = new();
|
||||
|
@ -29,6 +32,10 @@ namespace PkmnLibSharp.DynamicData
|
|||
private byte _abilityIndex;
|
||||
private byte _coloring;
|
||||
|
||||
/// <inheritdoc cref="PokemonBuilder"/>
|
||||
/// <param name="library">The library the Pokemon should use for data</param>
|
||||
/// <param name="species">The name of the species of Pokemon</param>
|
||||
/// <param name="level">The level the Pokemon should be</param>
|
||||
public PokemonBuilder(DynamicLibrary library, string species, LevelInt level)
|
||||
{
|
||||
_library = library;
|
||||
|
@ -38,54 +45,82 @@ namespace PkmnLibSharp.DynamicData
|
|||
_random = new Random(_randomSeed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the name of the form of the Pokemon.
|
||||
/// </summary>
|
||||
public PokemonBuilder WithForm(string form)
|
||||
{
|
||||
_form = form;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Force the Pokemon to be shiny or not shiny, instead of letting this be determined randomly.
|
||||
/// </summary>
|
||||
public PokemonBuilder ForceShiny(bool value)
|
||||
{
|
||||
_forceShininess = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the gender of the Pokemon to a specific value, instead of letting this be determined randomly.
|
||||
/// </summary>
|
||||
public PokemonBuilder WithGender(Gender gender)
|
||||
{
|
||||
_gender = gender;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the identifier of the Pokemon to a specific value, instead of letting this be determined randomly.
|
||||
/// </summary>
|
||||
public PokemonBuilder WithIdentifier(uint identifier)
|
||||
{
|
||||
_identifier = identifier;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the nature of the Pokemon to a specific value, instead of letting this be determined randomly.
|
||||
/// </summary>
|
||||
public PokemonBuilder WithNature(string nature)
|
||||
{
|
||||
_natureName = nature;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the ability of the Pokemon to a specific value, instead of letting this be determined randomly.
|
||||
/// </summary>
|
||||
public PokemonBuilder WithAbility(string ability)
|
||||
{
|
||||
_ability = ability;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gives the Pokemon a specific amount of experience. If not set, the experience will be calculated based on
|
||||
/// the Pokemon's level and growth rate.
|
||||
/// </summary>
|
||||
public PokemonBuilder WithExperience(uint experience)
|
||||
{
|
||||
_experience = experience;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Teaches the Pokemon a move.
|
||||
/// </summary>
|
||||
public PokemonBuilder LearnMove(string moveName, MoveLearnMethod learnMethod)
|
||||
{
|
||||
_moves.Add((moveName, learnMethod));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is called after all properties have been set, and will create the Pokemon.
|
||||
/// </summary>
|
||||
protected virtual Pokemon Finalize(Species species, Form form, Item? heldItem)
|
||||
{
|
||||
var pokemon = Pokemon.Create(_library, species, form, _hiddenAbility, _abilityIndex, _level,
|
||||
|
@ -100,6 +135,9 @@ namespace PkmnLibSharp.DynamicData
|
|||
return pokemon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates any properties that have not been set with random values.
|
||||
/// </summary>
|
||||
protected virtual void PopulateUninitialized(Species species, Form form, Random random)
|
||||
{
|
||||
_experience ??= _library.StaticData.GrowthRateLibrary.CalculateExperience(species.GrowthRate, _level);
|
||||
|
@ -146,6 +184,9 @@ namespace PkmnLibSharp.DynamicData
|
|||
return (true, (byte)i);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds the Pokemon, based on the properties that have been set.
|
||||
/// </summary>
|
||||
public Pokemon Build()
|
||||
{
|
||||
if (!_library.StaticData.SpeciesLibrary.TryGetValue(_species, out var species))
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using PkmnLibSharp.Utils;
|
||||
using Interface = PkmnLibSharp.FFI.DynamicData.PokemonParty;
|
||||
|
||||
namespace PkmnLibSharp.DynamicData
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of Pokemon belonging to a trainer.
|
||||
/// </summary>
|
||||
public class PokemonParty : HandleType, IReadOnlyList<Pokemon?>
|
||||
{
|
||||
/// <summary>
|
||||
/// A cache of the Pokemon in the party.
|
||||
/// </summary>
|
||||
private Pokemon?[] _cachedPokemon = null!;
|
||||
|
||||
internal PokemonParty(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a party with a set size.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The length of the party</param>
|
||||
public static PokemonParty Create(ulong capacity)
|
||||
{
|
||||
var handle = Interface.pokemon_party_new(capacity).Resolve();
|
||||
var party = Resolver.Instance.ResolvePokemonParty(handle);
|
||||
party._cachedPokemon = new Pokemon?[capacity];
|
||||
return party;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<Pokemon?> GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<Pokemon?>)_cachedPokemon).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Count => _cachedPokemon.Length;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Pokemon? this[int index] => _cachedPokemon[index];
|
||||
|
||||
/// <summary>
|
||||
/// Swaps two Pokemon in the party around.
|
||||
/// </summary>
|
||||
public void Switch(int a, int b)
|
||||
{
|
||||
Interface.pokemon_party_switch(Handle, (ulong)a, (ulong)b).Result();
|
||||
(_cachedPokemon[a], _cachedPokemon[b]) = (_cachedPokemon[b], _cachedPokemon[a]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the Pokemon at an index to a Pokemon, returning the old Pokemon.
|
||||
/// </summary>
|
||||
/// <param name="index">The index to switch at</param>
|
||||
/// <param name="pokemon">The pokemon to switch into the slot</param>
|
||||
/// <returns>The previous Pokemon in the slot</returns>
|
||||
public Pokemon? SwapInto(int index, Pokemon? pokemon)
|
||||
{
|
||||
var handle = Interface.pokemon_party_swap_into(Handle, (ulong)index, pokemon?.Handle ?? FFIHandle.Zero)
|
||||
.Result();
|
||||
var p = handle.IsNull ? null : Resolver.Instance.ResolvePokemon(handle.Resolve());
|
||||
_cachedPokemon[index] = pokemon;
|
||||
return p;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the party still has Pokemon that can be used in battle.
|
||||
/// </summary>
|
||||
public bool HasUsablePokemon() => Interface.pokemon_party_has_usable_pokemon(Handle) == 1;
|
||||
/// <summary>
|
||||
/// Checks if the party contains a given pokemon.
|
||||
/// </summary>
|
||||
/// <param name="pokemon">The pokemon to check for</param>
|
||||
public bool HasPokemon(Pokemon pokemon) => Interface.pokemon_party_has_pokemon(Handle, pokemon.Handle) == 1;
|
||||
|
||||
/// <summary>
|
||||
/// Makes sure there are no empty spots in the party anymore, leaving the length the same.
|
||||
/// </summary>
|
||||
public void PackParty()
|
||||
{
|
||||
Interface.pokemon_party_pack_party(Handle);
|
||||
// Ensure the old cache is kept alive while we update the new one.
|
||||
var oldCache = _cachedPokemon;
|
||||
|
||||
// Update the cache.
|
||||
_cachedPokemon = new Pokemon?[oldCache.Length];
|
||||
for (var i = 0; i < oldCache.Length; i++)
|
||||
{
|
||||
var handle = Interface.pokemon_party_at(Handle, (ulong)i).Resolve();
|
||||
_cachedPokemon[i] = Resolver.Instance.ResolvePokemon(handle);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -54,7 +54,7 @@ namespace PkmnLibSharp.FFI.DynamicData
|
|||
internal static extern uint pokemon_experience(FFIHandleValue pokemon);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern uint pokemon_unique_identifier(FFIHandleValue pokemon);
|
||||
internal static extern uint pokemon_personality_value(FFIHandleValue pokemon);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern Gender pokemon_gender(FFIHandleValue pokemon);
|
||||
|
@ -78,13 +78,13 @@ namespace PkmnLibSharp.FFI.DynamicData
|
|||
/// Changes the held item of the Pokemon. Returns the previously held item.
|
||||
/// </summary>
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern IdentifiablePointer pokemon_set_held_item(FFIHandleValue pokemon, FFIHandle item);
|
||||
internal static extern FFIHandleValue pokemon_set_held_item(FFIHandleValue pokemon, FFIHandle item);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the held item from the Pokemon. Returns the previously held item.
|
||||
/// </summary>
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern IdentifiablePointer pokemon_remove_held_item(FFIHandleValue pokemon);
|
||||
internal static extern FFIHandleValue pokemon_remove_held_item(FFIHandleValue pokemon);
|
||||
|
||||
/// <summary>
|
||||
/// Makes the Pokemon uses its held item.
|
||||
|
@ -191,7 +191,7 @@ namespace PkmnLibSharp.FFI.DynamicData
|
|||
/// returns null.
|
||||
/// </summary>
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern IdentifiablePointer pokemon_get_battle(FFIHandleValue pokemon);
|
||||
internal static extern FFIHandleValue pokemon_get_battle(FFIHandleValue pokemon);
|
||||
|
||||
/// <summary>
|
||||
/// Get the index of the side of the battle the Pokemon is in. If the Pokemon
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using PkmnLibSharp.StaticData;
|
||||
using PkmnLibSharp.Utils;
|
||||
|
||||
namespace PkmnLibSharp.FFI.DynamicData
|
||||
{
|
||||
internal static class PokemonParty
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a party with a set size.
|
||||
/// </summary>
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern FFIHandleValue pokemon_party_new(ulong capacity);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a Pokemon at an index in the party.
|
||||
/// </summary>
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern FFIHandleValue pokemon_party_at(FFIHandleValue party, ulong index);
|
||||
|
||||
/// <summary>
|
||||
/// Swaps two Pokemon in the party around.
|
||||
/// </summary>
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern NativeResult pokemon_party_switch(FFIHandle party, ulong a, ulong b);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the Pokemon at an index to a Pokemon, returning the old Pokemon.
|
||||
/// </summary>
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern NativeResult<FFIHandleValue> pokemon_party_swap_into(FFIHandleValue party, ulong index,
|
||||
FFIHandleValue pokemon);
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the party still has Pokemon that can be used in battle.
|
||||
/// </summary>
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern byte pokemon_party_has_usable_pokemon(FFIHandleValue party);
|
||||
|
||||
/// <summary>
|
||||
/// Get the length of the underlying list of Pokemon.
|
||||
/// </summary>
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern ulong pokemon_party_length(FFIHandleValue party);
|
||||
|
||||
/// <summary>
|
||||
/// Makes sure there are no empty spots in the party anymore, leaving the length the same.
|
||||
/// </summary>
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern NativeResult pokemon_party_pack_party(FFIHandleValue party);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the party contains a given pokemon.
|
||||
/// </summary>
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern byte pokemon_party_has_pokemon(FFIHandleValue party, FFIHandleValue pokemon);
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PkmnLibSharp.FFI
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct IdentifiablePointer
|
||||
{
|
||||
public readonly IntPtr Ptr;
|
||||
public readonly nuint Identifier;
|
||||
|
||||
public bool IsNull => Ptr == IntPtr.Zero;
|
||||
}
|
||||
}
|
|
@ -43,6 +43,9 @@ namespace PkmnLibSharp.FFI
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An error thrown by the library.
|
||||
/// </summary>
|
||||
public class PkmnLibException : Exception
|
||||
{
|
||||
internal PkmnLibException(string message) : base(message){}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace PkmnLibSharp.FFI.StaticData.Libraries
|
|||
internal static extern FFIHandleValue move_library_new(ulong capacity);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern IdentifiablePointer move_library_get(FFIHandleValue ptr, IntPtr key);
|
||||
internal static extern FFIHandleValue move_library_get(FFIHandleValue ptr, IntPtr key);
|
||||
|
||||
[DllImport(Data.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern IntPtr move_library_get_key_by_index(FFIHandleValue ptr, ulong index);
|
||||
|
|
|
@ -14,11 +14,13 @@
|
|||
<NoWarn>IDISP012</NoWarn>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TRACE;WASM;</DefineConstants>
|
||||
<DocumentationFile>bin\Debug\PkmnLibRSharp.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>TRACE;WASM;</DefineConstants>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -5,20 +5,38 @@ using Interface = PkmnLibSharp.FFI.StaticData.Ability;
|
|||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// An ability is a passive effect in battle that is attached to a Pokemon.
|
||||
/// </summary>
|
||||
public class Ability : HandleType
|
||||
{
|
||||
private string? _name;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the ability.
|
||||
/// </summary>
|
||||
public string Name => _name ??= Interface.ability_name(Handle).Result().PtrString()!;
|
||||
|
||||
private string? _effect;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the script effect of the ability.
|
||||
/// </summary>
|
||||
public string Effect => _effect ??= Interface.ability_effect(Handle).Result().PtrString()!;
|
||||
|
||||
/// <summary>
|
||||
/// The parameters for the script effect of the ability.
|
||||
/// </summary>
|
||||
public IReadOnlyList<EffectParameter> Parameters { get; private set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="Ability"/>
|
||||
protected Ability(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new ability.
|
||||
/// </summary>
|
||||
public static Ability Create(string name, string effect, IReadOnlyList<EffectParameter> parameters)
|
||||
{
|
||||
var parameterArray = parameters.Select(x => (FFIHandleValue)x.Handle).ToArray();
|
||||
|
|
|
@ -4,13 +4,27 @@ using Interface = PkmnLibSharp.FFI.StaticData.EffectParameter;
|
|||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// A parameter for an effect. This is basically a simple way to dynamically store multiple different
|
||||
/// primitives on data.
|
||||
/// </summary>
|
||||
public class EffectParameter : HandleType
|
||||
{
|
||||
private ParameterType? _type;
|
||||
|
||||
/// <summary>
|
||||
/// The underlying type of the parameter.
|
||||
/// </summary>
|
||||
public ParameterType? Type => _type ??= (ParameterType)Interface.effect_parameter_get_type(Handle);
|
||||
|
||||
private object? _data;
|
||||
|
||||
/// <summary>
|
||||
/// The data stored in the parameter.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when the parameter type is not recognized. This should never happen.
|
||||
/// </exception>
|
||||
public object Data
|
||||
{
|
||||
get
|
||||
|
@ -27,35 +41,75 @@ namespace PkmnLibSharp.StaticData
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EffectParameter"/>
|
||||
protected EffectParameter(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new parameter from a boolean.
|
||||
/// </summary>
|
||||
public static EffectParameter FromBool(bool b) =>
|
||||
Resolver.Instance.ResolveEffectParameter(Interface.effect_parameter_new_bool(b.ForeignBool()).Resolve());
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new parameter from a 64 bit integer.
|
||||
/// </summary>
|
||||
public static EffectParameter FromLong(long l) =>
|
||||
Resolver.Instance.ResolveEffectParameter(Interface.effect_parameter_new_int(l).Resolve());
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new parameter from a float.
|
||||
/// </summary>
|
||||
public static EffectParameter FromFloat(float f) =>
|
||||
Resolver.Instance.ResolveEffectParameter(Interface.effect_parameter_new_float(f).Resolve());
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new parameter from a string.
|
||||
/// </summary>
|
||||
public static EffectParameter FromString(string s) =>
|
||||
Resolver.Instance.ResolveEffectParameter(Interface.effect_parameter_new_string(s.ToPtr()).Result().Resolve());
|
||||
|
||||
Resolver.Instance.ResolveEffectParameter(
|
||||
Interface.effect_parameter_new_string(s.ToPtr()).Result().Resolve());
|
||||
|
||||
/// <inheritdoc cref="FromBool"/>
|
||||
public static implicit operator EffectParameter(bool b) => FromBool(b);
|
||||
|
||||
/// <inheritdoc cref="FromLong"/>
|
||||
public static implicit operator EffectParameter(long l) => FromLong(l);
|
||||
|
||||
/// <inheritdoc cref="FromFloat"/>
|
||||
public static implicit operator EffectParameter(float f) => FromFloat(f);
|
||||
|
||||
/// <inheritdoc cref="FromString"/>
|
||||
public static implicit operator EffectParameter(string s) => FromString(s);
|
||||
|
||||
/// <summary>
|
||||
/// The different types of parameters.
|
||||
/// </summary>
|
||||
public enum ParameterType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// A boolean parameter.
|
||||
/// </summary>
|
||||
Bool = 0,
|
||||
|
||||
/// <summary>
|
||||
/// A 64 bit integer parameter.
|
||||
/// </summary>
|
||||
Int = 1,
|
||||
|
||||
/// <summary>
|
||||
/// A 32 bit floating point parameter.
|
||||
/// </summary>
|
||||
Float = 2,
|
||||
|
||||
/// <summary>
|
||||
/// A string parameter.
|
||||
/// </summary>
|
||||
String = 3,
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
var data = Data;
|
||||
|
|
|
@ -5,12 +5,20 @@ using Interface = PkmnLibSharp.FFI.StaticData.Form;
|
|||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// A form is a variant of a specific species. A species always has at least one form, but can have
|
||||
/// many more.
|
||||
/// </summary>
|
||||
public class Form : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="Form"/>
|
||||
protected Form(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new form.
|
||||
/// </summary>
|
||||
public static Form Create(string name, float height, float weight, uint baseExperience, TypeIdentifier[] types,
|
||||
StaticStatisticSet<ushort> baseStats, IReadOnlyCollection<string> abilities,
|
||||
IReadOnlyCollection<string> hiddenAbilities, LearnableMoves learnableMoves,
|
||||
|
@ -32,34 +40,69 @@ namespace PkmnLibSharp.StaticData
|
|||
|
||||
|
||||
private string? _name;
|
||||
/// <summary>
|
||||
/// The name of the form.
|
||||
/// </summary>
|
||||
public string Name => _name ??= Interface.form_name(Handle).Result().PtrString()!;
|
||||
private float? _height;
|
||||
|
||||
/// <summary>
|
||||
/// The height of the form in meters.
|
||||
/// </summary>
|
||||
public float Height => _height ??= Interface.form_height(Handle);
|
||||
private float? _weight;
|
||||
|
||||
/// <summary>
|
||||
/// The weight of the form in kilograms.
|
||||
/// </summary>
|
||||
public float Weight => _weight ??= Interface.form_weight(Handle);
|
||||
private uint? _baseExperience;
|
||||
|
||||
/// <summary>
|
||||
/// The base amount of experience that is gained when beating a Pokemon with this form.
|
||||
/// </summary>
|
||||
public uint BaseExperience => _baseExperience ??= Interface.form_base_experience(Handle);
|
||||
|
||||
private IReadOnlyList<TypeIdentifier>? _types;
|
||||
|
||||
/// <summary>
|
||||
/// The normal types a Pokemon with this form has.
|
||||
/// </summary>
|
||||
public IReadOnlyList<TypeIdentifier> Types =>
|
||||
_types ??= new CachedExternValueArray<TypeIdentifier>(Interface.form_types_length(Handle),
|
||||
arg => Interface.form_types_get(Handle, arg));
|
||||
|
||||
private StaticStatisticSet<ushort>? _baseStats;
|
||||
|
||||
/// <summary>
|
||||
/// The inherent values of a form of species that are used for the stats of a Pokemon.
|
||||
/// </summary>
|
||||
public StaticStatisticSet<ushort> BaseStats =>
|
||||
_baseStats ??= Resolver.Instance.ResolveStaticStatisticSet<ushort>(Interface.form_base_stats(Handle).Resolve());
|
||||
|
||||
private IReadOnlyList<string>? _abilities;
|
||||
|
||||
/// <summary>
|
||||
/// The possible abilities a Pokemon with this form can have.
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> Abilities =>
|
||||
_abilities ??= new CachedExternArray<string>(Interface.form_abilities_length(Handle),
|
||||
arg => Interface.form_abilities_get(Handle, arg).PtrString()!);
|
||||
|
||||
private IReadOnlyList<string>? _hiddenAbilities;
|
||||
|
||||
/// <summary>
|
||||
/// The possible hidden abilities a Pokemon with this form can have.
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> HiddenAbilities =>
|
||||
_hiddenAbilities ??= new CachedExternArray<string>(Interface.form_hidden_abilities_length(Handle),
|
||||
arg => Interface.form_hidden_abilities_get(Handle, arg).PtrString()!);
|
||||
|
||||
private LearnableMoves? _learnableMoves;
|
||||
|
||||
/// <summary>
|
||||
/// The moves a Pokemon with this form can learn.
|
||||
/// </summary>
|
||||
public LearnableMoves LearnableMoves =>
|
||||
_learnableMoves ??= Resolver.Instance.ResolveLearnableMoves(Interface.form_moves(Handle).Resolve());
|
||||
}
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gender is a Pokemon characteristic.
|
||||
///
|
||||
/// Required for standard pokemon functions, but somewhat controversial nowadays. Consider adding a feature
|
||||
/// that allows for a more progressive gender system for those that want it?
|
||||
/// </summary>
|
||||
public enum Gender : byte
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -5,28 +5,45 @@ using Interface = PkmnLibSharp.FFI.StaticData.GrowthRate;
|
|||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// A growth rate defines how much experience is required per level.
|
||||
/// </summary>
|
||||
public abstract class GrowthRate : HandleType
|
||||
{
|
||||
|
||||
/// <inheritdoc cref="GrowthRate"/>
|
||||
protected internal GrowthRate(FFIHandle ptr) : base(ptr)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the level something with this growth rate would have at a certain experience.
|
||||
/// </summary>
|
||||
public LevelInt CalculateLevel(uint experience)
|
||||
{
|
||||
return Interface.growth_rate_calculate_level(Handle, experience);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the experience something with this growth rate would have at a certain level.
|
||||
/// </summary>
|
||||
public uint CalculateExperience(LevelInt level)
|
||||
{
|
||||
return Interface.growth_rate_calculate_experience(Handle, level).Result();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An implementation of the growth rate that uses a lookup table for experience.
|
||||
/// </summary>
|
||||
public class LookupGrowthRate : GrowthRate
|
||||
{
|
||||
/// <inheritdoc cref="LookupGrowthRate"/>
|
||||
protected LookupGrowthRate(FFIHandle handle) : base(handle){}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new lookup growth rate. The experience vec should be the amount of experience
|
||||
/// required per level, with the first element being the experience required for level 1 (generally 0).
|
||||
/// </summary>
|
||||
public static LookupGrowthRate Create(uint[] experienceArray)
|
||||
{
|
||||
var arrayPtr = experienceArray.ArrayPtr();
|
||||
|
@ -52,6 +69,10 @@ namespace PkmnLibSharp.StaticData
|
|||
return i * i * i;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Fast experience group
|
||||
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Experience#Fast">See also</a>
|
||||
/// </summary>
|
||||
public static LookupGrowthRate Fast(LevelInt maxLevel)
|
||||
{
|
||||
var arr = new uint[maxLevel];
|
||||
|
@ -64,6 +85,10 @@ namespace PkmnLibSharp.StaticData
|
|||
return LookupGrowthRate.Create(arr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Medium Fast experience group
|
||||
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Experience#Medium_Fast">See also</a>
|
||||
/// </summary>
|
||||
public static LookupGrowthRate MediumFast(LevelInt maxLevel)
|
||||
{
|
||||
var arr = new uint[maxLevel];
|
||||
|
@ -76,6 +101,10 @@ namespace PkmnLibSharp.StaticData
|
|||
return LookupGrowthRate.Create(arr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Medium Slow experience group
|
||||
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Experience#Medium_Slow">See also</a>
|
||||
/// </summary>
|
||||
public static LookupGrowthRate MediumSlow(LevelInt maxLevel)
|
||||
{
|
||||
var arr = new uint[maxLevel];
|
||||
|
@ -88,6 +117,10 @@ namespace PkmnLibSharp.StaticData
|
|||
return LookupGrowthRate.Create(arr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Slow experience group
|
||||
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Experience#Slow">See also</a>
|
||||
/// </summary>
|
||||
public static LookupGrowthRate Slow(LevelInt maxLevel)
|
||||
{
|
||||
var arr = new uint[maxLevel];
|
||||
|
@ -99,6 +132,10 @@ namespace PkmnLibSharp.StaticData
|
|||
return LookupGrowthRate.Create(arr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Erratic experience group
|
||||
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Experience#Erratic">See also</a>
|
||||
/// </summary>
|
||||
public static LookupGrowthRate Erratic(LevelInt maxLevel)
|
||||
{
|
||||
var arr = new uint[maxLevel];
|
||||
|
@ -127,6 +164,10 @@ namespace PkmnLibSharp.StaticData
|
|||
return LookupGrowthRate.Create(arr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The fluctuating experience group
|
||||
/// <a href="https://bulbapedia.bulbagarden.net/wiki/Experience#Fluctuating">See also</a>
|
||||
/// </summary>
|
||||
public static LookupGrowthRate Fluctuating(LevelInt maxLevel)
|
||||
{
|
||||
var arr = new uint[maxLevel];
|
||||
|
|
|
@ -82,10 +82,17 @@ namespace PkmnLibSharp.StaticData
|
|||
MiscBattleItem,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An item is an object which the player can pick up, keep in their Bag, and use in some manner
|
||||
/// </summary>
|
||||
public class Item : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="Item"/>
|
||||
protected Item(FFIHandle handle) : base(handle){}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates an item.
|
||||
/// </summary>
|
||||
public static Item Create(string name, ItemCategory category, BattleItemCategory battleItemCategory, int price,
|
||||
IEnumerable<string> flags)
|
||||
{
|
||||
|
@ -97,14 +104,29 @@ namespace PkmnLibSharp.StaticData
|
|||
}
|
||||
|
||||
private string? _name;
|
||||
/// <summary>
|
||||
/// The name of the item.
|
||||
/// </summary>
|
||||
public string Name => _name ??= Interface.item_name(Handle).Result().PtrString()!;
|
||||
private ItemCategory? _category;
|
||||
/// <summary>
|
||||
/// Which bag slot items are stored in.
|
||||
/// </summary>
|
||||
public ItemCategory Category => _category ??= Interface.item_category(Handle);
|
||||
private BattleItemCategory? _battleCategory;
|
||||
/// <summary>
|
||||
/// How the item is categorized when in battle.
|
||||
/// </summary>
|
||||
public BattleItemCategory BattleCategory => _battleCategory ??= Interface.item_battle_category(Handle);
|
||||
private int? _price;
|
||||
/// <summary>
|
||||
/// The buying value of the item.
|
||||
/// </summary>
|
||||
public int Price => _price ??= Interface.item_price(Handle);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the item has a specific flag.
|
||||
/// </summary>
|
||||
public bool HasFlag(string flag) => Interface.item_has_flag(Handle, flag.ToPtr()) == 1;
|
||||
}
|
||||
}
|
|
@ -3,23 +3,36 @@ using Interface = PkmnLibSharp.FFI.StaticData.LearnableMoves;
|
|||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// The storage of the moves a Pokemon can learn.
|
||||
/// </summary>
|
||||
public class LearnableMoves : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="LearnableMoves"/>
|
||||
protected LearnableMoves(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new object to store the moves a Pokemon can learn.
|
||||
/// </summary>
|
||||
public static LearnableMoves Create()
|
||||
{
|
||||
var handle = Interface.learnable_moves_new();
|
||||
return Resolver.Instance.ResolveLearnableMoves(handle.Resolve());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new level move the Pokemon can learn.
|
||||
/// </summary>
|
||||
public void AddLevelMove(LevelInt level, string moveName)
|
||||
{
|
||||
Interface.learnable_moves_add_level_move(Handle, level, moveName.ToPtr());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new level move the Pokemon can learn.
|
||||
/// </summary>
|
||||
public void AddLevelMove(LevelInt level, MoveData move)
|
||||
{
|
||||
Interface.learnable_moves_add_level_move(Handle, level, move.Name.ToPtr());
|
||||
|
|
|
@ -1,29 +1,48 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using BackingLevelInt = System.Byte;
|
||||
// ReSharper disable BuiltInTypeReferenceStyle
|
||||
|
||||
// The type we store a level in. As our implementation is aimed at normal Pokemon behaviour, a u8
|
||||
// is probably enough, as we'd go up to 100. If you for some reason want to go higher, you can just
|
||||
// change this type to hold a higher number.
|
||||
using BackingLevelInt = System.Byte;
|
||||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// The data structure used to store a level. This is a struct to allow for easy modification of the data type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you want to change the type of the level, you can just change the type of <see cref="BackingLevelInt"/>.
|
||||
/// Most of the implementation below is to allow for easy conversion between the two types, and to allow for
|
||||
/// using the type as a normal integer.
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct LevelInt : IComparable, IComparable<BackingLevelInt>, IComparable<LevelInt>, IConvertible,
|
||||
IEquatable<BackingLevelInt>, IEquatable<LevelInt>, IEquatable<int>, IFormattable
|
||||
{
|
||||
[FieldOffset(0)] private BackingLevelInt _value;
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="LevelInt"/> to a <see cref="BackingLevelInt"/>.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator BackingLevelInt(LevelInt l)
|
||||
{
|
||||
return l._value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="BackingLevelInt"/> to a <see cref="LevelInt"/>.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator LevelInt(BackingLevelInt b)
|
||||
{
|
||||
return new LevelInt { _value = b };
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
if (obj is LevelInt l)
|
||||
|
@ -31,89 +50,120 @@ namespace PkmnLibSharp.StaticData
|
|||
return _value.CompareTo(obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int CompareTo(BackingLevelInt other) => _value.CompareTo(other);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int CompareTo(LevelInt other) => _value.CompareTo(other._value);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public TypeCode GetTypeCode() => Type.GetTypeCode(typeof(BackingLevelInt));
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool ToBoolean(IFormatProvider provider) => ((IConvertible)_value).ToBoolean(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte ToByte(IFormatProvider provider) => ((IConvertible)_value).ToByte(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public char ToChar(IFormatProvider provider) => ((IConvertible)_value).ToChar(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public DateTime ToDateTime(IFormatProvider provider) => ((IConvertible)_value).ToDateTime(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public decimal ToDecimal(IFormatProvider provider) => ((IConvertible)_value).ToDecimal(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public double ToDouble(IFormatProvider provider) => ((IConvertible)_value).ToDouble(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public short ToInt16(IFormatProvider provider) => ((IConvertible)_value).ToInt16(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int ToInt32(IFormatProvider provider) => ((IConvertible)_value).ToInt32(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public long ToInt64(IFormatProvider provider) => ((IConvertible)_value).ToInt64(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public sbyte ToSByte(IFormatProvider provider) => ((IConvertible)_value).ToSByte(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public float ToSingle(IFormatProvider provider) => ((IConvertible)_value).ToSingle(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ToString(IFormatProvider provider) => _value.ToString(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public object ToType(Type conversionType, IFormatProvider provider) =>
|
||||
((IConvertible)_value).ToType(conversionType, provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ushort ToUInt16(IFormatProvider provider) => ((IConvertible)_value).ToUInt16(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint ToUInt32(IFormatProvider provider) => ((IConvertible)_value).ToUInt32(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ulong ToUInt64(IFormatProvider provider) => ((IConvertible)_value).ToUInt64(provider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(BackingLevelInt other) => _value == other;
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ToString(string format, IFormatProvider formatProvider) =>
|
||||
_value.ToString(format, formatProvider);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(LevelInt other) => _value == other._value;
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(int other) => _value == other;
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override bool Equals(object? obj) => obj is LevelInt other && Equals(other);
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _value.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Equality operator for <see cref="LevelInt"/>.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(LevelInt left, LevelInt right) => left.Equals(right);
|
||||
|
||||
/// <summary>
|
||||
/// Inequality operator for <see cref="LevelInt"/>.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(LevelInt left, LevelInt right) => !left.Equals(right);
|
||||
}
|
||||
|
|
|
@ -6,12 +6,19 @@ using Interface = PkmnLibSharp.FFI.StaticData.Libraries.AbilityLibrary;
|
|||
|
||||
namespace PkmnLibSharp.StaticData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// A storage for all abilities that can be used in this data library.
|
||||
/// </summary>
|
||||
public class AbilityLibrary : DataLibrary<Ability>
|
||||
{
|
||||
/// <inheritdoc cref="AbilityLibrary"/>
|
||||
protected AbilityLibrary(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new ability library.
|
||||
/// </summary>
|
||||
public static AbilityLibrary Create(ulong capacity)
|
||||
{
|
||||
var handle = Interface.ability_library_new(capacity).Resolve();
|
||||
|
@ -20,6 +27,7 @@ namespace PkmnLibSharp.StaticData.Libraries
|
|||
return self;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void AddNative(string key, Ability value) =>
|
||||
Interface.ability_library_add(Handle, key.ToPtr(), value.Handle);
|
||||
}
|
||||
|
|
|
@ -5,19 +5,30 @@ using PkmnLibSharp.Utils;
|
|||
|
||||
namespace PkmnLibSharp.StaticData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// The base backing class for all data libraries.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// The type that this data library stores.
|
||||
/// </typeparam>
|
||||
public abstract class DataLibrary<T> : HandleType, IReadOnlyDictionary<string, T> where T : HandleType
|
||||
{
|
||||
private Dictionary<string, T> _backingDictionary = new(StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
/// <inheritdoc cref="DataLibrary{T}"/>
|
||||
protected DataLibrary(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
protected void ReserveCapacity(ulong capacity)
|
||||
/// <summary>
|
||||
/// Reserves the cache capacity for this data library.
|
||||
/// </summary>
|
||||
private protected void ReserveCapacity(ulong capacity)
|
||||
{
|
||||
_backingDictionary = new Dictionary<string, T>((int)capacity, StringComparer.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<KeyValuePair<string, T>> GetEnumerator()
|
||||
{
|
||||
return _backingDictionary.GetEnumerator();
|
||||
|
@ -28,22 +39,36 @@ namespace PkmnLibSharp.StaticData.Libraries
|
|||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls the native add function for this data library.
|
||||
/// </summary>
|
||||
protected abstract void AddNative(string key, T value);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new value to the library.
|
||||
/// </summary>
|
||||
public void Add(string key, T value)
|
||||
{
|
||||
AddNative(key, value);
|
||||
_backingDictionary.Add(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Count => _backingDictionary.Count;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool ContainsKey(string key) => _backingDictionary.ContainsKey(key);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetValue(string key, out T value) => _backingDictionary.TryGetValue(key, out value);
|
||||
|
||||
/// <inheritdoc />
|
||||
public T this[string key] => _backingDictionary[key];
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<string> Keys => _backingDictionary.Keys;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<T> Values => _backingDictionary.Values;
|
||||
}
|
||||
}
|
|
@ -6,15 +6,22 @@ using Interface = PkmnLibSharp.FFI.StaticData.Libraries.GrowthRateLibrary;
|
|||
|
||||
namespace PkmnLibSharp.StaticData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// A library to store all growth rates.
|
||||
/// </summary>
|
||||
public class GrowthRateLibrary : HandleType
|
||||
{
|
||||
// ReSharper disable once CollectionNeverQueried.Local
|
||||
private Dictionary<string, GrowthRate> _growthRates = new();
|
||||
|
||||
/// <inheritdoc cref="GrowthRateLibrary"/>
|
||||
protected GrowthRateLibrary(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new growth rate library with a capacity.
|
||||
/// </summary>
|
||||
public static GrowthRateLibrary Create(ulong capacity)
|
||||
{
|
||||
var handle = Interface.growth_rate_library_new(capacity);
|
||||
|
@ -24,16 +31,25 @@ namespace PkmnLibSharp.StaticData.Libraries
|
|||
return lib;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the level for a given growth key name and a certain experience.
|
||||
/// </summary>
|
||||
[MustUseReturnValue]
|
||||
public LevelInt CalculateLevel(string name, uint experience) =>
|
||||
Interface.growth_rate_library_calculate_level(Handle, name.ToPtr(), experience).Result();
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the experience for a given growth key name and a certain level.
|
||||
/// </summary>
|
||||
[MustUseReturnValue]
|
||||
public uint CalculateExperience(string name, LevelInt level)
|
||||
{
|
||||
return Interface.growth_rate_library_calculate_experience(Handle, name.ToPtr(), level).Result();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new growth rate with a name and value.
|
||||
/// </summary>
|
||||
public void AddGrowthRate(string name, GrowthRate growthRate)
|
||||
{
|
||||
Interface.growth_rate_library_add_growth_rate(Handle, name.ToPtr(), growthRate.Handle);
|
||||
|
|
|
@ -5,10 +5,17 @@ using Interface = PkmnLibSharp.FFI.StaticData.Libraries.ItemLibrary;
|
|||
|
||||
namespace PkmnLibSharp.StaticData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// A library to store all items.
|
||||
/// </summary>
|
||||
public class ItemLibrary : DataLibrary<Item>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected ItemLibrary(FFIHandle handle) : base(handle){}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new Item Library.
|
||||
/// </summary>
|
||||
public static ItemLibrary Create(ulong capacity)
|
||||
{
|
||||
var handle = Interface.item_library_new(capacity).Resolve();
|
||||
|
@ -17,6 +24,7 @@ namespace PkmnLibSharp.StaticData.Libraries
|
|||
return self;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void AddNative(string key, Item value)
|
||||
{
|
||||
Interface.item_library_add(Handle, key.ToPtr(), value.Handle);
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace PkmnLibSharp.StaticData.Libraries
|
|||
/// </summary>
|
||||
public class LibrarySettings : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="LibrarySettings"/>
|
||||
protected LibrarySettings(FFIHandle handle) : base(handle) {}
|
||||
|
||||
/// <inheritdoc cref="LibrarySettings"/>
|
||||
|
|
|
@ -6,18 +6,26 @@ using Interface = PkmnLibSharp.FFI.StaticData.Libraries.MoveLibrary;
|
|||
|
||||
namespace PkmnLibSharp.StaticData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// A library to store all data for moves.
|
||||
/// </summary>
|
||||
public class MoveLibrary : DataLibrary<MoveData>
|
||||
{
|
||||
/// <inheritdoc cref="MoveLibrary"/>
|
||||
protected MoveLibrary(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new Move Library.
|
||||
/// </summary>
|
||||
public static MoveLibrary Create(ulong capacity)
|
||||
{
|
||||
var handle = Interface.move_library_new(capacity);
|
||||
return Resolver.Instance.ResolveMoveLibrary(handle.Resolve());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void AddNative(string key, MoveData value)
|
||||
{
|
||||
Interface.move_library_add(Handle, key.ToPtr(), value.Handle);
|
||||
|
|
|
@ -8,14 +8,21 @@ using Interface = PkmnLibSharp.FFI.StaticData.Libraries.NatureLibrary;
|
|||
|
||||
namespace PkmnLibSharp.StaticData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// A library of all natures that can be used, stored by their names.
|
||||
/// </summary>
|
||||
public class NatureLibrary : HandleType
|
||||
{
|
||||
private Dictionary<string, Nature> _natures = new();
|
||||
|
||||
/// <inheritdoc cref="NatureLibrary"/>
|
||||
protected NatureLibrary(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new nature library with a given capacity.
|
||||
/// </summary>
|
||||
public static NatureLibrary Create(ulong capacity)
|
||||
{
|
||||
var handle = Interface.nature_library_new(capacity);
|
||||
|
@ -25,6 +32,9 @@ namespace PkmnLibSharp.StaticData.Libraries
|
|||
return lib;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to get a nature from the library by its name.
|
||||
/// </summary>
|
||||
public bool TryGetNature(string name, [NotNullWhen(true)] out Nature? nature)
|
||||
{
|
||||
if (_natures.TryGetValue(name, out nature))
|
||||
|
@ -37,17 +47,29 @@ namespace PkmnLibSharp.StaticData.Libraries
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random nature.
|
||||
/// </summary>
|
||||
/// <param name="seed">
|
||||
/// The seed to use for the random number generator.
|
||||
/// </param>
|
||||
public Nature GetRandomNature(ulong seed)
|
||||
{
|
||||
return Resolver.Instance.ResolveNature(Interface.nature_library_get_random_nature(Handle, seed).Result().Resolve());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of a nature from its object.
|
||||
/// </summary>
|
||||
public string GetNatureName(Nature nature)
|
||||
{
|
||||
var fd = _natures.FirstOrDefault(x => x.Value == nature);
|
||||
return fd.Key ?? Interface.nature_library_get_nature_name(Handle, nature.Handle).PtrString()!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new nature with name to the library.
|
||||
/// </summary>
|
||||
public void LoadNature(string name, Nature nature)
|
||||
{
|
||||
Interface.nature_library_load_nature(Handle, name.ToPtr(), nature.Handle);
|
||||
|
|
|
@ -3,12 +3,19 @@ using Interface = PkmnLibSharp.FFI.StaticData.Libraries.SpeciesLibrary;
|
|||
|
||||
namespace PkmnLibSharp.StaticData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// A library to store all data for Pokemon species.
|
||||
/// </summary>
|
||||
public class SpeciesLibrary : DataLibrary<Species>
|
||||
{
|
||||
/// <inheritdoc cref="SpeciesLibrary"/>
|
||||
protected SpeciesLibrary(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new Species Library.
|
||||
/// </summary>
|
||||
public static SpeciesLibrary Create(ulong capacity)
|
||||
{
|
||||
var handle = Interface.species_library_new(capacity);
|
||||
|
@ -18,6 +25,7 @@ namespace PkmnLibSharp.StaticData.Libraries
|
|||
return lib;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void AddNative(string key, Species value)
|
||||
{
|
||||
Interface.species_library_add(Handle, key.ToPtr(), value.Handle);
|
||||
|
|
|
@ -3,12 +3,19 @@ using Interface = PkmnLibSharp.FFI.StaticData.Libraries.StaticData;
|
|||
|
||||
namespace PkmnLibSharp.StaticData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// The storage for all different libraries.
|
||||
/// </summary>
|
||||
public class StaticData : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="StaticData"/>
|
||||
protected StaticData(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new data collection.
|
||||
/// </summary>
|
||||
public static StaticData Create(LibrarySettings settings, SpeciesLibrary speciesLibrary,
|
||||
MoveLibrary moveLibrary, ItemLibrary itemLibrary, GrowthRateLibrary growthRateLibrary,
|
||||
TypeLibrary typeLibrary, NatureLibrary natureLibrary, AbilityLibrary abilityLibrary)
|
||||
|
@ -28,13 +35,44 @@ namespace PkmnLibSharp.StaticData.Libraries
|
|||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Several misc settings for the library.
|
||||
/// </summary>
|
||||
public LibrarySettings LibrarySettings { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// All data for Pokemon species.
|
||||
/// </summary>
|
||||
public SpeciesLibrary SpeciesLibrary { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// All data for the moves.
|
||||
/// </summary>
|
||||
public MoveLibrary MoveLibrary { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// All data for the items.
|
||||
/// </summary>
|
||||
public ItemLibrary ItemLibrary { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// All data for growth rates.
|
||||
/// </summary>
|
||||
public GrowthRateLibrary GrowthRateLibrary { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// All data related to types and type effectiveness.
|
||||
/// </summary>
|
||||
public TypeLibrary TypeLibrary { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// All data related to natures.
|
||||
/// </summary>
|
||||
public NatureLibrary NatureLibrary { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// All data related to abilities.
|
||||
/// </summary>
|
||||
public AbilityLibrary AbilityLibrary { get; private set; } = null!;
|
||||
}
|
||||
}
|
|
@ -7,53 +7,81 @@ using Interface = PkmnLibSharp.FFI.StaticData.Libraries.TypeLibrary;
|
|||
|
||||
namespace PkmnLibSharp.StaticData.Libraries
|
||||
{
|
||||
/// <summary>
|
||||
/// All data related to types and effectiveness.
|
||||
/// </summary>
|
||||
public class TypeLibrary : HandleType
|
||||
{
|
||||
public Dictionary<string, TypeIdentifier> TypeCache { get; private set; } =
|
||||
new(StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
protected TypeLibrary(FFIHandle handle) : base(handle){}
|
||||
|
||||
private Dictionary<string, TypeIdentifier> _typeCache = new(StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
/// <inheritdoc cref="TypeLibrary"/>
|
||||
protected TypeLibrary(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new type library with a specific capacity.
|
||||
/// </summary>
|
||||
public static TypeLibrary Create(ulong capacity)
|
||||
{
|
||||
var handle = Interface.type_library_new(capacity);
|
||||
var lib = Resolver.Instance.ResolveTypeLibrary(handle.Resolve());
|
||||
lib.TypeCache = new Dictionary<string, TypeIdentifier>((int)capacity, StringComparer.InvariantCultureIgnoreCase);
|
||||
lib._typeCache =
|
||||
new Dictionary<string, TypeIdentifier>((int)capacity, StringComparer.InvariantCultureIgnoreCase);
|
||||
return lib;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type identifier for a type with a name.
|
||||
/// </summary>
|
||||
public TypeIdentifier GetTypeId(string name)
|
||||
{
|
||||
if (TypeCache.TryGetValue(name, out var typeIdentifier))
|
||||
if (_typeCache.TryGetValue(name, out var typeIdentifier))
|
||||
return typeIdentifier;
|
||||
throw new KeyNotFoundException($"No type found with name `{name}`");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type name from the type identifier.
|
||||
/// </summary>
|
||||
public string GetTypeName(TypeIdentifier typeIdentifier)
|
||||
{
|
||||
var fd = TypeCache.FirstOrDefault(x => x.Value == typeIdentifier);
|
||||
var fd = _typeCache.FirstOrDefault(x => x.Value == typeIdentifier);
|
||||
if (fd.Key != null)
|
||||
return fd.Key;
|
||||
throw new KeyNotFoundException($"No type found for given identifier");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the effectiveness for a single attacking type against a single defending type.
|
||||
/// </summary>
|
||||
public float GetSingleEffectiveness(TypeIdentifier attacking, TypeIdentifier defending) =>
|
||||
Interface.type_library_get_single_effectiveness(Handle, attacking, defending);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the effectiveness for a single attacking type against an amount of defending types.
|
||||
/// This is equivalent to running <see cref="GetSingleEffectiveness"/> on each defending type, and
|
||||
/// multiplying the results with each other.
|
||||
/// </summary>
|
||||
public float GetEffectiveness(TypeIdentifier attacking, TypeIdentifier[] defending)
|
||||
{
|
||||
var arrayPtr = defending.ArrayPtr();
|
||||
return Interface.type_library_get_effectiveness(Handle, attacking, arrayPtr, (ulong)defending.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a new type in the library.
|
||||
/// </summary>
|
||||
public TypeIdentifier RegisterType(string name)
|
||||
{
|
||||
var typeId = Interface.type_library_register_type(Handle, name.ToPtr());
|
||||
TypeCache.Add(name, typeId);
|
||||
_typeCache.Add(name, typeId);
|
||||
return typeId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the effectiveness for an attacking type against a defending type.
|
||||
/// </summary>
|
||||
public void SetEffectiveness(TypeIdentifier attacking, TypeIdentifier defending, float effectiveness) =>
|
||||
Interface.type_library_set_effectiveness(Handle, attacking, defending, effectiveness);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ using Interface = PkmnLibSharp.FFI.StaticData.MoveData;
|
|||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// The move category defines what global kind of move this move is.
|
||||
/// </summary>
|
||||
public enum MoveCategory : byte
|
||||
{
|
||||
/// A physical move uses the physical attack stats and physical defense stats to calculate damage.
|
||||
|
@ -17,6 +20,9 @@ namespace PkmnLibSharp.StaticData
|
|||
Status = 2,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The move target defines what kind of targets the move can touch.
|
||||
/// </summary>
|
||||
public enum MoveTarget : byte
|
||||
{
|
||||
/// Adjacent allows a move to target any Pokemon that is either directly to the left or right of
|
||||
|
@ -60,40 +66,87 @@ namespace PkmnLibSharp.StaticData
|
|||
SelfUse,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A move is the skill Pokémon primarily use in battle. This is the data related to that.
|
||||
/// </summary>
|
||||
public class MoveData : HandleType
|
||||
{
|
||||
protected MoveData(FFIHandle handle) : base(handle) {}
|
||||
|
||||
public static MoveData Create(string name, TypeIdentifier moveType, MoveCategory category, byte basePower, byte accuracy,
|
||||
byte baseUsages, MoveTarget target, sbyte priority, SecondaryEffect? secondaryEffect,
|
||||
/// <inheritdoc cref="MoveData"/>
|
||||
protected MoveData(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new move.
|
||||
/// </summary>
|
||||
public static MoveData Create(string name, TypeIdentifier moveType, MoveCategory category, byte basePower,
|
||||
byte accuracy, byte baseUsages, MoveTarget target, sbyte priority, SecondaryEffect? secondaryEffect,
|
||||
IEnumerable<string> flags)
|
||||
{
|
||||
var ptrArray = flags.Select(x => x.ToPtr()).ToArray();
|
||||
var ptrToPtrArray = ptrArray.ArrayPtr();
|
||||
var handle = Interface.move_data_new(name.ToPtr(), moveType, category, basePower, accuracy, baseUsages, target,
|
||||
priority, secondaryEffect?.Handle ?? FFIHandle.Zero, ptrToPtrArray,
|
||||
(ulong)ptrArray.Length);
|
||||
var handle = Interface.move_data_new(name.ToPtr(), moveType, category, basePower, accuracy, baseUsages,
|
||||
target, priority, secondaryEffect?.Handle ?? FFIHandle.Zero, ptrToPtrArray, (ulong)ptrArray.Length);
|
||||
return Resolver.Instance.ResolveMoveData(handle.Result().Resolve());
|
||||
}
|
||||
|
||||
private string? _name;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the move.
|
||||
/// </summary>
|
||||
public string Name => _name ??= Interface.move_data_name(Handle).Result().PtrString()!;
|
||||
|
||||
private TypeIdentifier? _type;
|
||||
|
||||
/// <summary>
|
||||
/// The attacking type of the move.
|
||||
/// </summary>
|
||||
public TypeIdentifier Type => _type ??= Interface.move_data_move_type(Handle);
|
||||
private byte? _basePower;
|
||||
public byte BasePower => _basePower ??= Interface.move_data_base_power(Handle);
|
||||
|
||||
private MoveCategory? _category;
|
||||
|
||||
/// <summary>
|
||||
/// The category of the move.
|
||||
/// </summary>
|
||||
public MoveCategory Category => _category ??= Interface.move_data_category(Handle);
|
||||
|
||||
private byte? _basePower;
|
||||
|
||||
/// <summary>
|
||||
/// The base power, not considering any modifiers, the move has.
|
||||
/// </summary>
|
||||
public byte BasePower => _basePower ??= Interface.move_data_base_power(Handle);
|
||||
|
||||
private byte? _accuracy;
|
||||
|
||||
/// <summary>
|
||||
/// The accuracy of the move in percentage. Should be 255 for moves that always hit.
|
||||
/// </summary>
|
||||
public byte Accuracy => _accuracy ??= Interface.move_data_accuracy(Handle);
|
||||
private byte? _baseUsages;
|
||||
|
||||
/// <summary>
|
||||
/// The number of times the move can be used. This can be modified on actually learned moves using
|
||||
/// PP-Ups
|
||||
/// </summary>
|
||||
public byte BaseUsages => _baseUsages ??= Interface.move_data_base_usages(Handle);
|
||||
private MoveTarget? _target;
|
||||
/// <summary>
|
||||
/// How the move handles targets.
|
||||
/// </summary>
|
||||
public MoveTarget Target => _target ??= Interface.move_data_target(Handle);
|
||||
private sbyte? _priority;
|
||||
/// <summary>
|
||||
/// The priority of the move. A higher priority means the move should go before other moves.
|
||||
/// </summary>
|
||||
public sbyte Priority => _priority ??= Interface.move_data_priority(Handle);
|
||||
|
||||
private SecondaryEffect? _secondaryEffect;
|
||||
|
||||
/// <summary>
|
||||
/// The optional secondary effect the move has.
|
||||
/// </summary>
|
||||
public SecondaryEffect? SecondaryEffect
|
||||
{
|
||||
get
|
||||
|
@ -108,6 +161,9 @@ namespace PkmnLibSharp.StaticData
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the move has a specific flag.
|
||||
/// </summary>
|
||||
public bool HasFlag(string flag)
|
||||
{
|
||||
return Interface.move_data_has_flag(Handle, flag.ToPtr()) == 1;
|
||||
|
|
|
@ -3,36 +3,59 @@ using Interface = PkmnLibSharp.FFI.StaticData.Nature;
|
|||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// A nature is an attribute on a Pokemon that modifies the effective base stats on a Pokemon. They
|
||||
/// can have an increased statistic and a decreased statistic, or be neutral.
|
||||
/// </summary>
|
||||
public class Nature : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="Nature"/>
|
||||
protected Nature(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new nature.
|
||||
/// </summary>
|
||||
public static Nature Create(Statistic increasedStat, Statistic decreasedStat, float increaseModifier = 1.1f,
|
||||
float decreaseModifier = 0.9f)
|
||||
{
|
||||
var handle = Interface.nature_new(increasedStat, decreasedStat, increaseModifier, decreaseModifier);
|
||||
return Resolver.Instance.ResolveNature(handle.Resolve());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new nature that does not modify any stats.
|
||||
/// </summary>
|
||||
public static Nature NeutralNature()
|
||||
{
|
||||
return Create(Statistic.HP, Statistic.HP, 1f, 1f);
|
||||
}
|
||||
|
||||
private Statistic? _increasedStat;
|
||||
|
||||
/// <summary>
|
||||
/// The stat that should receive the increased modifier.
|
||||
/// </summary>
|
||||
public Statistic IncreasedStat
|
||||
{
|
||||
get { return _increasedStat ??= Interface.nature_increased_stat(Handle); }
|
||||
}
|
||||
|
||||
private Statistic? _decreasedStat;
|
||||
|
||||
/// <summary>
|
||||
/// The stat that should receive the decreased modifier.
|
||||
/// </summary>
|
||||
public Statistic DecreasedStat
|
||||
{
|
||||
get { return _decreasedStat ??= Interface.nature_decreased_stat(Handle); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the modifier for a given stat. If it's the increased stat, returns the increased
|
||||
/// modifier, if it's the decreased stat, returns the decreased modifier. Otherwise returns 1.0
|
||||
/// </summary>
|
||||
public float GetStatModifier(Statistic statistic)
|
||||
{
|
||||
return Interface.nature_get_stat_modifier(Handle, statistic);
|
||||
|
|
|
@ -5,12 +5,19 @@ using Interface = PkmnLibSharp.FFI.StaticData.MoveData;
|
|||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// A secondary effect is an effect on a move that happens after it hits.
|
||||
/// </summary>
|
||||
public class SecondaryEffect : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="SecondaryEffect"/>
|
||||
protected SecondaryEffect(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new Secondary Effect.
|
||||
/// </summary>
|
||||
public static SecondaryEffect Create(float chance, string effectName, IReadOnlyList<EffectParameter> parameters)
|
||||
{
|
||||
var parameterPtrs = parameters.Select(x => (FFIHandleValue)x.Handle).ToArray();
|
||||
|
@ -23,11 +30,20 @@ namespace PkmnLibSharp.StaticData
|
|||
}
|
||||
|
||||
private float? _chance;
|
||||
/// <summary>
|
||||
/// The chance in percentages that the effect triggers. -1 to make it always trigger.
|
||||
/// </summary>
|
||||
public float Chance => _chance ??= Interface.secondary_effect_chance(Handle);
|
||||
|
||||
private string? _name;
|
||||
/// <summary>
|
||||
/// The name of the effect.
|
||||
/// </summary>
|
||||
public string Name => _name ??= Interface.secondary_effect_effect_name(Handle).Result().PtrString()!;
|
||||
|
||||
/// <summary>
|
||||
/// A list of parameters for the effect.
|
||||
/// </summary>
|
||||
public IReadOnlyList<EffectParameter> Parameters { get; private set; } = null!;
|
||||
}
|
||||
}
|
|
@ -7,14 +7,21 @@ using Interface = PkmnLibSharp.FFI.StaticData.Species;
|
|||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// The data belonging to a Pokemon with certain characteristics.
|
||||
/// </summary>
|
||||
public class Species : HandleType
|
||||
{
|
||||
/// <inheritdoc cref="Species"/>
|
||||
protected Species(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
public static Species Create(ushort id, string name, float genderRate, string growthRate, byte captureRate, Form defaultForm,
|
||||
IReadOnlyCollection<string> flags)
|
||||
/// <summary>
|
||||
/// Creates a new species.
|
||||
/// </summary>
|
||||
public static Species Create(ushort id, string name, float genderRate, string growthRate, byte captureRate,
|
||||
Form defaultForm, IReadOnlyCollection<string> flags)
|
||||
{
|
||||
var flagsPtrArray = flags.Select(x => x.ToPtr()).ToArray();
|
||||
var handle = Interface.species_new(id, name.ToPtr(), genderRate, growthRate.ToPtr(), captureRate,
|
||||
|
@ -25,16 +32,44 @@ namespace PkmnLibSharp.StaticData
|
|||
}
|
||||
|
||||
private ushort? _id;
|
||||
|
||||
/// <summary>
|
||||
/// The national dex identifier of the Pokemon.
|
||||
/// </summary>
|
||||
public ushort Id => _id ??= Interface.species_id(Handle);
|
||||
|
||||
private string? _name;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the Pokemon.
|
||||
/// </summary>
|
||||
public string Name => _name ??= Interface.species_name(Handle).PtrString()!;
|
||||
|
||||
private float? _genderRate;
|
||||
|
||||
/// <summary>
|
||||
/// The chance between 0.0 and 1.0 that a Pokemon is female.
|
||||
/// </summary>
|
||||
public float GenderRate => _genderRate ??= Interface.species_gender_rate(Handle);
|
||||
|
||||
private string? _growthRate;
|
||||
|
||||
/// <summary>
|
||||
/// How much experience is required for a level.
|
||||
/// </summary>
|
||||
public string GrowthRate => _growthRate ??= Interface.species_growth_rate(Handle).PtrString()!;
|
||||
|
||||
private byte? _captureRate;
|
||||
public byte CaptureRate => _captureRate ??= Interface.species_capture_rate(Handle);
|
||||
|
||||
/// <summary>
|
||||
/// How hard it is to capture a Pokemon. 255 means this will be always caught, 0 means this is
|
||||
/// uncatchable.
|
||||
/// </summary>
|
||||
public byte CaptureRate => _captureRate ??= Interface.species_capture_rate(Handle);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the form the Pokemon will have by default, if no other form is specified.
|
||||
/// </summary>
|
||||
public Form DefaultForm
|
||||
{
|
||||
get
|
||||
|
@ -44,7 +79,11 @@ namespace PkmnLibSharp.StaticData
|
|||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, Form> _forms = new(StringComparer.InvariantCultureIgnoreCase);
|
||||
private readonly Dictionary<string, Form> _forms = new(StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a form by name.
|
||||
/// </summary>
|
||||
public bool TryGetForm(string formName, [NotNullWhen(true)] out Form? form)
|
||||
{
|
||||
if (_forms.TryGetValue(formName, out form))
|
||||
|
@ -61,12 +100,19 @@ namespace PkmnLibSharp.StaticData
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new form to the species.
|
||||
/// </summary>
|
||||
/// <param name="form"></param>
|
||||
public void AddForm(Form form)
|
||||
{
|
||||
Interface.species_add_form(Handle, form.Name.ToPtr(), form.Handle).Result();
|
||||
_forms.Add(form.Name, form);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random gender, returning a value based on the species gender ratio.
|
||||
/// </summary>
|
||||
public Gender GetRandomGender(ulong seed) => Interface.species_get_random_gender(Handle, seed);
|
||||
}
|
||||
}
|
|
@ -5,13 +5,24 @@ using Interface = PkmnLibSharp.FFI.StaticData.StaticStatisticSet;
|
|||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of statistics that can not be modified after creation.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// The integer type that this statistic set will use. This type must be one of the following: ushort
|
||||
/// </typeparam>
|
||||
public class StaticStatisticSet<T> : HandleType where T : struct, IConvertible
|
||||
{
|
||||
/// <inheritdoc cref="StaticStatisticSet{T}"/>
|
||||
protected StaticStatisticSet(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
public static StaticStatisticSet<T> Create(T hp, T attack, T defense, T specialAttack, T specialDefense, T speed)
|
||||
/// <summary>
|
||||
/// Create a new static statistic set.
|
||||
/// </summary>
|
||||
public static StaticStatisticSet<T> Create(T hp, T attack, T defense, T specialAttack, T specialDefense,
|
||||
T speed)
|
||||
{
|
||||
var handle = typeof(T) switch
|
||||
{
|
||||
|
@ -23,6 +34,9 @@ namespace PkmnLibSharp.StaticData
|
|||
return Resolver.Instance.ResolveStaticStatisticSet<T>(handle.Resolve());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of a specific stat
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public T GetStatistic(Statistic statistic)
|
||||
{
|
||||
|
@ -73,22 +87,45 @@ namespace PkmnLibSharp.StaticData
|
|||
}
|
||||
|
||||
private T? _hp;
|
||||
|
||||
/// <summary>
|
||||
/// The health point stat value.
|
||||
/// </summary>
|
||||
public T HP => GetStatistic(Statistic.HP);
|
||||
|
||||
private T? _attack;
|
||||
|
||||
/// <summary>
|
||||
/// The physical attack stat value.
|
||||
/// </summary>
|
||||
public T Attack => GetStatistic(Statistic.Attack);
|
||||
|
||||
private T? _defense;
|
||||
|
||||
/// <summary>
|
||||
/// The physical defense stat value.
|
||||
/// </summary>
|
||||
public T Defense => GetStatistic(Statistic.Defense);
|
||||
|
||||
private T? _specialAttack;
|
||||
|
||||
/// <summary>
|
||||
/// The special attack stat value.
|
||||
/// </summary>
|
||||
public T SpecialAttack => GetStatistic(Statistic.SpecialAttack);
|
||||
|
||||
private T? _specialDefense;
|
||||
|
||||
/// <summary>
|
||||
/// The special defense stat value.
|
||||
/// </summary>
|
||||
public T SpecialDefense => GetStatistic(Statistic.SpecialDefense);
|
||||
|
||||
private T? _speed;
|
||||
|
||||
/// <summary>
|
||||
/// The speed stat value.
|
||||
/// </summary>
|
||||
public T Speed => GetStatistic(Statistic.Speed);
|
||||
|
||||
}
|
||||
}
|
|
@ -1,12 +1,38 @@
|
|||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// Stats are numerical values on Pokemon that are used in battle.
|
||||
/// </summary>
|
||||
public enum Statistic : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Health Points determine how much damage a Pokemon can receive before fainting.
|
||||
/// </summary>
|
||||
HP = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Attack determines how much damage a Pokemon deals when using a physical attack.
|
||||
/// </summary>
|
||||
Attack = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Defense determines how much damage a Pokemon receives when it is hit by a physical attack.
|
||||
/// </summary>
|
||||
Defense = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Special Attack determines how much damage a Pokemon deals when using a special attack.
|
||||
/// </summary>
|
||||
SpecialAttack = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Special Defense determines how much damage a Pokemon receives when it is hit by a special attack.
|
||||
/// </summary>
|
||||
SpecialDefense = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Speed determines the order that a Pokemon can act in battle.
|
||||
/// </summary>
|
||||
Speed = 5,
|
||||
}
|
||||
}
|
|
@ -5,12 +5,23 @@ using Interface = PkmnLibSharp.FFI.StaticData.StatisticSet;
|
|||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of every individual stat. This set can hold any value that is valid for its integer
|
||||
/// type, and can be modified at will.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// The integer type that this statistic set will use. This type must be one of the following: byte, sbyte, uint.
|
||||
/// </typeparam>
|
||||
public class StatisticSet<T> : HandleType where T : struct, IConvertible
|
||||
{
|
||||
/// <inheritdoc cref="StatisticSet{T}"/>
|
||||
protected StatisticSet(FFIHandle handle) : base(handle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new statistic set with given stats.
|
||||
/// </summary>
|
||||
public static StatisticSet<T> Create(T hp, T attack, T defense, T specialAttack, T specialDefense, T speed)
|
||||
{
|
||||
var handle = typeof(T) switch
|
||||
|
@ -29,6 +40,9 @@ namespace PkmnLibSharp.StaticData
|
|||
return Resolver.Instance.ResolveStatisticSet<T>(handle.Resolve());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of a specific stat
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public T GetStatistic(Statistic statistic)
|
||||
{
|
||||
|
@ -42,6 +56,9 @@ namespace PkmnLibSharp.StaticData
|
|||
return (T)p;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modify the value of a specific stat.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public void SetStatistic(Statistic statistic, T value)
|
||||
{
|
||||
|
@ -53,36 +70,54 @@ namespace PkmnLibSharp.StaticData
|
|||
else throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The health point stat value.
|
||||
/// </summary>
|
||||
public T HP
|
||||
{
|
||||
get => GetStatistic(Statistic.HP);
|
||||
set => SetStatistic(Statistic.HP, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The physical attack stat value.
|
||||
/// </summary>
|
||||
public T Attack
|
||||
{
|
||||
get => GetStatistic(Statistic.Attack);
|
||||
set => SetStatistic(Statistic.Attack, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The physical defense stat value.
|
||||
/// </summary>
|
||||
public T Defense
|
||||
{
|
||||
get => GetStatistic(Statistic.Defense);
|
||||
set => SetStatistic(Statistic.Defense, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The special attack stat value.
|
||||
/// </summary>
|
||||
public T SpecialAttack
|
||||
{
|
||||
get => GetStatistic(Statistic.SpecialAttack);
|
||||
set => SetStatistic(Statistic.SpecialAttack, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The special defense stat value.
|
||||
/// </summary>
|
||||
public T SpecialDefense
|
||||
{
|
||||
get => GetStatistic(Statistic.SpecialDefense);
|
||||
set => SetStatistic(Statistic.SpecialDefense, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The speed stat value.
|
||||
/// </summary>
|
||||
public T Speed
|
||||
{
|
||||
get => GetStatistic(Statistic.Speed);
|
||||
|
|
|
@ -1,43 +1,61 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PkmnLibSharp.StaticData
|
||||
{
|
||||
/// <summary>
|
||||
/// An identifier for a type. This is stored as a single byte internally, but is represented as a struct so that
|
||||
/// we can use the type system to ensure that we don't accidentally mix up type identifiers with other bytes.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public readonly struct TypeIdentifier
|
||||
public readonly struct TypeIdentifier : IEquatable<TypeIdentifier>
|
||||
{
|
||||
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
|
||||
[FieldOffset(0)] private readonly byte _identifier;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new type identifier.
|
||||
/// </summary>
|
||||
public TypeIdentifier(byte b)
|
||||
{
|
||||
_identifier = b;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(TypeIdentifier other)
|
||||
{
|
||||
return _identifier == other._identifier;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is TypeIdentifier other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _identifier.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Equality operator for type identifiers.
|
||||
/// </summary>
|
||||
public static bool operator ==(TypeIdentifier left, TypeIdentifier right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inequality operator for type identifiers.
|
||||
/// </summary>
|
||||
public static bool operator !=(TypeIdentifier left, TypeIdentifier right)
|
||||
{
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Type({_identifier})";
|
||||
|
|
|
@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
|
|||
|
||||
namespace PkmnLibSharp.Utils
|
||||
{
|
||||
public sealed class CachedExternArray<T> : IReadOnlyList<T>
|
||||
internal sealed class CachedExternArray<T> : IReadOnlyList<T>
|
||||
where T: class
|
||||
{
|
||||
private readonly T?[] _array;
|
||||
|
@ -50,7 +50,7 @@ namespace PkmnLibSharp.Utils
|
|||
}
|
||||
|
||||
|
||||
public class CachedExternValueArray<T> : IReadOnlyList<T>
|
||||
internal class CachedExternValueArray<T> : IReadOnlyList<T>
|
||||
where T: struct
|
||||
{
|
||||
private readonly T?[] _array;
|
||||
|
|
|
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
|||
|
||||
namespace PkmnLibSharp.Utils
|
||||
{
|
||||
public class ExternValueArray<T> : IReadOnlyList<T> where T : struct
|
||||
internal class ExternValueArray<T> : IReadOnlyList<T>
|
||||
{
|
||||
private readonly Func<ulong> _getLength;
|
||||
private readonly Func<ulong, T> _getItem;
|
||||
|
|
|
@ -60,6 +60,9 @@ namespace PkmnLibSharp.Utils
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A handle to a native object.
|
||||
/// </summary>
|
||||
public struct FFIHandle
|
||||
{
|
||||
internal FFIHandle(ulong handle, FFIHandleReference handleReference)
|
||||
|
@ -68,7 +71,11 @@ namespace PkmnLibSharp.Utils
|
|||
_handleReference = handleReference;
|
||||
}
|
||||
|
||||
public ulong Handle { get; }
|
||||
internal ulong Handle { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A handle with a value of 0, which is the null handle.
|
||||
/// </summary>
|
||||
public static FFIHandle Zero => new(0, null!);
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,12 +1,22 @@
|
|||
using JetBrains.Annotations;
|
||||
|
||||
namespace PkmnLibSharp.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// A basic type that holds a handle to a native object.
|
||||
/// </summary>
|
||||
[UsedImplicitly(ImplicitUseTargetFlags.Default | ImplicitUseTargetFlags.WithInheritors)]
|
||||
public abstract class HandleType
|
||||
{
|
||||
/// <inheritdoc cref="HandleType"/>
|
||||
protected internal HandleType(FFIHandle handle)
|
||||
{
|
||||
Handle = handle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The internal handle to the native object.
|
||||
/// </summary>
|
||||
protected internal FFIHandle Handle { get; }
|
||||
}
|
||||
}
|
|
@ -3,17 +3,31 @@ using System.Collections.Generic;
|
|||
using System.Reflection;
|
||||
using PkmnLibSharp.DynamicData;
|
||||
using PkmnLibSharp.DynamicData.Libraries;
|
||||
using PkmnLibSharp.FFI;
|
||||
using PkmnLibSharp.StaticData;
|
||||
using PkmnLibSharp.StaticData.Libraries;
|
||||
|
||||
namespace PkmnLibSharp.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is used to resolve FFIHandles to their respective classes. We use this so we can handle inheritance
|
||||
/// in our objects. By overriding a method in this class, we can return a different object than the default throughout
|
||||
/// the library.
|
||||
///
|
||||
/// This class is a singleton, so you can replace the default resolver with your own by setting the Instance property.
|
||||
/// </summary>
|
||||
public class Resolver
|
||||
{
|
||||
/// <summary>
|
||||
/// The global resolver instance. This is used throughout the library to resolve FFIHandles to their respective
|
||||
/// classes.
|
||||
/// </summary>
|
||||
public static Resolver Instance { get; set; } = new();
|
||||
|
||||
private static readonly Dictionary<FFIHandle, object> Instances = new();
|
||||
|
||||
/// <summary>
|
||||
/// Either returns an existing instance of the given type, or creates a new one and returns it.
|
||||
/// </summary>
|
||||
protected static T GetOrCreateInstance<T>(FFIHandle handle)
|
||||
{
|
||||
if (!Instances.TryGetValue(handle, out var instance))
|
||||
|
@ -28,79 +42,177 @@ namespace PkmnLibSharp.Utils
|
|||
return (T)instance!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolve an effect parameter from the given handle.
|
||||
/// </summary>
|
||||
public virtual EffectParameter ResolveEffectParameter(FFIHandle handle) =>
|
||||
GetOrCreateInstance<EffectParameter>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a move effect from the given handle.
|
||||
/// </summary>
|
||||
public virtual Ability ResolveAbility(FFIHandle handle) => GetOrCreateInstance<Ability>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a form from the given handle.
|
||||
/// </summary>
|
||||
public virtual Form ResolveForm(FFIHandle handle) => GetOrCreateInstance<Form>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a static statistic set from the given handle.
|
||||
/// </summary>
|
||||
public virtual StaticStatisticSet<T> ResolveStaticStatisticSet<T>(FFIHandle handle)
|
||||
where T : struct, IConvertible =>
|
||||
GetOrCreateInstance<StaticStatisticSet<T>>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a statistic set from the given handle.
|
||||
/// </summary>
|
||||
public virtual StatisticSet<T> ResolveStatisticSet<T>(FFIHandle handle) where T : struct, IConvertible =>
|
||||
GetOrCreateInstance<StatisticSet<T>>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a learnable moves object from the given handle.
|
||||
/// </summary>
|
||||
public virtual LearnableMoves ResolveLearnableMoves(FFIHandle handle) =>
|
||||
GetOrCreateInstance<LearnableMoves>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve an item object from the given handle.
|
||||
/// </summary>
|
||||
public virtual Item ResolveItem(FFIHandle handle) => GetOrCreateInstance<Item>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a secondary effect object from the given handle.
|
||||
/// </summary>
|
||||
public virtual SecondaryEffect ResolveSecondaryEffect(FFIHandle handle) =>
|
||||
GetOrCreateInstance<SecondaryEffect>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a move data object from the given handle.
|
||||
/// </summary>
|
||||
public virtual MoveData ResolveMoveData(FFIHandle handle) => GetOrCreateInstance<MoveData>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve an nature from the given handle.
|
||||
/// </summary>
|
||||
public virtual Nature ResolveNature(FFIHandle handle) => GetOrCreateInstance<Nature>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a species object from the given handle.
|
||||
/// </summary>
|
||||
public virtual Species ResolveSpecies(FFIHandle handle) => GetOrCreateInstance<Species>(handle);
|
||||
|
||||
public virtual AbilityLibrary ResolveAbilityLibrary(FFIHandle handle) =>
|
||||
GetOrCreateInstance<AbilityLibrary>(handle);
|
||||
|
||||
public virtual ItemLibrary ResolveItemLibrary(FFIHandle handle) => GetOrCreateInstance<ItemLibrary>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a growthrate object from the given handle.
|
||||
/// </summary>
|
||||
public virtual LookupGrowthRate ResolveLookupGrowthRate(FFIHandle ptr) =>
|
||||
GetOrCreateInstance<LookupGrowthRate>(ptr);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve an ability library object from the given handle.
|
||||
/// </summary>
|
||||
public virtual AbilityLibrary ResolveAbilityLibrary(FFIHandle handle) =>
|
||||
GetOrCreateInstance<AbilityLibrary>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve an item library object from the given handle.
|
||||
/// </summary>
|
||||
public virtual ItemLibrary ResolveItemLibrary(FFIHandle handle) => GetOrCreateInstance<ItemLibrary>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a growthrate library object from the given handle.
|
||||
/// </summary>
|
||||
public virtual GrowthRateLibrary ResolveGrowthRateLibrary(FFIHandle handle) =>
|
||||
GetOrCreateInstance<GrowthRateLibrary>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a move library object from the given handle.
|
||||
/// </summary>
|
||||
public virtual MoveLibrary ResolveMoveLibrary(FFIHandle handle) => GetOrCreateInstance<MoveLibrary>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a nature library object from the given handle.
|
||||
/// </summary>
|
||||
public virtual NatureLibrary ResolveNatureLibrary(FFIHandle handle) =>
|
||||
GetOrCreateInstance<NatureLibrary>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a species library object from the given handle.
|
||||
/// </summary>
|
||||
public virtual SpeciesLibrary ResolveSpeciesLibrary(FFIHandle handle) =>
|
||||
GetOrCreateInstance<SpeciesLibrary>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a library settings object from the given handle.
|
||||
/// </summary>
|
||||
public virtual LibrarySettings ResolveLibrarySettings(FFIHandle handle) =>
|
||||
GetOrCreateInstance<LibrarySettings>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a type library object from the given handle.
|
||||
/// </summary>
|
||||
public virtual TypeLibrary ResolveTypeLibrary(FFIHandle handle) => GetOrCreateInstance<TypeLibrary>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a static data object from the given handle.
|
||||
/// </summary>
|
||||
public virtual StaticData.Libraries.StaticData ResolveStaticData(FFIHandle handle) =>
|
||||
GetOrCreateInstance<StaticData.Libraries.StaticData>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a learned move object from the given handle.
|
||||
/// </summary>
|
||||
public virtual LearnedMove ResolveLearnedMove(FFIHandle resolve) => GetOrCreateInstance<LearnedMove>(resolve);
|
||||
|
||||
public virtual Gen7BattleStatCalculator ResolveGen7BattleStatCalculator(FFIHandle handle) =>
|
||||
/// <summary>
|
||||
/// Resolve a battle stat calculator object from the given handle.
|
||||
/// </summary>
|
||||
public virtual BattleStatCalculator ResolveBattleStatCalculator(FFIHandle handle) =>
|
||||
GetOrCreateInstance<Gen7BattleStatCalculator>(handle);
|
||||
|
||||
public virtual Gen7DamageLibrary ResolveGen7DamageLibrary(FFIHandle handle) =>
|
||||
/// <summary>
|
||||
/// Resolve a damage library object from the given handle.
|
||||
/// </summary>
|
||||
public virtual DamageLibrary ResolveDamageLibrary(FFIHandle handle) =>
|
||||
GetOrCreateInstance<Gen7DamageLibrary>(handle);
|
||||
|
||||
public virtual Gen7MiscLibrary ResolveGen7MiscLibrary(FFIHandle handle) =>
|
||||
GetOrCreateInstance<Gen7MiscLibrary>(handle);
|
||||
/// <summary>
|
||||
/// Resolve a misc library object from the given handle.
|
||||
/// </summary>
|
||||
public virtual MiscLibrary ResolveMiscLibrary(FFIHandle handle) => GetOrCreateInstance<Gen7MiscLibrary>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve an empty script resolver object from the given handle.
|
||||
/// </summary>
|
||||
public virtual EmptyScriptResolver ResolveEmptyScriptResolver(FFIHandle handle) =>
|
||||
GetOrCreateInstance<EmptyScriptResolver>(handle);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a script resolver object from the given handle.
|
||||
/// </summary>
|
||||
#if WASM
|
||||
public virtual WasmScriptResolver ResolveWasmScriptResolver(FFIHandle handle) =>
|
||||
public virtual ScriptResolver ResolveScriptResolver(FFIHandle handle) =>
|
||||
GetOrCreateInstance<WasmScriptResolver>(handle);
|
||||
#else
|
||||
public virtual ScriptResolver ResolveScriptResolver(FFIHandle handle) => ResolveEmptyScriptResolver(handle);
|
||||
#endif
|
||||
public DynamicLibrary ResolveDynamicLibrary(FFIHandle resolve) => GetOrCreateInstance<DynamicLibrary>(resolve);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a dynamic library object from the given handle.
|
||||
/// </summary>
|
||||
public virtual DynamicLibrary ResolveDynamicLibrary(FFIHandle resolve) =>
|
||||
GetOrCreateInstance<DynamicLibrary>(resolve);
|
||||
|
||||
public Pokemon ResolvePokemon(FFIHandle resolve) => GetOrCreateInstance<Pokemon>(resolve);
|
||||
/// <summary>
|
||||
/// Resolve a pokemon object from the given handle.
|
||||
/// </summary>
|
||||
public virtual Pokemon ResolvePokemon(FFIHandle resolve) => GetOrCreateInstance<Pokemon>(resolve);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a pokemon party object from the given handle.
|
||||
/// </summary>
|
||||
public virtual PokemonParty ResolvePokemonParty(FFIHandle resolve) =>
|
||||
GetOrCreateInstance<PokemonParty>(resolve);
|
||||
}
|
||||
}
|
BIN
PkmnLibRSharp/libpkmn_lib.so (Stored with Git LFS)
BIN
PkmnLibRSharp/libpkmn_lib.so (Stored with Git LFS)
Binary file not shown.
|
@ -72,7 +72,7 @@ namespace PkmnLibRSharpTests.DynamicData
|
|||
{
|
||||
var library = GetLibrary();
|
||||
var pokemon = new PokemonBuilder(library, "testSpecies", 100).WithIdentifier(1000).Build();
|
||||
Assert.AreEqual(1000, pokemon.UniqueIdentifier);
|
||||
Assert.AreEqual(1000, pokemon.PersonalityValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
Loading…
Reference in New Issue