561 lines
20 KiB
C#
561 lines
20 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using PkmnLibSharp.Library;
|
|
using PkmnLibSharp.Utilities;
|
|
using Item = PkmnLibSharp.Library.Items.Item;
|
|
using Nature = PkmnLibSharp.Library.Nature;
|
|
|
|
namespace PkmnLibSharp.Battling
|
|
{
|
|
public class Pokemon : PointerWrapper
|
|
{
|
|
protected internal override void Initialize(IntPtr ptr)
|
|
{
|
|
base.Initialize(ptr);
|
|
if (Library == null)
|
|
Library = new BattleLibrary(Creaturelib.Generated.Creature.GetLibrary(ptr));
|
|
}
|
|
|
|
public Pokemon(BattleLibrary library, Species species, Forme forme, byte level, uint experience, uint uid,
|
|
Gender gender, byte coloring, Item? heldItem, string? nickname, bool hiddenAbility, byte abilityIndex,
|
|
IReadOnlyCollection<LearnedMove> moves, StatisticSet<byte> ivs, StatisticSet<byte> evs, Nature nature,
|
|
bool allowedExperienceGain = true, bool isEgg = false) : base(CreatePtr(library, species, forme, level,
|
|
experience, uid, gender, coloring, heldItem, nickname, hiddenAbility, abilityIndex, moves, ivs, evs, nature,
|
|
allowedExperienceGain, isEgg))
|
|
{
|
|
Library = library;
|
|
Initialize();
|
|
}
|
|
|
|
protected static IntPtr CreatePtr(BattleLibrary library, Species species, Forme forme, byte level,
|
|
uint experience, uint uid, Gender gender, byte coloring, Item? heldItem, string? nickname,
|
|
bool hiddenAbility, byte abilityIndex, IReadOnlyCollection<LearnedMove> moves, StatisticSet<byte> ivs,
|
|
StatisticSet<byte> evs, Nature nature, bool allowedExperienceGain, bool isEgg)
|
|
{
|
|
var movesArr = moves.Select(x => x?.Ptr ?? IntPtr.Zero).ToArray();
|
|
|
|
var libraryPtr = library.Ptr;
|
|
var speciesPtr = species.Ptr;
|
|
var formePtr = forme.Ptr;
|
|
var heldItemPtr = heldItem?.Ptr;
|
|
var nicknamePtr = nickname.ToPtr();
|
|
var naturePtr = nature.Ptr;
|
|
|
|
var ptr = IntPtr.Zero;
|
|
Pkmnlib.Generated.Pokemon.Construct(ref ptr, libraryPtr, speciesPtr, formePtr, level, experience, uid,
|
|
(Pkmnlib.Gender) gender, coloring, heldItemPtr ?? IntPtr.Zero, nicknamePtr, hiddenAbility.ToNative(),
|
|
abilityIndex, movesArr.ArrayPtr(), (ulong) moves.Count, ivs.HP, ivs.Attack, ivs.Defense,
|
|
ivs.SpecialAttack, ivs.SpecialDefense, ivs.Speed, evs.HP, evs.Attack, evs.Defense, evs.SpecialAttack,
|
|
evs.SpecialDefense, evs.Speed, naturePtr, allowedExperienceGain.ToNative(), isEgg.ToNative()).Assert();
|
|
return ptr;
|
|
}
|
|
|
|
public BattleLibrary Library { get; private set; }
|
|
|
|
public Species Species
|
|
{
|
|
get
|
|
{
|
|
if (_species != null) return _species;
|
|
var ptr = Creaturelib.Generated.Creature.GetSpecies(Ptr);
|
|
if (TryResolvePointer(ptr, out _species))
|
|
return _species!;
|
|
_species = Constructor.Active.ConstructSpecies(ptr)!;
|
|
return _species;
|
|
}
|
|
}
|
|
|
|
public Forme Forme
|
|
{
|
|
get
|
|
{
|
|
if (_forme != null) return _forme;
|
|
var ptr = Creaturelib.Generated.Creature.GetVariant(Ptr);
|
|
if (TryResolvePointer(ptr, out _forme))
|
|
return _forme!;
|
|
_forme = Constructor.Active.ConstructForme(ptr)!;
|
|
return _forme;
|
|
}
|
|
}
|
|
|
|
public Species? DisplaySpecies
|
|
{
|
|
get
|
|
{
|
|
if (_displaySpecies != null) return _displaySpecies;
|
|
var ptr = Creaturelib.Generated.Creature.GetDisplaySpecies(Ptr);
|
|
if (TryResolvePointer(ptr, out _displaySpecies))
|
|
return _displaySpecies;
|
|
_displaySpecies = Constructor.Active.ConstructSpecies(ptr);
|
|
return _displaySpecies;
|
|
}
|
|
set => Creaturelib.Generated.Creature.SetDisplaySpecies(Ptr, value?.Ptr ?? IntPtr.Zero);
|
|
}
|
|
|
|
public Forme? DisplayForme
|
|
{
|
|
get
|
|
{
|
|
if (_displayForme != null) return _displayForme;
|
|
var ptr = Creaturelib.Generated.Creature.GetDisplayVariant(Ptr);
|
|
if (TryResolvePointer(ptr, out _displayForme))
|
|
return _displayForme;
|
|
_displayForme = Constructor.Active.ConstructForme(ptr)!;
|
|
return _displayForme;
|
|
}
|
|
set => Creaturelib.Generated.Creature.SetDisplayVariant(Ptr, value?.Ptr ?? IntPtr.Zero);
|
|
}
|
|
|
|
public bool AllowedExperienceGain
|
|
{
|
|
get => Creaturelib.Generated.Creature.AllowedExperienceGain(Ptr) == 1;
|
|
set => Creaturelib.Generated.Creature.SetAllowedExperienceGain(Ptr, value.ToNative());
|
|
}
|
|
|
|
public byte Level => Creaturelib.Generated.Creature.GetLevel(Ptr);
|
|
public uint Experience => Creaturelib.Generated.Creature.GetExperience(Ptr);
|
|
public uint UniqueIdentifier => Creaturelib.Generated.Creature.GetUniqueIdentifier(Ptr);
|
|
public Gender Gender => (Gender) Creaturelib.Generated.Creature.GetGender(Ptr);
|
|
public byte Coloring => Creaturelib.Generated.Creature.GetColoring(Ptr);
|
|
public bool IsShiny => Pkmnlib.Generated.Pokemon.IsShiny(Ptr) == 1;
|
|
public uint CurrentHealth => Creaturelib.Generated.Creature.GetCurrentHealth(Ptr);
|
|
public uint MaxHealth => Creaturelib.Generated.Creature.GetMaxHealth(Ptr);
|
|
|
|
public byte Friendship
|
|
{
|
|
get => Pkmnlib.Generated.Pokemon.GetFriendship(Ptr);
|
|
set => Pkmnlib.Generated.Pokemon.SetFriendship(Ptr, value);
|
|
}
|
|
|
|
public bool IsActualAbilityHidden => Creaturelib.Generated.Creature.GetRealTalentIsSecret(Ptr) == 1;
|
|
public byte ActualAbilityIndex => Creaturelib.Generated.Creature.GetRealTalentIndex(Ptr);
|
|
|
|
public string? ActiveAbility
|
|
{
|
|
get
|
|
{
|
|
var ptr = IntPtr.Zero;
|
|
Creaturelib.Generated.Creature.GetActiveTalent(Ptr, ref ptr).Assert();
|
|
return ptr.PtrString();
|
|
}
|
|
}
|
|
|
|
public Battle? Battle
|
|
{
|
|
get
|
|
{
|
|
var ptr = Creaturelib.Generated.Creature.GetBattle(Ptr);
|
|
if (_battle != null && !_battle.IsDeleted && _battle.Ptr == ptr) return _battle;
|
|
if (TryResolvePointer(ptr, out _battle))
|
|
return _battle;
|
|
_battle = Constructor.Active.ConstructBattle(ptr);
|
|
return _battle;
|
|
}
|
|
}
|
|
|
|
public BattleSide? BattleSide
|
|
{
|
|
get
|
|
{
|
|
var ptr = Creaturelib.Generated.Creature.GetBattleSide(Ptr);
|
|
if (_battleSide != null && !_battleSide.IsDeleted && _battleSide.Ptr == ptr) return _battleSide;
|
|
if (TryResolvePointer(ptr, out _battleSide))
|
|
return _battleSide;
|
|
_battleSide = new BattleSide(ptr);
|
|
return _battleSide;
|
|
}
|
|
}
|
|
|
|
public bool IsOnBattleField => Creaturelib.Generated.Creature.IsOnBattleField(Ptr) == 1;
|
|
|
|
public Item? HeldItem
|
|
{
|
|
get
|
|
{
|
|
var ptr = Creaturelib.Generated.Creature.GetHeldItem(Ptr);
|
|
if (ptr == IntPtr.Zero) return null;
|
|
if (!TryResolvePointer(ptr, out Item? item))
|
|
{
|
|
item = Constructor.Active.ConstructItem(ptr);
|
|
}
|
|
|
|
return item;
|
|
}
|
|
set => Creaturelib.Generated.Creature.SetHeldItemFromItem(Ptr, value?.Ptr ?? IntPtr.Zero);
|
|
}
|
|
|
|
public virtual string? Nickname
|
|
{
|
|
get
|
|
{
|
|
if (_nickname != null) return _nickname;
|
|
_nickname = Creaturelib.Generated.Creature.GetNickname(Ptr).PtrString();
|
|
return _nickname;
|
|
}
|
|
set
|
|
{
|
|
Creaturelib.Generated.Creature.SetNickname(Ptr, value.ToPtr());
|
|
// Clear cache.
|
|
_nickname = null;
|
|
}
|
|
}
|
|
|
|
public bool IsEgg
|
|
{
|
|
get => Pkmnlib.Generated.Pokemon.IsEgg(Ptr) == 1;
|
|
set => Pkmnlib.Generated.Pokemon.SetIsEgg(Ptr, value.ToNative());
|
|
}
|
|
|
|
public ReadOnlyNativePtrArray<LearnedMove> Moves
|
|
{
|
|
get
|
|
{
|
|
if (_moves != null) return _moves;
|
|
var movesLength = Creaturelib.Generated.Creature.GetAttacksCount(Ptr);
|
|
var movesPtr = Creaturelib.Generated.Creature.GetAttacks(Ptr);
|
|
_moves = new ReadOnlyNativePtrArray<LearnedMove>(movesPtr, (int) movesLength,
|
|
Constructor.GenericType.LearnedMove);
|
|
return _moves;
|
|
}
|
|
}
|
|
|
|
public byte[] Types
|
|
{
|
|
get
|
|
{
|
|
var typesLength = Creaturelib.Generated.Creature.GetTypeCount(Ptr);
|
|
var typePtr = Creaturelib.Generated.Creature.GetTypes(Ptr);
|
|
byte[] managedArray = new byte[typesLength];
|
|
Marshal.Copy(typePtr, managedArray, 0, (int) typesLength);
|
|
return managedArray;
|
|
}
|
|
}
|
|
|
|
public sbyte HpBoost => GetStatBoost(Statistic.Health);
|
|
public sbyte AttackBoost => GetStatBoost(Statistic.Attack);
|
|
public sbyte DefenseBoost => GetStatBoost(Statistic.Defense);
|
|
public sbyte SpecialAttackBoost => GetStatBoost(Statistic.SpecialAttack);
|
|
public sbyte SpecialDefenseBoost => GetStatBoost(Statistic.SpecialDefense);
|
|
public sbyte SpeedBoost => GetStatBoost(Statistic.Speed);
|
|
|
|
public uint BaseHp => GetBaseStat(Statistic.Health);
|
|
public uint BaseAttack => GetBaseStat(Statistic.Attack);
|
|
public uint BaseDefense => GetBaseStat(Statistic.Defense);
|
|
public uint BaseSpecialAttack => GetBaseStat(Statistic.SpecialAttack);
|
|
public uint BaseSpecialDefense => GetBaseStat(Statistic.SpecialDefense);
|
|
public uint BaseSpeed => GetBaseStat(Statistic.Speed);
|
|
|
|
public uint FlatHp => GetFlatStat(Statistic.Health);
|
|
public uint FlatAttack => GetFlatStat(Statistic.Attack);
|
|
public uint FlatDefense => GetFlatStat(Statistic.Defense);
|
|
public uint FlatSpecialAttack => GetFlatStat(Statistic.SpecialAttack);
|
|
public uint FlatSpecialDefense => GetFlatStat(Statistic.SpecialDefense);
|
|
public uint FlatSpeed => GetFlatStat(Statistic.Speed);
|
|
|
|
public uint BoostedHp => GetBoostedStat(Statistic.Health);
|
|
public uint BoostedAttack => GetBoostedStat(Statistic.Attack);
|
|
public uint BoostedDefense => GetBoostedStat(Statistic.Defense);
|
|
public uint BoostedSpecialAttack => GetBoostedStat(Statistic.SpecialAttack);
|
|
public uint BoostedSpecialDefense => GetBoostedStat(Statistic.SpecialDefense);
|
|
public uint BoostedSpeed => GetBoostedStat(Statistic.Speed);
|
|
|
|
public byte HpIv
|
|
{
|
|
get => GetIndividualValue(Statistic.Health);
|
|
set => SetEffortValue(Statistic.Health, value);
|
|
}
|
|
|
|
public byte AttackIv
|
|
{
|
|
get => GetIndividualValue(Statistic.Attack);
|
|
set => SetEffortValue(Statistic.Attack, value);
|
|
}
|
|
|
|
public byte DefenseIv
|
|
{
|
|
get => GetIndividualValue(Statistic.Defense);
|
|
set => SetEffortValue(Statistic.Defense, value);
|
|
}
|
|
|
|
public byte SpecialAttackIv
|
|
{
|
|
get => GetIndividualValue(Statistic.SpecialAttack);
|
|
set => SetEffortValue(Statistic.SpecialAttack, value);
|
|
}
|
|
|
|
public byte SpecialDefenseIv
|
|
{
|
|
get => GetIndividualValue(Statistic.SpecialDefense);
|
|
set => SetEffortValue(Statistic.SpecialDefense, value);
|
|
}
|
|
|
|
public byte SpeedIv
|
|
{
|
|
get => GetIndividualValue(Statistic.Speed);
|
|
set => SetEffortValue(Statistic.Speed, value);
|
|
}
|
|
|
|
public byte HpEv
|
|
{
|
|
get => GetEffortValue(Statistic.Health);
|
|
set => SetEffortValue(Statistic.Health, value);
|
|
}
|
|
|
|
public byte AttackEv
|
|
{
|
|
get => GetEffortValue(Statistic.Attack);
|
|
set => SetEffortValue(Statistic.Attack, value);
|
|
}
|
|
|
|
public byte DefenseEv
|
|
{
|
|
get => GetEffortValue(Statistic.Defense);
|
|
set => SetEffortValue(Statistic.Defense, value);
|
|
}
|
|
|
|
public byte SpecialAttackEv
|
|
{
|
|
get => GetEffortValue(Statistic.SpecialAttack);
|
|
set => SetEffortValue(Statistic.SpecialAttack, value);
|
|
}
|
|
|
|
public byte SpecialDefenseEv
|
|
{
|
|
get => GetEffortValue(Statistic.SpecialDefense);
|
|
set => SetEffortValue(Statistic.SpecialDefense, value);
|
|
}
|
|
|
|
public byte SpeedEv
|
|
{
|
|
get => GetEffortValue(Statistic.Speed);
|
|
set => SetEffortValue(Statistic.Speed, value);
|
|
}
|
|
|
|
public Nature Nature
|
|
{
|
|
get
|
|
{
|
|
if (_nature != null) return _nature;
|
|
var ptr = Pkmnlib.Generated.Pokemon.GetNature(Ptr);
|
|
if (TryResolvePointer(ptr, out _nature))
|
|
return _nature!;
|
|
_nature = new Nature(ptr);
|
|
return _nature;
|
|
}
|
|
}
|
|
|
|
public string? StatusName => Creaturelib.Generated.Creature.GetStatusName(Ptr).PtrString();
|
|
|
|
public void Initialize()
|
|
{
|
|
Creaturelib.Generated.Creature.Initialize(Ptr).Assert();
|
|
}
|
|
|
|
public void ChangeForme(Forme forme)
|
|
{
|
|
_forme = null;
|
|
Creaturelib.Generated.Creature.ChangeVariant(Ptr, forme.Ptr);
|
|
}
|
|
|
|
public bool HasHeldItem(string itemName)
|
|
{
|
|
return Creaturelib.Generated.Creature.HasHeldItem(Ptr, itemName.ToPtr()) == 1;
|
|
}
|
|
|
|
public void SetHeldItem(string item)
|
|
{
|
|
if (string.IsNullOrEmpty(item))
|
|
Creaturelib.Generated.Creature.SetHeldItemFromItem(Ptr, IntPtr.Zero);
|
|
else
|
|
Creaturelib.Generated.Creature.SetHeldItem(Ptr, item.ToPtr());
|
|
}
|
|
|
|
public bool HasType(string type)
|
|
{
|
|
var typeByte = Library.StaticLibrary.TypeLibrary.GetTypeId(type);
|
|
return Creaturelib.Generated.Creature.HasType(Ptr, typeByte) == 1;
|
|
}
|
|
|
|
public void ChangeLevelBy(sbyte amount)
|
|
{
|
|
Creaturelib.Generated.Creature.ChangeLevelBy(Ptr, amount).Assert();
|
|
}
|
|
|
|
public void AddExperience(uint experience)
|
|
{
|
|
Creaturelib.Generated.Creature.AddExperience(Ptr, experience).Assert();
|
|
}
|
|
|
|
public void Damage(uint damage, DamageSource source)
|
|
{
|
|
Creaturelib.Generated.Creature.Damage(Ptr, damage, (Creaturelib.DamageSource) source);
|
|
}
|
|
|
|
public void Heal(uint amount, bool canRevive)
|
|
{
|
|
Creaturelib.Generated.Creature.Heal(Ptr, amount, canRevive.ToNative()).Assert();
|
|
}
|
|
|
|
public void RestoreAllPP()
|
|
{
|
|
Creaturelib.Generated.Creature.RestoreAllAttackUses(Ptr);
|
|
}
|
|
|
|
public void OverrideActiveAbility(string ability)
|
|
{
|
|
Creaturelib.Generated.Creature.OverrideActiveTalent(Ptr, ability.ToPtr()).Assert();
|
|
}
|
|
|
|
public void ClearVolatileScripts()
|
|
{
|
|
Creaturelib.Generated.Creature.ClearVolatileScripts(Ptr).Assert();
|
|
}
|
|
|
|
public void AddVolatileScript(string scriptName)
|
|
{
|
|
Creaturelib.Generated.Creature.AddVolatileScriptByName(Ptr, scriptName.ToPtr()).Assert();
|
|
}
|
|
|
|
public void AddVolatileScript(Script script)
|
|
{
|
|
Creaturelib.Generated.Creature.AddVolatileScript(Ptr, script.Ptr).Assert();
|
|
}
|
|
|
|
public void RemoveVolatileScript(string scriptName)
|
|
{
|
|
Creaturelib.Generated.Creature.RemoveVolatileScriptByName(Ptr, scriptName.ToPtr()).Assert();
|
|
}
|
|
|
|
public void RemoveVolatileScript(Script script)
|
|
{
|
|
Creaturelib.Generated.Creature.RemoveVolatileScript(Ptr, script.Ptr).Assert();
|
|
}
|
|
|
|
public bool HasVolatileScript(string scriptName)
|
|
{
|
|
return Creaturelib.Generated.Creature.HasVolatileScript(Ptr, scriptName.ToPtr()) == 1;
|
|
}
|
|
|
|
public bool HasMove(string moveName)
|
|
{
|
|
return Creaturelib.Generated.Creature.HasAttack(Ptr, moveName.ToPtr()) == 1;
|
|
}
|
|
|
|
public sbyte GetStatBoost(Statistic stat)
|
|
{
|
|
return Creaturelib.Generated.Creature.GetStatBoost(Ptr, (Creaturelib.Statistic) stat);
|
|
}
|
|
|
|
public void ChangeStatBoost(Statistic stat, sbyte amount)
|
|
{
|
|
Creaturelib.Generated.Creature.ChangeStatBoost(Ptr, (Creaturelib.Statistic) stat, amount);
|
|
}
|
|
|
|
public uint GetBaseStat(Statistic stat)
|
|
{
|
|
return Creaturelib.Generated.Creature.GetBaseStat(Ptr, (Creaturelib.Statistic) stat);
|
|
}
|
|
|
|
public uint GetFlatStat(Statistic stat)
|
|
{
|
|
return Creaturelib.Generated.Creature.GetFlatStat(Ptr, (Creaturelib.Statistic) stat);
|
|
}
|
|
|
|
public uint GetBoostedStat(Statistic stat)
|
|
{
|
|
return Creaturelib.Generated.Creature.GetBoostedStat(Ptr, (Creaturelib.Statistic) stat);
|
|
}
|
|
|
|
public byte GetIndividualValue(Statistic stat)
|
|
{
|
|
return Pkmnlib.Generated.Pokemon.GetIndividualValue(Ptr, (Pkmnlib.Statistic) stat);
|
|
}
|
|
|
|
public void SetIndividualValue(Statistic stat, byte value)
|
|
{
|
|
Pkmnlib.Generated.Pokemon.SetIndividualValue(Ptr, (Pkmnlib.Statistic) stat, value);
|
|
}
|
|
|
|
public byte GetEffortValue(Statistic stat)
|
|
{
|
|
return Pkmnlib.Generated.Pokemon.GetEffortValue(Ptr, (Pkmnlib.Statistic) stat);
|
|
}
|
|
|
|
public void SetEffortValue(Statistic stat, byte value)
|
|
{
|
|
Pkmnlib.Generated.Pokemon.SetEffortValue(Ptr, (Pkmnlib.Statistic) stat, value);
|
|
}
|
|
|
|
public void SetStatus(string name)
|
|
{
|
|
Creaturelib.Generated.Creature.SetStatus(Ptr, name.ToPtr());
|
|
}
|
|
|
|
public void ClearStatus()
|
|
{
|
|
Creaturelib.Generated.Creature.ClearStatus(Ptr);
|
|
}
|
|
|
|
public void ChangeFriendship(sbyte amount)
|
|
{
|
|
Pkmnlib.Generated.Pokemon.ChangeFriendship(Ptr, amount);
|
|
}
|
|
|
|
public byte FirstAvailableMoveSlot()
|
|
{
|
|
return Creaturelib.Generated.Creature.GetAvailableAttackSlot(Ptr);
|
|
}
|
|
|
|
public void AddMove(LearnedMove move)
|
|
{
|
|
Creaturelib.Generated.Creature.AddAttack(Ptr, move.Ptr).Assert();
|
|
}
|
|
|
|
public void ReplaceMove(byte index, LearnedMove move)
|
|
{
|
|
Creaturelib.Generated.Creature.ReplaceAttack(Ptr, index, move.Ptr).Assert();
|
|
}
|
|
|
|
public void SwapMoves(byte a, byte b)
|
|
{
|
|
Creaturelib.Generated.Creature.SwapAttack(Ptr, a, b).Assert();
|
|
}
|
|
|
|
public void Evolve(Species species, Forme forme)
|
|
{
|
|
Pkmnlib.Generated.Pokemon.Evolve(Ptr, species.Ptr, forme.Ptr).Assert();
|
|
}
|
|
|
|
private Species? _displaySpecies;
|
|
private Forme? _displayForme;
|
|
private Species? _species;
|
|
private Forme? _forme;
|
|
private string? _nickname;
|
|
private ReadOnlyNativePtrArray<LearnedMove>? _moves;
|
|
private Nature? _nature;
|
|
private Battle? _battle;
|
|
private BattleSide? _battleSide;
|
|
|
|
public override string ToString()
|
|
{
|
|
return base.ToString() + $": {Species.Name}-{Forme.Name} lv. {Level} HP: {CurrentHealth}/{MaxHealth}";
|
|
}
|
|
|
|
protected override void DeletePtr()
|
|
{
|
|
Pkmnlib.Generated.Pokemon.Destruct(Ptr);
|
|
}
|
|
|
|
protected internal override void MarkAsDeleted()
|
|
{
|
|
foreach (var move in Moves)
|
|
{
|
|
move?.MarkAsDeleted();
|
|
}
|
|
|
|
base.MarkAsDeleted();
|
|
}
|
|
}
|
|
} |