Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions ModiBuff/ModiBuff.Tests/ModifierRecipeDataTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using System.Collections.Generic;
using System.Linq;
using ModiBuff.Core;
using ModiBuff.Core.Units;
using NUnit.Framework;

namespace ModiBuff.Tests
{
public sealed class ModifierRecipeDataTests : ModifierTests
{
[Test]
public void LegalActionUnitType()
{
const EnemyUnitType enemyType = EnemyUnitType.Goblin;
AddEnemySelfBuff("AddDamage", enemyType)
.Effect(new AddDamageEffect(5), EffectOn.Init);
AddRecipe("AddDamageApplier" + enemyType)
.Effect(new AddDamageEffect(5), EffectOn.Init)
.Data(new AddModifierCommonData<EnemyUnitType>(ModifierAddType.Applier, enemyType));
AddEnemySelfBuff("AddDamage", EnemyUnitType.Slime)
.Effect(new AddDamageEffect(5), EffectOn.Init);
AddRecipe("AddDamageAdvanced" + enemyType)
.Effect(new AddDamageEffect(5), EffectOn.Init)
.Data(new AddModifierCommonData<GoblinModifierActionType, EnemyUnitType>(
GoblinModifierActionType.OnSurrender, EnemyUnitType.Goblin));
Setup();

Unit.AddModifierSelf("AddDamage" + enemyType);

Assert.AreEqual(UnitDamage + 5, Unit.Damage);

var enemySelfModifiers = new List<int>();
var addModifierCommonData = ModifierRecipes.GetModifierData<AddModifierCommonData<EnemyUnitType>>();
Assert.AreEqual(addModifierCommonData.Length, 3);
Assert.AreEqual(addModifierCommonData.Count(d => d.Data.UnitType == enemyType), 2);
foreach ((int id, var data) in addModifierCommonData)
if (data.UnitType == enemyType && data.ModifierType == ModifierAddType.Self)
enemySelfModifiers.Add(id);

Assert.AreEqual(enemySelfModifiers.Count, 1);
Assert.AreEqual(enemySelfModifiers[0], IdManager.GetId("AddDamage" + enemyType));

ModifierRecipe AddEnemySelfBuff(string name, EnemyUnitType enemyUnitType) =>
AddRecipe(name + enemyUnitType)
.Data(new AddModifierCommonData<EnemyUnitType>(ModifierAddType.Self, enemyUnitType));
}

[Test]
public void SpecialUnitEvent()
{
const EnemyUnitType enemyType = EnemyUnitType.Goblin;
AddGoblinModifier("RemoveDamage", GoblinModifierActionType.OnSurrender)
.Effect(new AddDamageEffect(-5), EffectOn.Init);
Setup();

Unit.AddModifierSelf("RemoveDamage" + enemyType);

Assert.AreEqual(UnitDamage - 5, Unit.Damage);

var goblinSurrenderModifiers = new List<int>();
foreach ((int id, var data) in ModifierRecipes
.GetModifierData<AddModifierCommonData<GoblinModifierActionType, EnemyUnitType>>())
if (data.UnitType == enemyType && data.ModifierType == GoblinModifierActionType.OnSurrender)
goblinSurrenderModifiers.Add(id);

Assert.AreEqual(goblinSurrenderModifiers.Count, 1);
Assert.AreEqual(goblinSurrenderModifiers[0], IdManager.GetId("RemoveDamage" + enemyType));

ModifierRecipe AddGoblinModifier(string name, GoblinModifierActionType modifierActionType) =>
AddRecipe(name + EnemyUnitType.Goblin)
.Data(new AddModifierCommonData<GoblinModifierActionType, EnemyUnitType>(modifierActionType,
EnemyUnitType.Goblin));
}

[Test]
public void LegalActionUnitTypeGenerator()
{
const EnemyUnitType enemyType = EnemyUnitType.Goblin;
AddGenerator("AddDamage" + enemyType, (id, genId, name, tag) =>
{
var addDamageEffect = new AddDamageEffect(5);
var initComponent = new InitComponent(false, new IEffect[] { addDamageEffect }, null);

return new Modifier(id, genId, name, initComponent, null, null, null,
new SingleTargetComponent(), new EffectStateInfo(addDamageEffect), null);
}, Core.Units.TagType.Default,
customModifierData: new AddModifierCommonData<EnemyUnitType>(ModifierAddType.Self, enemyType));
Setup();

Unit.AddModifierSelf("AddDamage" + enemyType);

Assert.AreEqual(UnitDamage + 5, Unit.Damage);

var enemySelfModifiers = new List<int>();
foreach ((int id, var data) in ModifierRecipes.GetModifierData<AddModifierCommonData<EnemyUnitType>>())
if (data.UnitType == enemyType && data.ModifierType == ModifierAddType.Self)
enemySelfModifiers.Add(id);

Assert.AreEqual(enemySelfModifiers.Count, 1);
Assert.AreEqual(enemySelfModifiers[0], IdManager.GetId("AddDamage" + enemyType));
}
}
}
5 changes: 3 additions & 2 deletions ModiBuff/ModiBuff.Tests/ModifierTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ public virtual void IterationSetup()

