256 lines
8.8 KiB
C#
256 lines
8.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using PkmnLibSharp.Battling.ChoiceTurn;
|
|
using PkmnLibSharp.Battling.Events;
|
|
using PkmnLibSharp.Battling.History;
|
|
using PkmnLibSharp.Utilities;
|
|
|
|
namespace PkmnLibSharp.Battling
|
|
{
|
|
public class Battle : PointerWrapper
|
|
{
|
|
public Battle(BattleLibrary library, BattleParty[] parties, bool canFlee, byte numberOfSides, byte pokemonPerSide,
|
|
ulong randomSeed)
|
|
{
|
|
var ptr = IntPtr.Zero;
|
|
var arr = parties.Select(x => x.Ptr).ToArray();
|
|
Pkmnlib.Generated.Battle.Construct(ref ptr, library.Ptr, arr.ArrayPtr(), (ulong) arr.Length,
|
|
canFlee.ToNative(), numberOfSides, pokemonPerSide, randomSeed).Assert();
|
|
Initialize(ptr);
|
|
}
|
|
|
|
public BattleLibrary Library
|
|
{
|
|
get
|
|
{
|
|
if (_library != null) return _library;
|
|
var ptr = Creaturelib.Generated.Battle.GetLibrary(Ptr);
|
|
if (TryResolvePointer(ptr, out _library))
|
|
{
|
|
return _library!;
|
|
}
|
|
_library = new BattleLibrary(ptr);
|
|
return _library;
|
|
}
|
|
}
|
|
|
|
public BattleRandom Random
|
|
{
|
|
get
|
|
{
|
|
if (_random != null) return _random;
|
|
var ptr = Creaturelib.Generated.Battle.GetRandom(Ptr);
|
|
if (TryResolvePointer(ptr, out _random))
|
|
{
|
|
return _random!;
|
|
}
|
|
_random = new BattleRandom(ptr);
|
|
return _random;
|
|
}
|
|
}
|
|
|
|
public bool CanFlee => Creaturelib.Generated.Battle.CanFlee(Ptr) == 1;
|
|
public bool HasEnded => Creaturelib.Generated.Battle.HasEnded(Ptr) == 1;
|
|
public bool HasConclusiveResult => Creaturelib.Generated.Battle.HasConclusiveResult(Ptr) == 1;
|
|
public byte WinningSide => Creaturelib.Generated.Battle.GetWinningSide(Ptr);
|
|
public ulong SidesCount => Creaturelib.Generated.Battle.GetSidesCount(Ptr);
|
|
public ulong PartiesCount => Creaturelib.Generated.Battle.GetPartiesCount(Ptr);
|
|
public ulong MonsPerSide => Creaturelib.Generated.Battle.GetCreaturesPerSide(Ptr);
|
|
public long LastTurnTimeMicroseconds => Creaturelib.Generated.Battle.GetLastTurnTimeMicroseconds(Ptr);
|
|
|
|
private bool _cleared;
|
|
|
|
public ReadOnlyNativePtrArray<BattleSide> Sides
|
|
{
|
|
get
|
|
{
|
|
if (_sides != null) return _sides;
|
|
var ptr = Creaturelib.Generated.Battle.GetSides(Ptr);
|
|
_sides = new ReadOnlyNativePtrArray<BattleSide>(ptr, (int) SidesCount, Constructor.GenericType.BattleSide);
|
|
return _sides;
|
|
}
|
|
}
|
|
|
|
public uint CurrentTurn => Creaturelib.Generated.Battle.GetCurrentTurn(Ptr);
|
|
|
|
public ReadOnlyNativePtrArray<BattleParty> Parties
|
|
{
|
|
get
|
|
{
|
|
if (_parties != null) return _parties;
|
|
var ptr = Creaturelib.Generated.Battle.GetParties(Ptr);
|
|
_parties = new ReadOnlyNativePtrArray<BattleParty>(ptr, (int) PartiesCount, Constructor.GenericType.BattleParty);
|
|
return _parties;
|
|
}
|
|
}
|
|
|
|
public string? WeatherName => Pkmnlib.Generated.Battle.GetWeatherName(Ptr).PtrString();
|
|
|
|
public HistoryHandler History
|
|
{
|
|
get
|
|
{
|
|
if (_history != null) return _history;
|
|
var ptr = Creaturelib.Generated.Battle.GetHistory(Ptr);
|
|
if (TryResolvePointer(ptr, out _history))
|
|
return _history!;
|
|
_history = new HistoryHandler(ptr);
|
|
return _history;
|
|
}
|
|
}
|
|
|
|
|
|
public bool CanUse(BaseTurnChoice turnChoice)
|
|
{
|
|
byte b = 0;
|
|
Creaturelib.Generated.Battle.CanUse(ref b, Ptr, turnChoice.Ptr).Assert();
|
|
return b == 1;
|
|
}
|
|
|
|
private readonly List<BaseTurnChoice> _choiceCache = new List<BaseTurnChoice>();
|
|
public bool TrySetChoice(BaseTurnChoice turnChoice)
|
|
{
|
|
byte b = 0;
|
|
var initialTurn = CurrentTurn;
|
|
_choiceCache.Add(turnChoice);
|
|
var t1 = System.Diagnostics.Stopwatch.StartNew();
|
|
Creaturelib.Generated.Battle.TrySetChoice(ref b, Ptr, turnChoice.Ptr).Assert();
|
|
t1.Stop();
|
|
if (b == 1 && CurrentTurn != initialTurn)
|
|
{
|
|
LogHandler.Log(LogHandler.LogLevel.Information,
|
|
$"Ran turn in {t1.ElapsedMilliseconds} ms, battle reported {LastTurnTimeMicroseconds} microseconds");
|
|
_choiceCache.Clear();
|
|
}
|
|
return b == 1;
|
|
}
|
|
|
|
public void EndBattle()
|
|
{
|
|
Creaturelib.Generated.Battle.EndBattle(Ptr).Assert();
|
|
}
|
|
|
|
public void CheckChoicesSetAndRun()
|
|
{
|
|
Creaturelib.Generated.Battle.CheckChoicesSetAndRun(Ptr);
|
|
}
|
|
|
|
public bool IsPokemonInField(Pokemon pokemon)
|
|
{
|
|
byte b = 0;
|
|
Creaturelib.Generated.Battle.CreatureInField(ref b, Ptr, pokemon.Ptr).Assert();
|
|
return b == 1;
|
|
}
|
|
|
|
public Pokemon GetPokemonInField(byte side, byte index)
|
|
{
|
|
var ptr = IntPtr.Zero;
|
|
Creaturelib.Generated.Battle.GetCreature(ref ptr, Ptr, side, index).Assert();
|
|
return TryResolvePointer(ptr, out Pokemon? pokemon) ? pokemon! : Constructor.Active.ConstructPokemon(ptr)!;
|
|
}
|
|
|
|
public void ForceRecall(byte side, byte index)
|
|
{
|
|
Creaturelib.Generated.Battle.ForceRecall(Ptr, side, index).Assert();
|
|
}
|
|
|
|
public void SwitchPokemon(byte side, byte index, Pokemon newPokemon)
|
|
{
|
|
Creaturelib.Generated.Battle.SwitchCreature(Ptr, side, index, newPokemon.Ptr).Assert();
|
|
}
|
|
|
|
public bool CanSlotBeFilled(byte side, byte index)
|
|
{
|
|
byte b = 0;
|
|
Creaturelib.Generated.Battle.CanSlotBeFilled(ref b, Ptr, side, index).Assert();
|
|
return b == 1;
|
|
}
|
|
|
|
public void ValidateBattleState()
|
|
{
|
|
Creaturelib.Generated.Battle.ValidateBattleState(Ptr).Assert();
|
|
}
|
|
|
|
public Script GetVolatileScript(string key)
|
|
{
|
|
var ptr = Creaturelib.Generated.Battle.GetVolatileScript(Ptr, key.ToPtr());
|
|
if (TryResolvePointer(ptr, out Script? script))
|
|
{
|
|
return script!;
|
|
}
|
|
// TODO: Handle with different script providers.
|
|
return new AngelscriptScript(ptr);
|
|
}
|
|
|
|
public void AddVolatileScript(string key)
|
|
{
|
|
Creaturelib.Generated.Battle.AddVolatileScriptByName(Ptr, key.ToPtr()).Assert();
|
|
}
|
|
|
|
public void AddVolatileScript(Script script)
|
|
{
|
|
Creaturelib.Generated.Battle.AddVolatileScript(Ptr, script.Ptr).Assert();
|
|
}
|
|
|
|
public void RemoveVolatileScript(string key)
|
|
{
|
|
Creaturelib.Generated.Battle.RemoveVolatileScript(Ptr, key.ToPtr()).Assert();
|
|
}
|
|
|
|
public void RemoveVolatileScript(Script script)
|
|
{
|
|
Creaturelib.Generated.Battle.RemoveVolatileScriptWithScript(Ptr, script.Ptr).Assert();
|
|
}
|
|
|
|
public bool HasVolatileScript(string key)
|
|
{
|
|
return Creaturelib.Generated.Battle.HasVolatileScript(Ptr, key.ToPtr()) == 1;
|
|
}
|
|
|
|
private List<BattleEventListener> _listeners = new List<BattleEventListener>();
|
|
public void RegisterEventListener(BattleEventListener listener)
|
|
{
|
|
_listeners.Add(listener);
|
|
Creaturelib.Generated.Battle.RegisterEventListener(Ptr, listener.FunctionPtr).Assert();
|
|
}
|
|
|
|
public void SetWeather(string weatherName)
|
|
{
|
|
Pkmnlib.Generated.Battle.SetWeather(Ptr, weatherName.ToPtr());
|
|
}
|
|
|
|
public void ClearWeather()
|
|
{
|
|
Pkmnlib.Generated.Battle.ClearWeather(Ptr);
|
|
}
|
|
|
|
private BattleLibrary? _library;
|
|
private BattleRandom? _random;
|
|
private ReadOnlyNativePtrArray<BattleSide>? _sides;
|
|
private ReadOnlyNativePtrArray<BattleParty>? _parties;
|
|
private HistoryHandler? _history;
|
|
|
|
public void ClearBattle()
|
|
{
|
|
if (_cleared)
|
|
return;
|
|
_cleared = true;
|
|
Creaturelib.Generated.Battle.ClearBattle(Ptr);
|
|
}
|
|
|
|
protected override void DeletePtr()
|
|
{
|
|
Pkmnlib.Generated.Battle.Destruct(Ptr);
|
|
}
|
|
|
|
public override void Dispose()
|
|
{
|
|
if (!IsDeleted)
|
|
{
|
|
ClearBattle();
|
|
}
|
|
base.Dispose();
|
|
}
|
|
}
|
|
} |