Implementation of Pokeballs
This commit is contained in:
parent
0518499a4c
commit
42e3273483
19
PkmnLib.Dynamic/Events/CaptureAttemptEvent.cs
Normal file
19
PkmnLib.Dynamic/Events/CaptureAttemptEvent.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using PkmnLib.Dynamic.Libraries;
|
||||||
|
using PkmnLib.Dynamic.Models;
|
||||||
|
|
||||||
|
namespace PkmnLib.Dynamic.Events;
|
||||||
|
|
||||||
|
public class CaptureAttemptEvent : IEventData
|
||||||
|
{
|
||||||
|
public CaptureAttemptEvent(IPokemon target, CaptureResult result)
|
||||||
|
{
|
||||||
|
Target = target;
|
||||||
|
Result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPokemon Target { get; init; }
|
||||||
|
public CaptureResult Result { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public EventBatchId BatchId { get; init; }
|
||||||
|
}
|
25
PkmnLib.Dynamic/Libraries/CaptureLibrary.cs
Normal file
25
PkmnLib.Dynamic/Libraries/CaptureLibrary.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using PkmnLib.Dynamic.Models;
|
||||||
|
using PkmnLib.Static;
|
||||||
|
|
||||||
|
namespace PkmnLib.Dynamic.Libraries;
|
||||||
|
|
||||||
|
public record struct CaptureResult
|
||||||
|
{
|
||||||
|
public CaptureResult(bool IsCaught, int Shakes, bool CriticalCapture)
|
||||||
|
{
|
||||||
|
this.IsCaught = IsCaught;
|
||||||
|
this.Shakes = Shakes;
|
||||||
|
this.CriticalCapture = CriticalCapture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsCaught { get; init; }
|
||||||
|
public int Shakes { get; init; }
|
||||||
|
public bool CriticalCapture { get; init; }
|
||||||
|
|
||||||
|
public static CaptureResult Failed => new CaptureResult(false, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ICaptureLibrary
|
||||||
|
{
|
||||||
|
CaptureResult TryCapture(IPokemon target, IItem captureItem, IBattleRandom random);
|
||||||
|
}
|
@ -32,6 +32,11 @@ public interface IDynamicLibrary
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
IMiscLibrary MiscLibrary { get; }
|
IMiscLibrary MiscLibrary { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The capture library deals with the calculation of the capture rate of a Pokémon.
|
||||||
|
/// </summary>
|
||||||
|
ICaptureLibrary CaptureLibrary { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A holder of the script types that can be resolved by this library.
|
/// A holder of the script types that can be resolved by this library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -58,19 +63,22 @@ public class DynamicLibraryImpl : IDynamicLibrary
|
|||||||
throw new InvalidOperationException("Stat calculator not found in plugins.");
|
throw new InvalidOperationException("Stat calculator not found in plugins.");
|
||||||
if (registry.MiscLibrary is null)
|
if (registry.MiscLibrary is null)
|
||||||
throw new InvalidOperationException("Misc library not found in plugins.");
|
throw new InvalidOperationException("Misc library not found in plugins.");
|
||||||
|
if (registry.CaptureLibrary is null)
|
||||||
|
throw new InvalidOperationException("Capture library not found in plugins.");
|
||||||
var scriptResolver = new ScriptResolver(registry.ScriptTypes, registry.ItemScriptTypes);
|
var scriptResolver = new ScriptResolver(registry.ScriptTypes, registry.ItemScriptTypes);
|
||||||
return new DynamicLibraryImpl(staticLibrary, registry.BattleStatCalculator,
|
return new DynamicLibraryImpl(staticLibrary, registry.BattleStatCalculator,
|
||||||
registry.DamageCalculator, registry.MiscLibrary, scriptResolver);
|
registry.DamageCalculator, registry.MiscLibrary, registry.CaptureLibrary, scriptResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DynamicLibraryImpl(IStaticLibrary staticLibrary, IBattleStatCalculator statCalculator,
|
private DynamicLibraryImpl(IStaticLibrary staticLibrary, IBattleStatCalculator statCalculator,
|
||||||
IDamageCalculator damageCalculator, IMiscLibrary miscLibrary, ScriptResolver scriptResolver)
|
IDamageCalculator damageCalculator, IMiscLibrary miscLibrary, ICaptureLibrary captureLibrary, ScriptResolver scriptResolver)
|
||||||
{
|
{
|
||||||
StaticLibrary = staticLibrary;
|
StaticLibrary = staticLibrary;
|
||||||
StatCalculator = statCalculator;
|
StatCalculator = statCalculator;
|
||||||
DamageCalculator = damageCalculator;
|
DamageCalculator = damageCalculator;
|
||||||
MiscLibrary = miscLibrary;
|
MiscLibrary = miscLibrary;
|
||||||
ScriptResolver = scriptResolver;
|
ScriptResolver = scriptResolver;
|
||||||
|
CaptureLibrary = captureLibrary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -84,7 +92,10 @@ public class DynamicLibraryImpl : IDynamicLibrary
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IMiscLibrary MiscLibrary { get; }
|
public IMiscLibrary MiscLibrary { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ICaptureLibrary CaptureLibrary { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ScriptResolver ScriptResolver { get; }
|
public ScriptResolver ScriptResolver { get; }
|
||||||
}
|
}
|
@ -3,6 +3,7 @@ using PkmnLib.Dynamic.Libraries;
|
|||||||
using PkmnLib.Dynamic.Models.BattleFlow;
|
using PkmnLib.Dynamic.Models.BattleFlow;
|
||||||
using PkmnLib.Dynamic.Models.Choices;
|
using PkmnLib.Dynamic.Models.Choices;
|
||||||
using PkmnLib.Dynamic.ScriptHandling;
|
using PkmnLib.Dynamic.ScriptHandling;
|
||||||
|
using PkmnLib.Static;
|
||||||
using PkmnLib.Static.Utils;
|
using PkmnLib.Static.Utils;
|
||||||
|
|
||||||
namespace PkmnLib.Dynamic.Models;
|
namespace PkmnLib.Dynamic.Models;
|
||||||
@ -116,6 +117,8 @@ public interface IBattle : IScriptSource, IDeepCloneable
|
|||||||
/// for a single turn. The outer list is ordered from oldest to newest turn.
|
/// for a single turn. The outer list is ordered from oldest to newest turn.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IReadOnlyList<IReadOnlyList<ITurnChoice>> PreviousTurnChoices { get; }
|
IReadOnlyList<IReadOnlyList<ITurnChoice>> PreviousTurnChoices { get; }
|
||||||
|
|
||||||
|
CaptureResult AttempCapture(byte sideIndex, byte position, IItem item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IBattle"/>
|
/// <inheritdoc cref="IBattle"/>
|
||||||
@ -335,6 +338,24 @@ public class BattleImpl : ScriptSource, IBattle
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IReadOnlyList<IReadOnlyList<ITurnChoice>> PreviousTurnChoices => _previousTurnChoices;
|
public IReadOnlyList<IReadOnlyList<ITurnChoice>> PreviousTurnChoices => _previousTurnChoices;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public CaptureResult AttempCapture(byte sideIndex, byte position, IItem item)
|
||||||
|
{
|
||||||
|
var target = GetPokemon(sideIndex, position);
|
||||||
|
if (target is not { IsUsable: true })
|
||||||
|
return CaptureResult.Failed;
|
||||||
|
|
||||||
|
var attemptCapture = Library.CaptureLibrary.TryCapture(target, item, Random);
|
||||||
|
if (attemptCapture.IsCaught)
|
||||||
|
{
|
||||||
|
target.MarkAsCaught();
|
||||||
|
var side = Sides[target.BattleData!.SideIndex];
|
||||||
|
side.ForceClearPokemonFromField(target.BattleData.Position);
|
||||||
|
}
|
||||||
|
EventHook.Invoke(new CaptureAttemptEvent(target, attemptCapture));
|
||||||
|
return attemptCapture;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override int ScriptCount => 2;
|
public override int ScriptCount => 2;
|
||||||
|
|
||||||
|
@ -217,6 +217,13 @@ public class BattleSideImpl : ScriptSource, IBattleSide
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void ForceClearPokemonFromField(byte index)
|
public void ForceClearPokemonFromField(byte index)
|
||||||
{
|
{
|
||||||
|
var pokemon = _pokemon[index];
|
||||||
|
if (pokemon is not null)
|
||||||
|
{
|
||||||
|
pokemon.RunScriptHook(script => script.OnRemove());
|
||||||
|
pokemon.SetOnBattlefield(false);
|
||||||
|
}
|
||||||
|
|
||||||
_pokemon[index] = null;
|
_pokemon[index] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,6 +201,8 @@ public interface IPokemon : IScriptSource, IDeepCloneable
|
|||||||
/// Whether or not this Pokemon was caught this battle.
|
/// Whether or not this Pokemon was caught this battle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsCaught { get; }
|
bool IsCaught { get; }
|
||||||
|
|
||||||
|
public void MarkAsCaught();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The script for the held item.
|
/// The script for the held item.
|
||||||
@ -632,6 +634,12 @@ public class PokemonImpl : ScriptSource, IPokemon
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool IsCaught { get; private set; }
|
public bool IsCaught { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void MarkAsCaught()
|
||||||
|
{
|
||||||
|
IsCaught = true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ScriptContainer HeldItemTriggerScript { get; } = new();
|
public ScriptContainer HeldItemTriggerScript { get; } = new();
|
||||||
|
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
using PkmnLib.Dynamic.Models;
|
using PkmnLib.Dynamic.Models;
|
||||||
|
using PkmnLib.Static;
|
||||||
using PkmnLib.Static.Utils;
|
using PkmnLib.Static.Utils;
|
||||||
|
|
||||||
namespace PkmnLib.Dynamic.ScriptHandling;
|
namespace PkmnLib.Dynamic.ScriptHandling;
|
||||||
|
|
||||||
public abstract class ItemScript : IDeepCloneable
|
public abstract class ItemScript : IDeepCloneable
|
||||||
{
|
{
|
||||||
|
protected ItemScript(IItem item)
|
||||||
|
{
|
||||||
|
Item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IItem Item { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the script with the given parameters for a specific item
|
/// Initializes the script with the given parameters for a specific item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
24
PkmnLib.Dynamic/ScriptHandling/PokeballScript.cs
Normal file
24
PkmnLib.Dynamic/ScriptHandling/PokeballScript.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using PkmnLib.Dynamic.Models;
|
||||||
|
using PkmnLib.Static;
|
||||||
|
|
||||||
|
namespace PkmnLib.Dynamic.ScriptHandling;
|
||||||
|
|
||||||
|
public abstract class PokeballScript : ItemScript
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected PokeballScript(IItem item) : base(item)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract byte GetCatchRate(IPokemon target);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnUseWithTarget(IPokemon target)
|
||||||
|
{
|
||||||
|
var battleData = target.BattleData;
|
||||||
|
if (battleData == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
battleData.Battle.AttempCapture(battleData.SideIndex, battleData.Position, Item);
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ using System.Linq.Expressions;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using PkmnLib.Dynamic.Libraries;
|
using PkmnLib.Dynamic.Libraries;
|
||||||
|
using PkmnLib.Static;
|
||||||
using PkmnLib.Static.Utils;
|
using PkmnLib.Static.Utils;
|
||||||
|
|
||||||
namespace PkmnLib.Dynamic.ScriptHandling.Registry;
|
namespace PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||||
@ -13,10 +14,11 @@ namespace PkmnLib.Dynamic.ScriptHandling.Registry;
|
|||||||
public class ScriptRegistry
|
public class ScriptRegistry
|
||||||
{
|
{
|
||||||
private readonly Dictionary<(ScriptCategory category, StringKey name), Func<Script>> _scriptTypes = new();
|
private readonly Dictionary<(ScriptCategory category, StringKey name), Func<Script>> _scriptTypes = new();
|
||||||
private readonly Dictionary<StringKey, Func<ItemScript>> _itemScriptTypes = new();
|
private readonly Dictionary<StringKey, Func<IItem, ItemScript>> _itemScriptTypes = new();
|
||||||
private IBattleStatCalculator? _battleStatCalculator;
|
private IBattleStatCalculator? _battleStatCalculator;
|
||||||
private IDamageCalculator? _damageCalculator;
|
private IDamageCalculator? _damageCalculator;
|
||||||
private IMiscLibrary? _miscLibrary;
|
private IMiscLibrary? _miscLibrary;
|
||||||
|
private ICaptureLibrary? _captureLibrary;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Automatically register all scripts in the given assembly that have the <see cref="ScriptAttribute"/>, and
|
/// Automatically register all scripts in the given assembly that have the <see cref="ScriptAttribute"/>, and
|
||||||
@ -73,13 +75,15 @@ public class ScriptRegistry
|
|||||||
throw new ArgumentNullException(nameof(type));
|
throw new ArgumentNullException(nameof(type));
|
||||||
|
|
||||||
var constructor = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
|
var constructor = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
|
||||||
null, Type.EmptyTypes, null);
|
null, [typeof(IItem)], null);
|
||||||
if (constructor == null)
|
if (constructor == null)
|
||||||
throw new ArgumentException($"Type {type} does not have a parameterless constructor.");
|
throw new ArgumentException($"Type {type} does not have a constructor that takes an IItem.");
|
||||||
|
|
||||||
// We create a lambda that creates a new instance of the script type.
|
// We create a lambda that creates a new instance of the script type.
|
||||||
// This is more performant than using Activator.CreateInstance.
|
// This is more performant than using Activator.CreateInstance.
|
||||||
_itemScriptTypes[name] = Expression.Lambda<Func<ItemScript>>(Expression.New(constructor)).Compile();
|
var parameterExpression = Expression.Parameter(typeof(IItem), "item");
|
||||||
|
var newExpression = Expression.New(constructor, parameterExpression);
|
||||||
|
_itemScriptTypes[name] = Expression.Lambda<Func<IItem, ItemScript>>(newExpression, parameterExpression).Compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -99,10 +103,17 @@ public class ScriptRegistry
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void RegisterMiscLibrary<T>(T miscLibrary) where T : IMiscLibrary
|
public void RegisterMiscLibrary<T>(T miscLibrary) where T : IMiscLibrary
|
||||||
=> _miscLibrary = miscLibrary;
|
=> _miscLibrary = miscLibrary;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Register a capture library.
|
||||||
|
/// </summary>
|
||||||
|
public void RegisterCaptureLibrary<T>(T captureLibrary) where T : ICaptureLibrary
|
||||||
|
=> _captureLibrary = captureLibrary;
|
||||||
|
|
||||||
internal IReadOnlyDictionary<(ScriptCategory category, StringKey name), Func<Script>> ScriptTypes => _scriptTypes;
|
internal IReadOnlyDictionary<(ScriptCategory category, StringKey name), Func<Script>> ScriptTypes => _scriptTypes;
|
||||||
internal IReadOnlyDictionary<StringKey, Func<ItemScript>> ItemScriptTypes => _itemScriptTypes;
|
internal IReadOnlyDictionary<StringKey, Func<IItem, ItemScript>> ItemScriptTypes => _itemScriptTypes;
|
||||||
internal IBattleStatCalculator? BattleStatCalculator => _battleStatCalculator;
|
internal IBattleStatCalculator? BattleStatCalculator => _battleStatCalculator;
|
||||||
internal IDamageCalculator? DamageCalculator => _damageCalculator;
|
internal IDamageCalculator? DamageCalculator => _damageCalculator;
|
||||||
internal IMiscLibrary? MiscLibrary => _miscLibrary;
|
internal IMiscLibrary? MiscLibrary => _miscLibrary;
|
||||||
|
internal ICaptureLibrary? CaptureLibrary => _captureLibrary;
|
||||||
}
|
}
|
@ -493,7 +493,7 @@ public abstract class Script : IDeepCloneable
|
|||||||
/// rate of this attempt. Pokeball modifier effects should be implemented here, as well as for
|
/// rate of this attempt. Pokeball modifier effects should be implemented here, as well as for
|
||||||
/// example status effects that change capture rates.
|
/// example status effects that change capture rates.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void ChangeCaptureRateBonus(IPokemon pokemon, IItem pokeball, ref byte modifier)
|
public virtual void ChangeCatchRateBonus(IPokemon pokemon, IItem pokeball, ref byte modifier)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,11 +10,12 @@ namespace PkmnLib.Dynamic.ScriptHandling;
|
|||||||
public class ScriptResolver
|
public class ScriptResolver
|
||||||
{
|
{
|
||||||
private IReadOnlyDictionary<(ScriptCategory, StringKey), Func<Script>> _scriptCtors;
|
private IReadOnlyDictionary<(ScriptCategory, StringKey), Func<Script>> _scriptCtors;
|
||||||
private IReadOnlyDictionary<StringKey, Func<ItemScript>> _itemScriptCtors;
|
private IReadOnlyDictionary<StringKey, Func<IItem, ItemScript>> _itemScriptCtors;
|
||||||
|
private readonly Dictionary<IItem, ItemScript> _itemBattleScripts = new();
|
||||||
|
|
||||||
/// <inheritdoc cref="ScriptResolver"/>
|
/// <inheritdoc cref="ScriptResolver"/>
|
||||||
public ScriptResolver(IReadOnlyDictionary<(ScriptCategory, StringKey), Func<Script>> scriptCtors,
|
public ScriptResolver(IReadOnlyDictionary<(ScriptCategory, StringKey), Func<Script>> scriptCtors,
|
||||||
IReadOnlyDictionary<StringKey, Func<ItemScript>> itemScriptCtors)
|
IReadOnlyDictionary<StringKey, Func<IItem, ItemScript>> itemScriptCtors)
|
||||||
{
|
{
|
||||||
_scriptCtors = scriptCtors;
|
_scriptCtors = scriptCtors;
|
||||||
_itemScriptCtors = itemScriptCtors;
|
_itemScriptCtors = itemScriptCtors;
|
||||||
@ -46,6 +47,11 @@ public class ScriptResolver
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TryResolveBattleItemScript(IItem item, [MaybeNullWhen(false)] out ItemScript script)
|
public bool TryResolveBattleItemScript(IItem item, [MaybeNullWhen(false)] out ItemScript script)
|
||||||
{
|
{
|
||||||
|
if (_itemBattleScripts.TryGetValue(item, out script))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
var effect = item.BattleEffect;
|
var effect = item.BattleEffect;
|
||||||
if (effect == null)
|
if (effect == null)
|
||||||
{
|
{
|
||||||
@ -58,8 +64,9 @@ public class ScriptResolver
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
script = scriptCtor();
|
script = scriptCtor(item);
|
||||||
script.OnInitialize(effect.Parameters);
|
script.OnInitialize(effect.Parameters);
|
||||||
|
_itemBattleScripts[item] = script;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -36,5 +36,6 @@ public class Gen7Plugin : Dynamic.ScriptHandling.Registry.Plugin
|
|||||||
registry.RegisterBattleStatCalculator(new Gen7BattleStatCalculator());
|
registry.RegisterBattleStatCalculator(new Gen7BattleStatCalculator());
|
||||||
registry.RegisterDamageCalculator(new Gen7DamageCalculator(_configuration.DamageCalculatorHasRandomness));
|
registry.RegisterDamageCalculator(new Gen7DamageCalculator(_configuration.DamageCalculatorHasRandomness));
|
||||||
registry.RegisterMiscLibrary(new Gen7MiscLibrary());
|
registry.RegisterMiscLibrary(new Gen7MiscLibrary());
|
||||||
|
registry.RegisterCaptureLibrary(new Gen7CaptureLibrary());
|
||||||
}
|
}
|
||||||
}
|
}
|
53
Plugins/PkmnLib.Plugin.Gen7/Libraries/Gen7CaptureLibrary.cs
Normal file
53
Plugins/PkmnLib.Plugin.Gen7/Libraries/Gen7CaptureLibrary.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using PkmnLib.Dynamic.Libraries;
|
||||||
|
using PkmnLib.Dynamic.Models;
|
||||||
|
using PkmnLib.Dynamic.ScriptHandling;
|
||||||
|
using PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||||
|
using PkmnLib.Static;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Libraries;
|
||||||
|
|
||||||
|
public class Gen7CaptureLibrary : ICaptureLibrary
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public CaptureResult TryCapture(IPokemon target, IItem captureItem, IBattleRandom random)
|
||||||
|
{
|
||||||
|
var maxHealth = target.BoostedStats.Hp;
|
||||||
|
var currentHealth = target.CurrentHealth;
|
||||||
|
var catchRate = target.Species.CaptureRate;
|
||||||
|
|
||||||
|
byte bonusBall = 1;
|
||||||
|
if (target.Library.ScriptResolver.TryResolveBattleItemScript(captureItem, out var script) &&
|
||||||
|
script is PokeballScript pokeballScript)
|
||||||
|
{
|
||||||
|
bonusBall = pokeballScript.GetCatchRate(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte bonusStatus = 1;
|
||||||
|
target.RunScriptHook(x => x.ChangeCatchRateBonus(target, captureItem, ref bonusStatus));
|
||||||
|
|
||||||
|
var modifiedCatchRate =
|
||||||
|
(((3.0 * maxHealth) - (2.0 * currentHealth)) * catchRate * bonusBall) / (3.0 * maxHealth);
|
||||||
|
modifiedCatchRate *= bonusStatus;
|
||||||
|
|
||||||
|
var shakeProbability = 65536 / Math.Pow((255 / modifiedCatchRate), 0.1875);
|
||||||
|
byte shakes = 0;
|
||||||
|
if (modifiedCatchRate >= 255)
|
||||||
|
{
|
||||||
|
shakes = 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// FIXME: Implement critical capture
|
||||||
|
for (var i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (random.GetInt(0, 65536) < shakeProbability)
|
||||||
|
{
|
||||||
|
shakes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var success = shakes >= 3;
|
||||||
|
return new CaptureResult(success, shakes, false);
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
|||||||
using PkmnLib.Dynamic.Models;
|
using PkmnLib.Dynamic.Models;
|
||||||
using PkmnLib.Dynamic.ScriptHandling;
|
using PkmnLib.Dynamic.ScriptHandling;
|
||||||
using PkmnLib.Dynamic.ScriptHandling.Registry;
|
using PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||||
|
using PkmnLib.Static;
|
||||||
using PkmnLib.Static.Utils;
|
using PkmnLib.Static.Utils;
|
||||||
|
|
||||||
namespace PkmnLib.Plugin.Gen7.Scripts.Items;
|
namespace PkmnLib.Plugin.Gen7.Scripts.Items;
|
||||||
@ -11,6 +12,11 @@ public class HealingItem : ItemScript
|
|||||||
{
|
{
|
||||||
private uint _healAmount;
|
private uint _healAmount;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public HealingItem(IItem item) : base(item)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool IsItemUsable => true;
|
public override bool IsItemUsable => true;
|
||||||
|
|
||||||
|
40
Plugins/PkmnLib.Plugin.Gen7/Scripts/Items/StaticPokeball.cs
Normal file
40
Plugins/PkmnLib.Plugin.Gen7/Scripts/Items/StaticPokeball.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using PkmnLib.Dynamic.Models;
|
||||||
|
using PkmnLib.Dynamic.ScriptHandling;
|
||||||
|
using PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||||
|
using PkmnLib.Static;
|
||||||
|
using PkmnLib.Static.Utils;
|
||||||
|
|
||||||
|
namespace PkmnLib.Plugin.Gen7.Scripts.Items;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An implementation of a pokeball script that just has a flat catch rate bonus.
|
||||||
|
/// </summary>
|
||||||
|
[ItemScript("pokeball")]
|
||||||
|
public class StaticPokeball : PokeballScript
|
||||||
|
{
|
||||||
|
private byte _catchRate;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public StaticPokeball(IItem item) : base(item)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnInitialize(IReadOnlyDictionary<StringKey, object?>? parameters)
|
||||||
|
{
|
||||||
|
if (parameters == null || !parameters.TryGetValue("catchRate", out var catchRateObj) ||
|
||||||
|
catchRateObj is not byte catchRate)
|
||||||
|
{
|
||||||
|
catchRate = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_catchRate = catchRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override byte GetCatchRate(IPokemon target)
|
||||||
|
{
|
||||||
|
return _catchRate;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user