protected void AddEffect(string name, params IEffect[] effects) => Effects.Add(name, effects);

protected void AddGenerator(string name, in ModifierGeneratorFunc createFunc, TagType tag = TagType.Default)
protected void AddGenerator(string name, in ModifierGeneratorFunc createFunc, TagType tag = TagType.Default,
int auraId = -1, object customModifierData = null)
{
Recipes.Add(name, name, "", in createFunc, tag.ToInternalTag());
Recipes.Add(name, name, "", in createFunc, tag.ToInternalTag(), auraId, customModifierData);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ public void IterationSetup()

protected void AddEffect(string name, params IEffect[] effects) => Effects.Add(name, effects);

protected void AddGenerator(string name, in ModifierGeneratorFunc createFunc, TagType tag = TagType.Default)
protected void AddGenerator(string name, in ModifierGeneratorFunc createFunc, TagType tag = TagType.Default,
int auraId = -1, object customModifierData = null)
{
Recipes.Add(name, name, "", in createFunc, tag.ToInternalTag());
Recipes.Add(name, name, "", in createFunc, tag.ToInternalTag(), auraId, customModifierData);
}

/// <summary>
Expand Down
22 changes: 22 additions & 0 deletions ModiBuff/ModiBuff.Units/Recipe/AddModifierCommonData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace ModiBuff.Core.Units
{
public enum ModifierAddType
{
Self = 1,
Applier,
}

public record AddModifierCommonData<TUnit>(ModifierAddType ModifierType, TUnit UnitType);

/// <summary>
/// Custom AddModifierCommonData for non-standard/non-generic modifier add actions
/// </summary>
public record AddModifierCommonData<TModifier, TUnit>(TModifier ModifierType, TUnit UnitType);
}

namespace System.Runtime.CompilerServices
{
internal static class IsExternalInit
{
}
}
29 changes: 29 additions & 0 deletions ModiBuff/ModiBuff.Units/UnitType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,35 @@ public enum UnitType
Neutral = 3,
}

/// <summary>
/// Example of how to use custom modifier data for advanced tagging purposes
/// </summary>
public enum AllyUnitType
{
Warrior,
Archer,
Mage,
}

/// <summary>
/// Example of how to use custom modifier data for advanced tagging purposes
/// </summary>
public enum EnemyUnitType
{
Slime,
Goblin,
Orc,
}

public enum GoblinModifierActionType
{
/// <summary>
/// Example special goblin mechanic, that says that these modifiers should be triggered on goblins event "OnSurrender"
/// </summary>
OnSurrender,
OnRetreat,
}

