Initial set up for item use
This commit is contained in:
54
PkmnLib.Dynamic/ScriptHandling/ItemScript.cs
Normal file
54
PkmnLib.Dynamic/ScriptHandling/ItemScript.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using PkmnLib.Dynamic.Models;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Dynamic.ScriptHandling;
|
||||
|
||||
public abstract class ItemScript : IDeepCloneable
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the script with the given parameters for a specific item
|
||||
/// </summary>
|
||||
public virtual void OnInitialize(IReadOnlyDictionary<StringKey, object?>? parameters)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the item is usable in the current context.
|
||||
/// </summary>
|
||||
public virtual bool IsItemUsable => false;
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the item requires a target to be used.
|
||||
/// </summary>
|
||||
public virtual bool RequiresTarget => false;
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the item is usable on the given target.
|
||||
/// </summary>
|
||||
public virtual bool IsTargetValid(IPokemon target) => false;
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the item can be held by a Pokémon.
|
||||
/// </summary>
|
||||
public virtual bool IsHoldable => false;
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the item can be held by the given target.
|
||||
/// </summary>
|
||||
public virtual bool CanTargetHold(IPokemon pokemon) => false;
|
||||
|
||||
/// <summary>
|
||||
/// Handles the use of the item.
|
||||
/// </summary>
|
||||
public virtual void OnUse()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the use of the item on the given target.
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
public virtual void OnUseWithTarget(IPokemon target)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using JetBrains.Annotations;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
[MeansImplicitUse]
|
||||
public class ItemScriptAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the script.
|
||||
/// </summary>
|
||||
public StringKey Name { get; }
|
||||
|
||||
/// <inheritdoc cref="ItemScriptAttribute"/>
|
||||
public ItemScriptAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ namespace PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||
public class ScriptRegistry
|
||||
{
|
||||
private readonly Dictionary<(ScriptCategory category, StringKey name), Func<Script>> _scriptTypes = new();
|
||||
private readonly Dictionary<StringKey, Func<ItemScript>> _itemScriptTypes = new();
|
||||
private IBattleStatCalculator? _battleStatCalculator;
|
||||
private IDamageCalculator? _damageCalculator;
|
||||
private IMiscLibrary? _miscLibrary;
|
||||
@@ -32,6 +33,15 @@ public class ScriptRegistry
|
||||
|
||||
RegisterScriptType(attribute.Category, attribute.Name, type);
|
||||
}
|
||||
var itemBaseType = typeof(ItemScript);
|
||||
foreach (var type in assembly.GetTypes().Where(t => itemBaseType.IsAssignableFrom(t)))
|
||||
{
|
||||
var attribute = type.GetCustomAttribute<ItemScriptAttribute>();
|
||||
if (attribute == null)
|
||||
continue;
|
||||
|
||||
RegisterItemScriptType(attribute.Name, type);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -52,6 +62,25 @@ public class ScriptRegistry
|
||||
// This is more performant than using Activator.CreateInstance.
|
||||
_scriptTypes[(category, name)] = Expression.Lambda<Func<Script>>(Expression.New(constructor)).Compile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register an item script type with the given name.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public void RegisterItemScriptType(StringKey name, Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
|
||||
var constructor = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
|
||||
null, Type.EmptyTypes, null);
|
||||
if (constructor == null)
|
||||
throw new ArgumentException($"Type {type} does not have a parameterless constructor.");
|
||||
|
||||
// We create a lambda that creates a new instance of the script type.
|
||||
// This is more performant than using Activator.CreateInstance.
|
||||
_itemScriptTypes[name] = Expression.Lambda<Func<ItemScript>>(Expression.New(constructor)).Compile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a battle stat calculator.
|
||||
@@ -71,7 +100,8 @@ public class ScriptRegistry
|
||||
public void RegisterMiscLibrary<T>(T miscLibrary) where T : IMiscLibrary
|
||||
=> _miscLibrary = miscLibrary;
|
||||
|
||||
internal Dictionary<(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 IBattleStatCalculator? BattleStatCalculator => _battleStatCalculator;
|
||||
internal IDamageCalculator? DamageCalculator => _damageCalculator;
|
||||
internal IMiscLibrary? MiscLibrary => _miscLibrary;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using PkmnLib.Dynamic.Libraries;
|
||||
using PkmnLib.Dynamic.Models;
|
||||
using PkmnLib.Dynamic.Models.Choices;
|
||||
using PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||
@@ -74,7 +73,7 @@ public abstract class Script : IDeepCloneable
|
||||
/// <summary>
|
||||
/// This function is ran when this script starts being in effect.
|
||||
/// </summary>
|
||||
public virtual void OnInitialize(IDynamicLibrary library, IReadOnlyDictionary<StringKey, object?>? parameters)
|
||||
public virtual void OnInitialize(IReadOnlyDictionary<StringKey, object?>? parameters)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -9,33 +9,57 @@ namespace PkmnLib.Dynamic.ScriptHandling;
|
||||
/// </summary>
|
||||
public class ScriptResolver
|
||||
{
|
||||
private Dictionary<(ScriptCategory, StringKey), Func<Script>> _scriptCtors;
|
||||
private IReadOnlyDictionary<(ScriptCategory, StringKey), Func<Script>> _scriptCtors;
|
||||
private IReadOnlyDictionary<StringKey, Func<ItemScript>> _itemScriptCtors;
|
||||
|
||||
/// <inheritdoc cref="ScriptResolver"/>
|
||||
public ScriptResolver(Dictionary<(ScriptCategory, StringKey), Func<Script>> scriptCtors)
|
||||
public ScriptResolver(IReadOnlyDictionary<(ScriptCategory, StringKey), Func<Script>> scriptCtors,
|
||||
IReadOnlyDictionary<StringKey, Func<ItemScript>> itemScriptCtors)
|
||||
{
|
||||
_scriptCtors = scriptCtors;
|
||||
_itemScriptCtors = itemScriptCtors;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Try and create a new script for the given category and key. If the script does not exist, return false.
|
||||
/// </summary>
|
||||
public bool TryResolve(ScriptCategory category, StringKey key, [MaybeNullWhen(false)] out Script script)
|
||||
public bool TryResolve(ScriptCategory category, StringKey key, IReadOnlyDictionary<StringKey, object?>? parameters,
|
||||
[MaybeNullWhen(false)] out Script script)
|
||||
{
|
||||
if (!_scriptCtors.TryGetValue((category, key), out var scriptCtor))
|
||||
{
|
||||
script = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
script = scriptCtor();
|
||||
if (parameters != null)
|
||||
{
|
||||
script.OnInitialize(parameters);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Try and resolve an item script for the given item. If the item does not have a script, return false.
|
||||
/// </summary>
|
||||
public bool TryResolveItemScript(IItem item, [MaybeNullWhen(false)] out Script script)
|
||||
public bool TryResolveBattleItemScript(IItem item, [MaybeNullWhen(false)] out ItemScript script)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var effect = item.BattleEffect;
|
||||
if (effect == null)
|
||||
{
|
||||
script = null;
|
||||
return false;
|
||||
}
|
||||
if (!_itemScriptCtors.TryGetValue(effect.Name, out var scriptCtor))
|
||||
{
|
||||
script = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
script = scriptCtor();
|
||||
script.OnInitialize(effect.Parameters);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user