PkmnLibSharp/PkmnLibSharp/Battling/Pokemon.cs

551 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 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 => Pkmnlib.Generated.Pokemon.IsEgg(Ptr) == 1;
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 => Pkmnlib.Generated.Pokemon.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)
{
Pkmnlib.Generated.Pokemon.SetStatus(Ptr, name.ToPtr());
}
public void ClearStatus()
{
Pkmnlib.Generated.Pokemon.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();
}
}
}