public static class UnitTypeExtensions
{
public static bool IsLegalTarget(this UnitType unitType, UnitType target)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ public sealed class ManualModifierGenerator : IModifierGenerator
public string Description { get; }
public TagType Tag { get; }
public int AuraId { get; }
public object Data { get; }
private readonly ModifierGeneratorFunc _createFunc;

private int _genId;

public ManualModifierGenerator(int id, string name, string displayName, string description,
in ModifierGeneratorFunc createFunc, TagType tag, int auraId)
in ModifierGeneratorFunc createFunc, TagType tag, int auraId, object customModifierData)
{
Id = id;
Name = name;
Expand All @@ -27,6 +28,8 @@ public ManualModifierGenerator(int id, string name, string displayName, string d
if (auraId != -1)
tag |= TagType.IsAura;
Tag = tag;
AuraId = auraId;
Data = customModifierData;
}

public Modifier Create() => _createFunc(Id, _genId++, Name, Tag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public interface IModifierRecipe
ModifierInfo CreateModifierInfo();
TagType GetTag();
int GetAuraId();
object GetData();

//TODO Move/refactor
ModifierRecipe.SaveData SaveState();
Expand Down
11 changes: 11 additions & 0 deletions ModiBuff/ModiBuff/Core/Modifier/Creation/Recipe/ModifierRecipe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public sealed partial class ModifierRecipe : IModifierRecipe, IEquatable<Modifie
private int _auraId;
private TagType _tag;

private object _data;

private bool _oneTimeInit;

private bool _currentIsInterval;
Expand Down Expand Up @@ -339,6 +341,13 @@ public ModifierRecipe Dispel(DispelType dispelType = DispelType.Basic)
return this;
}

public ModifierRecipe Data<T>(T data)
{
_data = data;
//_saveInstructions.Add(new SaveInstruction.Data(@object));
return this;
}

private void AddRemoveEffect(EffectOn effectOn)
{
if (_removeEffectWrapper != null)
Expand Down Expand Up @@ -581,6 +590,8 @@ public ModifierInfo CreateModifierInfo()

public int GetAuraId() => _auraId;

public object GetData() => _data;

private ModifierRecipe DurationInternal(float duration)
{
_duration = duration;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,12 @@ public void LoadState<TUnitCallback>(SaveData saveData)
ModifierAction(action.ModifierActionFlags, action.EffectOn);
#endif
break;
// case SaveInstruction.Event.Id:
//#if MODIBUFF_SYSTEM_TEXT_JSON
//#endif
// break;
case SaveInstruction.Data.Id:
#if MODIBUFF_SYSTEM_TEXT_JSON
var data = (SaveInstruction.Data)instruction;
Data(data.SaveData);
#endif
break;
default:
Logger.LogError($"Unknown instruction with id {instruction.InstructionId}");
break;
Expand Down Expand Up @@ -184,6 +186,7 @@ public void LoadState<TUnitCallback>(SaveData saveData)
[System.Text.Json.Serialization.JsonDerivedType(typeof(CallbackUnit), CallbackUnit.Id)]
[System.Text.Json.Serialization.JsonDerivedType(typeof(Effect), Effect.Id)]
[System.Text.Json.Serialization.JsonDerivedType(typeof(ModifierAction), ModifierAction.Id)]
[System.Text.Json.Serialization.JsonDerivedType(typeof(Data), Data.Id)]
#endif
public record SaveInstruction
{
Expand Down Expand Up @@ -413,6 +416,18 @@ public ModifierAction(ModiBuff.Core.ModifierAction modifierActionFlags, EffectOn
EffectOn = effectOn;
}
}

public sealed record Data : SaveInstruction
{
public const int Id = ModifierAction.Id + 1;

public readonly object SaveData;

#if MODIBUFF_SYSTEM_TEXT_JSON
[System.Text.Json.Serialization.JsonConstructor]
#endif
public Data(object saveData) : base(Id) => SaveData = saveData;
}
}

public readonly struct SaveData
Expand Down
28 changes: 25 additions & 3 deletions ModiBuff/ModiBuff/Core/Modifier/Creation/Recipe/ModifierRecipes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public class ModifierRecipes : IModifierRecipes
private ModifierInfo[] _modifierInfos;
private TagType[] _tags;
private int[] _auraIds;
private object[] _modifierData;

private readonly List<(int, object)> _modifierDataList;

public ModifierRecipes(ModifierIdManager idManager, EffectTypeIdManager effectTypeIdManager)
{
Expand All @@ -40,6 +43,7 @@ public ModifierRecipes(ModifierIdManager idManager, EffectTypeIdManager effectTy
_manualGenerators = new Dictionary<string, ManualModifierGenerator>(64);
_modifierGenerators = new Dictionary<string, IModifierGenerator>(64);
_registeredNames = new List<RegisterData>(16);
_modifierDataList = new List<(int, object)>(16);
}

//TODO TEMP
Expand All @@ -61,6 +65,7 @@ public void CreateGenerators()
_auraIds = new int[_recipes.Count + _manualGenerators.Count];
for (int i = 0; i < _auraIds.Length; i++)
_auraIds[i] = -1;
_modifierData = new object[_recipes.Count + _manualGenerators.Count];
foreach (var generator in _manualGenerators.Values)
{
_modifierGenerators.Add(generator.Name, generator);
Expand All @@ -69,6 +74,7 @@ public void CreateGenerators()
_tags[generator.Id] = generator.Tag;
if (generator.Tag.HasFlag(TagType.IsAura))
_auraIds[generator.Id] = generator.AuraId;
_modifierData[generator.Id] = generator.Data;
}

foreach (var recipe in _recipes.Values)
Expand All @@ -78,6 +84,7 @@ public void CreateGenerators()
_tags[recipe.Id] = recipe.GetTag();
if (recipe.GetTag().HasFlag(TagType.IsAura))
_auraIds[recipe.Id] = recipe.GetAuraId();
_modifierData[recipe.Id] = recipe.GetData();
}

GeneratorCount = _modifierGenerators.Count;
Expand All @@ -100,6 +107,21 @@ public ModifierInfo GetModifierInfo(int id)
public static ref readonly TagType GetTag(int id) => ref _instance._tags[id];
public static int GetAuraId(int id) => _instance._auraIds[id];

public static T GetModifierData<T>(int id) => (T)_instance._modifierData[id];

public static (int Id, T Data)[] GetModifierData<T>()
{
for (int i = 0; i < _instance._modifierData.Length; i++)
if (_instance._modifierData[i] is T data)
_instance._modifierDataList.Add((i, data));

var modifierData = new (int, T)[_instance._modifierDataList.Count];
for (int i = 0; i < modifierData.Length; i++)
modifierData[i] = ((int, T))_instance._modifierDataList[i];
_instance._modifierDataList.Clear();
return modifierData;
}

public IModifierGenerator GetGenerator(string name) => _modifierGenerators[name];

public IModifierGenerator[] GetGenerators() => _modifierGenerators.Values.ToArray();
Expand Down Expand Up @@ -135,8 +157,8 @@ public ModifierRecipe Add(string name, string displayName = "", string descripti
return recipe;
}

public void Add(string name, string displayName, string description,
in ModifierGeneratorFunc createFunc, TagType tag = TagType.Default, int auraId = -1)
public void Add(string name, string displayName, string description, in ModifierGeneratorFunc createFunc,
TagType tag = TagType.Default, int auraId = -1, object customModifierData = null)
{
if (_recipes.ContainsKey(name))
{
Expand Down Expand Up @@ -169,7 +191,7 @@ public void Add(string name, string displayName, string description,
id = _idManager.GetFreeId(name);

var modifierGenerator = new ManualModifierGenerator(id, name, displayName, description,
in createFunc, tag, auraId);
in createFunc, tag, auraId, customModifierData);
_manualGenerators.Add(name, modifierGenerator);
}

Expand Down
Loading
Loading