NPTXIY5PL7XQUOFJ2WRAZUBHMC4OFZVF4EA74GBI63TJ4QXDKMAAC
BF2XBP7WISOQGHV3QX5XBWTPADBYO2FPNNEYWR6UPPFTRGMTZH2AC
7BZ73FLUK5ANK44V7EMAROTHHVE2IGJ65GTA26DRWY65566HMNPAC
HUULCHM5GFGZ7GKLCULFHC333LQ3LBI62VKII3YL5O4C5CDGCT4AC
FNS4LRFQNFM4BCB23CYHOWA2N4MG2DEUMNK6D55BQ26TX6OJLIBQC
G4XIS2NEM4WHRP2775YBCLFDT7JZZS52CMEHY3PA43QSXL45XNDAC
RZAMG2H2NY73KZJIV4VXLJHJVSRGJDRWWZJERAI6O7AVDW64JEQQC
6UYO5OFJ5JDP3ANPDJ3NG66EQHMTBAAP6K4LPRG3DH34R2S4VZUAC
YI7M5RWLKUG256YXK6CGZKUPDCNHREU2PGV344L2IV24FF5PHG3AC
P5O6MKCMZL3DK7ZO5SBWTCHOQB6O2MZA5VPSCQX6X4LJQVOWYV7AC
LAFCS4AAOMBOBURWXRZEDUI4J5QGBP7CJQXIPLKXEDXNBCVE7SLQC
FQZF2IY4T2F7KEVSHMFID35WNAU55CRRDF6XEXZB7PYZH26UGYPQC
MHN2B5YZ2Y4G3O7UOZJKFQ3SSP5HTNJCXFKCO3KYY46I2GHM3TIQC
ZHJFVCAJGFFEQCY6IZW2VFXBDTTWLBKDIABIGMF4CZOMTGYJKCYQC
QOAVQCDV2MRAPUX62ZLDTUB6AXYSAGEEWIEZIG4TGIQKCLP5T5GAC
AZN3UTBQLTKMGIHW5UCAMLC4GGHG6MAORBQ7OIR2U7NTZ53GWGNQC
7QKPEDFDFQJFTXM4BFJ4CFHOOZKOI6NKRRSBDLMP7SELPJMFOQRAC
OXMN3LHBNH7CWHEZRPSZTN244O3ACTOEKZEAKQNKFXQ7VQSM26YQC
J75RIWLT42QXABT6GQMAVIOP5XDUF7UAGFQUSSKDIULB3LEB22EQC
ZZLU6UG75ALN7BYLP4SLGT4SIHDKJPFZPMNSYST25RQT3KLTFHPAC
VUAVVMQEUYSXHBIUJHGRX237EZFT5MCB73ZKVWMGJDRHYZH4XZKAC
HMDPEJRZK3PO6M5Z655Y4HWCUKC5I35GRMVVQOZYXWWCIH5ZWNPQC
GBGS6RTZTCKRMLLDVCBGMRTJNNOSAUTXN5D2EMEQMQAREORE54PAC
G6KBRZNCPEBI5YF2ZJYRAFCYDO3CDGFPQBDC3I4JQEYJ4DNT234AC
4JF64OZ2FPMTXL5XV3Z6HCEKKGCLXPLMNV3YCNX35RL5CXL42VNQC
R475KN7MR3OG7EBLVNOO7QRIKXDGY2PIDXXV3HW4KBD5QM7B5OJQC
2RUZ7TTRT7SMZT2V7YWUCCTJJXNRT2LNJ2QBBVN4RMREMOGMGMHQC
TKLR43RQKXB47J2YVVSJ7CAZAJZYOKXSDUXAUOVQMFUN73KZVUVQC
R6RQ2RKQV3YFYIRN5JED6NAFB4E34WQJRDHHKZ4JO7KLBXRKNFYAC
ZFSIN26KNM3DNHBUA67DKKHQYH62TZ627SNBHPO37IS3AB2XTHEQC
CD5FF75KTOBTMVMTMCKMR6F5DFKOF26I5K43ITNHGBI3ZAZHA4RAC
JMMGK6VQWZOLY6C6YWUPAIHLQXUZ2ZZTVJQAL7ODPZAWUSZQIJJAC
HXTSBPAP75A7EC4RKWYQMVPPHPNZFPHUORBZWDHGEB6MPAGI7G7AC
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using TagFighter.Resources;
using UnityEngine;
[Serializable]
public class EffectSystem : IEffectSystem
{
ParticleSystem _rippleOutVfx;
[SerializeField] TagFighter.Effects.EffectColors _colorMapping;
const string PulseMaterial = "Materials/PulseMaterial2";
class EffectRunner : MonoBehaviour
{
public GameObject EffectObj;
public Material Material;
public float PlayTime;
public void Run(GameObject effectObj, Material material, float playTime) {
EffectObj = effectObj;
Material = material;
PlayTime = playTime;
Material.SetFloat("_Phase", 0);
EffectObj.SetActive(true);
StartCoroutine("PlayEffect");
}
public IEnumerator PlayEffect() {
float totalTime = 0;
float phase = 0;
while (phase < 0.98) {
totalTime += Time.deltaTime;
phase = totalTime / PlayTime;
Material.SetFloat("_Phase", phase);
yield return null;
}
Destroy(EffectObj);
}
}
public EffectSystem() {
}
public void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, Transform origin, Quaternion direction, IAreaOfEffect areaOfEffect) {
switch (areaOfEffect) {
case SingleTarget: ApplyTagsEffectSingle(); break;
case CircleArea aoe: ApplyTagsEffectRadius(tags, origin, direction, aoe); break;
case ConeArea aoe: ApplyTagsEffectCone(tags, origin, direction, aoe); break;
case PathArea aoe: ApplyTagsEffectPath(tags, origin, direction, aoe); break;
}
}
void ApplyTagsEffectSingle() {
Debug.Log("ApplyTagsEffectSingle");
}
void ApplyTagsEffectPath(IEnumerable<(Type, IUnit)> tags, Transform origin, Quaternion direction, PathArea areaOfEffect) {
var color = GetEffectColor(tags);
var mesh = CreateQuadMeshForUnit(origin, areaOfEffect.Width, areaOfEffect.Length);
// Add a new to clone the shared resource
Material material = new(Resources.Load<Material>(PulseMaterial));
material.SetColor("_Color", color);
DisplayEffect(origin, direction, mesh, material);
}
void ApplyTagsEffectRadius(IEnumerable<(Type, IUnit)> tags, Transform origin, Quaternion direction, CircleArea areaOfEffect) {
var color = GetEffectColor(tags);
var mesh = CreateArcMeshForUnit(origin, 360, areaOfEffect.Radius);
// Add a new to clone the shared resource
Material material = new(Resources.Load<Material>(PulseMaterial));
material.SetColor("_Color", color);
DisplayEffect(origin, direction, mesh, material);
}
void ApplyTagsEffectCone(IEnumerable<(Type, IUnit)> tags, Transform origin, Quaternion direction, ConeArea areaOfEffect) {
Debug.Log("ApplyTagsEffectCone");
var color = GetEffectColor(tags);
var mesh = CreateArcMeshForUnit(origin, areaOfEffect.Angle, areaOfEffect.Radius);
// Add a new to clone the shared resource
Material material = new(Resources.Load<Material>(PulseMaterial));
material.SetColor("_Color", color);
DisplayEffect(origin, direction, mesh, material);
}
public Color GetEffectColor(IEnumerable<(Type, IUnit)> tags) {
Debug.Log("GetEffectColor");
var color = new Color();
Debug.Log($"GetEffectColor length {tags.Count()}");
if (_colorMapping == null) {
foreach (var tag in tags) {
Debug.Log("GetEffectColor tag");
if (_colorMapping.ContainsKey(tag.Item1)) {
Debug.Log("GetEffectColor mapping found");
var mappedColor = _colorMapping[tag.Item1];
// TODO: scale color by amount
color += mappedColor;
}
}
}
Debug.Log("GetEffectColor Finished");
return color;
}
public Mesh CreateArcMeshForUnit(Transform unit, float arc, float length, int numberOfVerticesInArc = 100) {
return CreateArcMesh(unit.forward, arc, length, numberOfVerticesInArc, Vector3.up);
}
public Mesh CreateQuadMeshForUnit(Transform unit, float width, float length) {
return CreateQuadMesh(unit.forward, width, length, Vector3.up);
}
void DisplayEffect(Transform originUnit, Quaternion direction, Mesh mesh, Material material) {
GameObject effectObj = new();
effectObj.SetActive(false);
effectObj.transform.position = originUnit.position;
effectObj.transform.rotation = direction;
var meshRenderer = effectObj.AddComponent<MeshRenderer>();
meshRenderer.sharedMaterial = material;
meshRenderer.shadowCastingMode = 0;
meshRenderer.receiveShadows = false;
var meshFilter = effectObj.AddComponent<MeshFilter>();
meshFilter.mesh = mesh;
effectObj.AddComponent<EffectRunner>();
var effectRunner = effectObj.GetComponent<EffectRunner>();
effectRunner.Run(effectObj, material, 1f);
}
public Mesh CreateArcMesh(Vector3 direction, float arc, float length, int numberOfVerticesInArc, Vector3 rotationAxis) {
var origin = Vector3.zero;
Mesh mesh = new();
var n = numberOfVerticesInArc + 1;
var arcStep = arc / (n - 2);
var currentDegrees = -arc / 2;
var vertices = new Vector3[n];
var uv = new Vector2[n];
vertices[0] = origin;
uv[0] = origin;
for (var i = 1; i < n; i++) {
vertices[i] = Quaternion.AngleAxis(currentDegrees, rotationAxis) * direction * length;
uv[i] = new Vector2(0, 1);
//Debug.Log($"Current Degrees: {currentDegrees} -> {vertices[i]}");
currentDegrees += arcStep;
}
mesh.vertices = vertices;
mesh.uv = uv;
var tris = new int[(n - 2) * 3];
for (var i = 0; i < n - 2; i++) {
tris[i * 3] = 0;
tris[i * 3 + 1] = i + 1;
tris[i * 3 + 2] = i + 2;
}
mesh.triangles = tris;
var normals = new Vector3[n];
for (var i = 0; i < n; i++) {
normals[i] = rotationAxis;
}
mesh.normals = normals;
return mesh;
}
public Mesh CreateQuadMesh(Vector3 direction, float width, float length, Vector3 rotationAxis) {
Mesh mesh = new();
var origin = Vector3.zero;
// TODO: how to calculate local rotation? direction
var vertices = new Vector3[4]
{
new Vector3(-width/2, 0, 0) + origin,
new Vector3(width/2, 0, 0) + origin,
new Vector3(-width/2, 0, length) + origin,
new Vector3(width/2, 0, length) + origin
};
mesh.vertices = vertices;
var tris = new int[6]
{
// lower left triangle
0, 2, 1,
// upper right triangle
2, 3, 1
};
mesh.triangles = tris;
var normals = new Vector3[4]
{
rotationAxis,
rotationAxis,
rotationAxis,
rotationAxis
};
mesh.normals = normals;
var uv = new Vector2[4]
{
new Vector2(0, 0),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(1, 1)
};
mesh.uv = uv;
return mesh;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using CareBoo.Serially;
using TagFighter.Resources;
using UnityEngine;
[ProvideSourceInfo]
[Serializable]
public class EffectSystem : IEffectSystem
{
ParticleSystem _rippleOutVfx;
[SerializeField] TagFighter.Effects.EffectColors _colorMapping;
const string PulseMaterial = "Materials/PulseMaterial2";
class EffectRunner : MonoBehaviour
{
public GameObject EffectObj;
public Material Material;
public float PlayTime;
public void Run(GameObject effectObj, Material material, float playTime) {
EffectObj = effectObj;
Material = material;
PlayTime = playTime;
Material.SetFloat("_Phase", 0);
EffectObj.SetActive(true);
StartCoroutine("PlayEffect");
}
public IEnumerator PlayEffect() {
float totalTime = 0;
float phase = 0;
while (phase < 0.98) {
totalTime += Time.deltaTime;
phase = totalTime / PlayTime;
Material.SetFloat("_Phase", phase);
yield return null;
}
Destroy(EffectObj);
}
}
public EffectSystem() {
}
public void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, Transform origin, Quaternion direction, IAreaOfEffect areaOfEffect) {
switch (areaOfEffect) {
case SingleTarget: ApplyTagsEffectSingle(); break;
case CircleArea aoe: ApplyTagsEffectRadius(tags, origin, direction, aoe); break;
case ConeArea aoe: ApplyTagsEffectCone(tags, origin, direction, aoe); break;
case PathArea aoe: ApplyTagsEffectPath(tags, origin, direction, aoe); break;
}
}
void ApplyTagsEffectSingle() {
Debug.Log("ApplyTagsEffectSingle");
}
void ApplyTagsEffectPath(IEnumerable<(Type, IUnit)> tags, Transform origin, Quaternion direction, PathArea areaOfEffect) {
var color = GetEffectColor(tags);
var mesh = CreateQuadMeshForUnit(origin, areaOfEffect.Width, areaOfEffect.Length);
// Add a new to clone the shared resource
Material material = new(Resources.Load<Material>(PulseMaterial));
material.SetColor("_Color", color);
DisplayEffect(origin, direction, mesh, material);
}
void ApplyTagsEffectRadius(IEnumerable<(Type, IUnit)> tags, Transform origin, Quaternion direction, CircleArea areaOfEffect) {
var color = GetEffectColor(tags);
var mesh = CreateArcMeshForUnit(origin, 360, areaOfEffect.Radius);
// Add a new to clone the shared resource
Material material = new(Resources.Load<Material>(PulseMaterial));
material.SetColor("_Color", color);
DisplayEffect(origin, direction, mesh, material);
}
void ApplyTagsEffectCone(IEnumerable<(Type, IUnit)> tags, Transform origin, Quaternion direction, ConeArea areaOfEffect) {
Debug.Log("ApplyTagsEffectCone");
var color = GetEffectColor(tags);
var mesh = CreateArcMeshForUnit(origin, areaOfEffect.Angle, areaOfEffect.Radius);
// Add a new to clone the shared resource
Material material = new(Resources.Load<Material>(PulseMaterial));
material.SetColor("_Color", color);
DisplayEffect(origin, direction, mesh, material);
}
public Color GetEffectColor(IEnumerable<(Type, IUnit)> tags) {
Debug.Log("GetEffectColor");
var color = new Color();
Debug.Log($"GetEffectColor length {tags.Count()}");
if (_colorMapping == null) {
foreach (var tag in tags) {
Debug.Log("GetEffectColor tag");
if (_colorMapping.ContainsKey(tag.Item1)) {
Debug.Log("GetEffectColor mapping found");
var mappedColor = _colorMapping[tag.Item1];
// TODO: scale color by amount
color += mappedColor;
}
}
}
Debug.Log("GetEffectColor Finished");
return color;
}
public Mesh CreateArcMeshForUnit(Transform unit, float arc, float length, int numberOfVerticesInArc = 100) {
return CreateArcMesh(unit.forward, arc, length, numberOfVerticesInArc, Vector3.up);
}
public Mesh CreateQuadMeshForUnit(Transform unit, float width, float length) {
return CreateQuadMesh(unit.forward, width, length, Vector3.up);
}
void DisplayEffect(Transform originUnit, Quaternion direction, Mesh mesh, Material material) {
GameObject effectObj = new();
effectObj.SetActive(false);
effectObj.transform.position = originUnit.position;
effectObj.transform.rotation = direction;
var meshRenderer = effectObj.AddComponent<MeshRenderer>();
meshRenderer.sharedMaterial = material;
meshRenderer.shadowCastingMode = 0;
meshRenderer.receiveShadows = false;
var meshFilter = effectObj.AddComponent<MeshFilter>();
meshFilter.mesh = mesh;
effectObj.AddComponent<EffectRunner>();
var effectRunner = effectObj.GetComponent<EffectRunner>();
effectRunner.Run(effectObj, material, 1f);
}
public Mesh CreateArcMesh(Vector3 direction, float arc, float length, int numberOfVerticesInArc, Vector3 rotationAxis) {
var origin = Vector3.zero;
Mesh mesh = new();
var n = numberOfVerticesInArc + 1;
var arcStep = arc / (n - 2);
var currentDegrees = -arc / 2;
var vertices = new Vector3[n];
var uv = new Vector2[n];
vertices[0] = origin;
uv[0] = origin;
for (var i = 1; i < n; i++) {
vertices[i] = Quaternion.AngleAxis(currentDegrees, rotationAxis) * direction * length;
uv[i] = new Vector2(0, 1);
//Debug.Log($"Current Degrees: {currentDegrees} -> {vertices[i]}");
currentDegrees += arcStep;
}
mesh.vertices = vertices;
mesh.uv = uv;
var tris = new int[(n - 2) * 3];
for (var i = 0; i < n - 2; i++) {
tris[i * 3] = 0;
tris[i * 3 + 1] = i + 1;
tris[i * 3 + 2] = i + 2;
}
mesh.triangles = tris;
var normals = new Vector3[n];
for (var i = 0; i < n; i++) {
normals[i] = rotationAxis;
}
mesh.normals = normals;
return mesh;
}
public Mesh CreateQuadMesh(Vector3 direction, float width, float length, Vector3 rotationAxis) {
Mesh mesh = new();
var origin = Vector3.zero;
// TODO: how to calculate local rotation? direction
var vertices = new Vector3[4]
{
new Vector3(-width/2, 0, 0) + origin,
new Vector3(width/2, 0, 0) + origin,
new Vector3(-width/2, 0, length) + origin,
new Vector3(width/2, 0, length) + origin
};
mesh.vertices = vertices;
var tris = new int[6]
{
// lower left triangle
0, 2, 1,
// upper right triangle
2, 3, 1
};
mesh.triangles = tris;
var normals = new Vector3[4]
{
rotationAxis,
rotationAxis,
rotationAxis,
rotationAxis
};
mesh.normals = normals;
var uv = new Vector2[4]
{
new Vector2(0, 0),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(1, 1)
};
mesh.uv = uv;
return mesh;
}
}
using System;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
namespace TagFighter.Resources
{
public interface IAccessibleResource<TUnitType> where TUnitType : IUnitType
{
public Unit<TUnitType> GetCapacity();
public Unit<TUnitType> GetCurrent();
}
[Serializable]
public class Resource<TUnitType> : MonoBehaviour, IWatchableResource, IAccessibleResource<TUnitType> where TUnitType : IUnitType
{
[SerializeField] Stat<Current> _current;
[SerializeField] Stat<Capacity> _capacity;
readonly Unit<TUnitType> _minimumCapacity = (Unit<TUnitType>)0;
public ResourceChangeArgs Status => (ResourceChangeArgs)this;
public Unit<TUnitType> GetCapacity() {
var value = _capacity.Total;
if (value < _minimumCapacity) {
value = _minimumCapacity;
}
return value;
}
public void AddCapacityModifier(StatModifier<TUnitType> modifier, CancellationToken cancelToken) {
AddModifier(modifier, _capacity, cancelToken);
}
public Unit<TUnitType> GetCurrent() {
var value = _current.Total;
value = Unit<TUnitType>.Clamp(value, _minimumCapacity, GetCapacity());
return value;
}
public void AddCurrentModifier(StatModifier<TUnitType> modifier, CancellationToken cancelToken) {
AddModifier(modifier, _current, cancelToken);
}
void AddModifier<TStatType>(StatModifier<TUnitType> modifier, Stat<TStatType> stat, CancellationToken cancelToken)
where TStatType : IStatType {
cancelToken.Register(() => {
OnResourceChanged((ResourceChangeArgs)this);
});
stat.AddModifier(modifier, cancelToken);
Debug.Log($"AddModifier {transform.name}.{GetType().Name}.{typeof(TStatType).Name}");
OnResourceChanged((ResourceChangeArgs)this);
}
public event EventHandler<ResourceChangeArgs> ResourceChanged;
public static explicit operator ResourceChangeArgs(Resource<TUnitType> resource) {
return new((int)resource.GetCurrent(), (int)resource._current.Base, (int)resource._current.Modified,
(int)resource.GetCapacity(), (int)resource._capacity.Base, (int)resource._capacity.Modified,
resource.transform);
}
void OnResourceChanged(ResourceChangeArgs e) {
ResourceChanged?.Invoke(this, e);
}
public interface IStatType { }
class Current : IStatType { }
class Capacity : IStatType { }
[Serializable]
public class Stat<TStatType> where TStatType : IStatType
{
[SerializeField] Unit<TUnitType> _base;
LinkedList<StatModifier<TUnitType>> _modifiers = new();
public Unit<TUnitType> Base {
get {
return _base;
}
private set {
_base = value;
}
}
public Unit<TUnitType> Modified {
get;
private set;
}
public Unit<TUnitType> Total => Base + Modified;
public void AddModifier(StatModifier<TUnitType> modifier, CancellationToken cancelToken) {
if (cancelToken == CancellationToken.None) {
Base += modifier.Amount;
}
else {
AddTransientModifier(modifier, cancelToken);
}
}
void AddTransientModifier(StatModifier<TUnitType> modifier, CancellationToken cancelToken) {
LinkedListNode<StatModifier<TUnitType>> node = new(modifier);
_modifiers.AddFirst(node);
Modified += modifier.Amount;
cancelToken.Register(() => {
_modifiers.Remove(node);
Modified -= modifier.Amount;
});
}
}
}
}
using System;
using System.Collections.Generic;
using System.Threading;
using CareBoo.Serially;
using UnityEngine;
namespace TagFighter.Resources
{
public interface IAccessibleResource<TUnitType> where TUnitType : IUnitType
{
public Unit<TUnitType> GetCapacity();
public Unit<TUnitType> GetCurrent();
}
[Serializable]
public class Resource<TUnitType> : MonoBehaviour, IWatchableResource, IAccessibleResource<TUnitType> where TUnitType : IUnitType
{
[SerializeField] Stat<Current> _current;
[SerializeField] Stat<Capacity> _capacity;
readonly Unit<TUnitType> _minimumCapacity = (Unit<TUnitType>)0;
public ResourceChangeArgs Status => (ResourceChangeArgs)this;
public Unit<TUnitType> GetCapacity() {
var value = _capacity.Total;
if (value < _minimumCapacity) {
value = _minimumCapacity;
}
return value;
}
public void AddCapacityModifier(StatModifier<TUnitType> modifier, CancellationToken cancelToken) {
AddModifier(modifier, _capacity, cancelToken);
}
public Unit<TUnitType> GetCurrent() {
var value = _current.Total;
value = Unit<TUnitType>.Clamp(value, _minimumCapacity, GetCapacity());
return value;
}
public void AddCurrentModifier(StatModifier<TUnitType> modifier, CancellationToken cancelToken) {
AddModifier(modifier, _current, cancelToken);
}
void AddModifier<TStatType>(StatModifier<TUnitType> modifier, Stat<TStatType> stat, CancellationToken cancelToken)
where TStatType : IStatType {
cancelToken.Register(() => {
OnResourceChanged((ResourceChangeArgs)this);
});
stat.AddModifier(modifier, cancelToken);
Debug.Log($"AddModifier {transform.name}.{GetType().Name}.{typeof(TStatType).Name}");
OnResourceChanged((ResourceChangeArgs)this);
}
public event EventHandler<ResourceChangeArgs> ResourceChanged;
public static explicit operator ResourceChangeArgs(Resource<TUnitType> resource) {
return new((int)resource.GetCurrent(), (int)resource._current.Base, (int)resource._current.Modified,
(int)resource.GetCapacity(), (int)resource._capacity.Base, (int)resource._capacity.Modified,
resource.transform);
}
void OnResourceChanged(ResourceChangeArgs e) {
ResourceChanged?.Invoke(this, e);
}
public interface IStatType { }
class Current : IStatType { }
class Capacity : IStatType { }
[Serializable]
public class Stat<TStatType> where TStatType : IStatType
{
[SerializeField] Unit<TUnitType> _base;
LinkedList<StatModifier<TUnitType>> _modifiers = new();
public Unit<TUnitType> Base {
get {
return _base;
}
private set {
_base = value;
}
}
public Unit<TUnitType> Modified {
get;
private set;
}
public Unit<TUnitType> Total => Base + Modified;
public void AddModifier(StatModifier<TUnitType> modifier, CancellationToken cancelToken) {
if (cancelToken == CancellationToken.None) {
Base += modifier.Amount;
}
else {
AddTransientModifier(modifier, cancelToken);
}
}
void AddTransientModifier(StatModifier<TUnitType> modifier, CancellationToken cancelToken) {
LinkedListNode<StatModifier<TUnitType>> node = new(modifier);
_modifiers.AddFirst(node);
Modified += modifier.Amount;
cancelToken.Register(() => {
_modifiers.Remove(node);
Modified -= modifier.Amount;
});
}
}
}
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("F18D2C2B-4AA0-45EA-8137-70D85F067FFA")]
[Serializable]
[ProvideSourceInfo()]
public sealed class SwordKnowledge : Resource<SwordKP> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("F18D2C2B-4AA0-45EA-8137-70D85F067FFA")]
[Serializable]
[ProvideSourceInfo]
public sealed class SwordKnowledge : Resource<SwordKP> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("18751303-04F3-47B4-B66D-9E734E55F0E8")]
[Serializable]
[ProvideSourceInfo()]
public sealed class ShieldKnowledge : Resource<ShieldKP> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("18751303-04F3-47B4-B66D-9E734E55F0E8")]
[Serializable]
[ProvideSourceInfo]
public sealed class ShieldKnowledge : Resource<ShieldKP> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("7F412C19-18FE-476F-92E4-469FFAD0C5D4")]
[Serializable]
[ProvideSourceInfo()]
public sealed class RedTag : Resource<RedTagUnit> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("7F412C19-18FE-476F-92E4-469FFAD0C5D4")]
[Serializable]
[ProvideSourceInfo]
public sealed class RedTag : Resource<RedTagUnit> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("4B8E4C4F-03D6-4102-9936-AC66DD899EE2")]
[Serializable]
[ProvideSourceInfo()]
public sealed class RecklessFormKnowledge : Resource<RecklessFormKP> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("4B8E4C4F-03D6-4102-9936-AC66DD899EE2")]
[Serializable]
[ProvideSourceInfo]
public sealed class RecklessFormKnowledge : Resource<RecklessFormKP> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("CF53C617-F396-4C4F-9317-F935188D525C")]
[Serializable]
[ProvideSourceInfo()]
public sealed class Range : Resource<Centimeter> { }
public static class CentimeterExtensions
{
public static float ToMeter(this Unit<Centimeter> source) {
return source.AsPrimitive() * 0.01f;
}
}
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("CF53C617-F396-4C4F-9317-F935188D525C")]
[Serializable]
[ProvideSourceInfo]
public sealed class Range : Resource<Centimeter> { }
public static class CentimeterExtensions
{
public static float ToMeter(this Unit<Centimeter> source) {
return source.AsPrimitive() * 0.01f;
}
}
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("30A0DDC8-3FCF-496A-B578-81DBF333C7EC")]
[Serializable]
[ProvideSourceInfo()]
public sealed class Pain : Resource<PainUnit> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("30A0DDC8-3FCF-496A-B578-81DBF333C7EC")]
[Serializable]
[ProvideSourceInfo]
public sealed class Pain : Resource<PainUnit> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("DA13F1C1-4359-4EB9-B969-7DB50AFE6423")]
[Serializable]
[ProvideSourceInfo()]
public sealed class GreenTag : Resource<GreenTagUnit> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("DA13F1C1-4359-4EB9-B969-7DB50AFE6423")]
[Serializable]
[ProvideSourceInfo]
public sealed class GreenTag : Resource<GreenTagUnit> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("59A26139-CA50-4E6F-8AC0-27DFB70CCB8B")]
[Serializable]
[ProvideSourceInfo()]
public sealed class Fatigue : Resource<FatigueUnit> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("59A26139-CA50-4E6F-8AC0-27DFB70CCB8B")]
[Serializable]
[ProvideSourceInfo]
public sealed class Fatigue : Resource<FatigueUnit> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("AECC1739-A0DF-4013-B430-22D2EB13F0FF")]
[Serializable]
[ProvideSourceInfo()]
public sealed class BlueTag : Resource<BlueTagUnit> { }
}
using System;
using System.Runtime.InteropServices;
using CareBoo.Serially;
namespace TagFighter.Resources
{
[Guid("AECC1739-A0DF-4013-B430-22D2EB13F0FF")]
[Serializable]
[ProvideSourceInfo]
public sealed class BlueTag : Resource<BlueTagUnit> { }
}
using System;
using System.Collections.Generic;
using System.Linq;
using TagFighter.Effects.ResourceLocationAccessors.PawnProperties;
using TagFighter.Resources;
using UnityEngine;
namespace TagFighter.Effects
{
public interface IResourceGetter
{
public IWatchableResource GetWatchableResource(Transform transform);
public int GetStat(Transform transform, IPawnResourceProperty stat);
}
public interface IResourceTypeAccessor
{
public IEnumerable<double> Get(EffectInput data, IResourceLocationGet accessor);
public void Set(EffectInput data, IResourceLocationSet accessor, IEnumerable<int> value);
}
public class ResourceTypeAccessor<TResource, TUnit> : IResourceTypeAccessor, IResourceGetter, IEquatable<ResourceTypeAccessor<TResource, TUnit>>
where TResource : Resource<TUnit>
where TUnit : IUnitType
{
public IEnumerable<double> Get(EffectInput data, IResourceLocationGet accessor) {
return accessor.Get<TResource, TUnit>(data).Select(resource => (double)resource);
}
public void Set(EffectInput data, IResourceLocationSet accessor, IEnumerable<int> values) {
accessor.Set<TResource, TUnit>(data, values.Select(value => (Unit<TUnit>)value));
}
public IWatchableResource GetWatchableResource(Transform transform) {
return transform.GetComponent<TResource>();
}
public int GetStat(Transform transform, IPawnResourceProperty stat) {
return (int)stat.Get<TResource, TUnit>(transform.GetComponent<TResource>());
}
public override string ToString() => $"{typeof(TResource).Name}";
public bool Equals(ResourceTypeAccessor<TResource, TUnit> other) {
if ((other == null) || !GetType().Equals(other.GetType())) {
return false;
}
return true;
}
public override bool Equals(object other) {
if ((other == null) || !GetType().Equals(other.GetType())) {
return false;
}
return true;
}
public override int GetHashCode() {
return GetType().GetHashCode();
}
}
namespace ResourceTypeAccessors
{
[Serializable] public sealed class Pain : ResourceTypeAccessor<Resources.Pain, PainUnit> { }
[Serializable] public sealed class Fatigue : ResourceTypeAccessor<Resources.Fatigue, FatigueUnit> { }
[Serializable] public sealed class BlueTag : ResourceTypeAccessor<Resources.BlueTag, BlueTagUnit> { }
[Serializable] public sealed class RedTag : ResourceTypeAccessor<Resources.RedTag, RedTagUnit> { }
[Serializable] public sealed class GreenTag : ResourceTypeAccessor<Resources.GreenTag, GreenTagUnit> { }
[Serializable] public sealed class Range : ResourceTypeAccessor<Resources.Range, Centimeter> { }
[Serializable] public sealed class RecklessFormKnowledge : ResourceTypeAccessor<Resources.RecklessFormKnowledge, RecklessFormKP> { }
[Serializable] public sealed class SwordKnowledge : ResourceTypeAccessor<Resources.SwordKnowledge, SwordKP> { }
[Serializable] public sealed class ShieldKnowledge : ResourceTypeAccessor<Resources.ShieldKnowledge, ShieldKP> { }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using CareBoo.Serially;
using TagFighter.Effects.ResourceLocationAccessors.PawnProperties;
using TagFighter.Resources;
using UnityEngine;
namespace TagFighter.Effects
{
public interface IResourceGetter
{
public IWatchableResource GetWatchableResource(Transform transform);
public int GetStat(Transform transform, IPawnResourceProperty stat);
}
public interface IResourceTypeAccessor
{
public IEnumerable<double> Get(EffectInput data, IResourceLocationGet accessor);
public void Set(EffectInput data, IResourceLocationSet accessor, IEnumerable<int> value);
}
public class ResourceTypeAccessor<TResource, TUnit> : IResourceTypeAccessor, IResourceGetter, IEquatable<ResourceTypeAccessor<TResource, TUnit>>
where TResource : Resource<TUnit>
where TUnit : IUnitType
{
public IEnumerable<double> Get(EffectInput data, IResourceLocationGet accessor) {
return accessor.Get<TResource, TUnit>(data).Select(resource => (double)resource);
}
public void Set(EffectInput data, IResourceLocationSet accessor, IEnumerable<int> values) {
accessor.Set<TResource, TUnit>(data, values.Select(value => (Unit<TUnit>)value));
}
public IWatchableResource GetWatchableResource(Transform transform) {
return transform.GetComponent<TResource>();
}
public int GetStat(Transform transform, IPawnResourceProperty stat) {
return (int)stat.Get<TResource, TUnit>(transform.GetComponent<TResource>());
}
public override string ToString() => $"{typeof(TResource).Name}";
public bool Equals(ResourceTypeAccessor<TResource, TUnit> other) {
if ((other == null) || !GetType().Equals(other.GetType())) {
return false;
}
return true;
}
public override bool Equals(object other) {
if ((other == null) || !GetType().Equals(other.GetType())) {
return false;
}
return true;
}
public override int GetHashCode() {
return GetType().GetHashCode();
}
}
namespace ResourceTypeAccessors
{
[ProvideSourceInfo][Serializable] public sealed class Pain : ResourceTypeAccessor<Resources.Pain, PainUnit> { }
[ProvideSourceInfo][Serializable] public sealed class Fatigue : ResourceTypeAccessor<Resources.Fatigue, FatigueUnit> { }
[ProvideSourceInfo][Serializable] public sealed class BlueTag : ResourceTypeAccessor<Resources.BlueTag, BlueTagUnit> { }
[ProvideSourceInfo][Serializable] public sealed class RedTag : ResourceTypeAccessor<Resources.RedTag, RedTagUnit> { }
[ProvideSourceInfo][Serializable] public sealed class GreenTag : ResourceTypeAccessor<Resources.GreenTag, GreenTagUnit> { }
[ProvideSourceInfo][Serializable] public sealed class Range : ResourceTypeAccessor<Resources.Range, Centimeter> { }
[ProvideSourceInfo][Serializable] public sealed class RecklessFormKnowledge : ResourceTypeAccessor<Resources.RecklessFormKnowledge, RecklessFormKP> { }
[ProvideSourceInfo][Serializable] public sealed class SwordKnowledge : ResourceTypeAccessor<Resources.SwordKnowledge, SwordKP> { }
[ProvideSourceInfo][Serializable] public sealed class ShieldKnowledge : ResourceTypeAccessor<Resources.ShieldKnowledge, ShieldKP> { }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using TagFighter.Resources;
namespace TagFighter.Effects
{
public interface IResourceOperator
{
public double Operate(params double[] values) => OperateEnum(values);
public Unit<TUnit> Operate<TUnit>(params Unit<TUnit>[] values) where TUnit : IUnitType => OperateEnum(values);
public Unit<TUnit> OperateEnum<TUnit>(IEnumerable<Unit<TUnit>> values) where TUnit : IUnitType => (Unit<TUnit>)OperateEnum(values.Select(value => value.AsPrimitive()));
public double OperateEnum(IEnumerable<double> values);
public int OperateEnum(IEnumerable<int> values);
}
namespace Operators
{
[Serializable]
public class Sum : IResourceOperator
{
public double OperateEnum(IEnumerable<double> a) => a.Sum();
public int OperateEnum(IEnumerable<int> a) => a.Sum();
public override string ToString() => nameof(Sum);
}
[Serializable]
public class Multiply : IResourceOperator
{
public double OperateEnum(IEnumerable<double> values) => values.Aggregate(1d, (acc, val) => acc * val);
public int OperateEnum(IEnumerable<int> values) => values.Aggregate(1, (acc, val) => acc * val);
public override string ToString() => nameof(Multiply);
}
[Serializable]
public class Min : IResourceOperator
{
public double OperateEnum(IEnumerable<double> values) => values.Min();
public int OperateEnum(IEnumerable<int> values) => values.Min();
public override string ToString() => nameof(Min);
}
[Serializable]
public class Max : IResourceOperator
{
public double OperateEnum(IEnumerable<double> values) => values.Max();
public int OperateEnum(IEnumerable<int> values) => values.Max();
public override string ToString() => nameof(Max);
}
[Serializable]
public class Average : IResourceOperator
{
public double OperateEnum(IEnumerable<double> values) => values.Average();
public int OperateEnum(IEnumerable<int> values) => (int)values.Average();
public override string ToString() => nameof(Average);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using CareBoo.Serially;
using TagFighter.Resources;
namespace TagFighter.Effects
{
public interface IResourceOperator
{
public double Operate(params double[] values) => OperateEnum(values);
public Unit<TUnit> Operate<TUnit>(params Unit<TUnit>[] values) where TUnit : IUnitType => OperateEnum(values);
public Unit<TUnit> OperateEnum<TUnit>(IEnumerable<Unit<TUnit>> values) where TUnit : IUnitType => (Unit<TUnit>)OperateEnum(values.Select(value => value.AsPrimitive()));
public double OperateEnum(IEnumerable<double> values);
public int OperateEnum(IEnumerable<int> values);
}
namespace Operators
{
[ProvideSourceInfo]
[Serializable]
public class Sum : IResourceOperator
{
public double OperateEnum(IEnumerable<double> a) => a.Sum();
public int OperateEnum(IEnumerable<int> a) => a.Sum();
public override string ToString() => nameof(Sum);
}
[ProvideSourceInfo]
[Serializable]
public class Multiply : IResourceOperator
{
public double OperateEnum(IEnumerable<double> values) => values.Aggregate(1d, (acc, val) => acc * val);
public int OperateEnum(IEnumerable<int> values) => values.Aggregate(1, (acc, val) => acc * val);
public override string ToString() => nameof(Multiply);
}
[ProvideSourceInfo]
[Serializable]
public class Min : IResourceOperator
{
public double OperateEnum(IEnumerable<double> values) => values.Min();
public int OperateEnum(IEnumerable<int> values) => values.Min();
public override string ToString() => nameof(Min);
}
[ProvideSourceInfo]
[Serializable]
public class Max : IResourceOperator
{
public double OperateEnum(IEnumerable<double> values) => values.Max();
public int OperateEnum(IEnumerable<int> values) => values.Max();
public override string ToString() => nameof(Max);
}
[ProvideSourceInfo]
[Serializable]
public class Average : IResourceOperator
{
public double OperateEnum(IEnumerable<double> values) => values.Average();
public int OperateEnum(IEnumerable<int> values) => (int)values.Average();
public override string ToString() => nameof(Average);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using CareBoo.Serially;
using TagFighter.Resources;
using UnityEngine;
namespace TagFighter.Effects.ResourceLocationAccessors
{
namespace PawnProperties
{
public interface IPawnResourceProperty
{
public Unit<TUnit> Get<TResource, TUnit>(TResource resource)
where TResource : IAccessibleResource<TUnit> where TUnit : IUnitType;
public void Set<TResource, TUnit>(EffectInput data, TResource resource, Unit<TUnit> value)
where TResource : Resource<TUnit> where TUnit : IUnitType;
}
[Serializable]
public class Current : IPawnResourceProperty
{
public Unit<TUnit> Get<TResource, TUnit>(TResource resource)
where TResource : IAccessibleResource<TUnit> where TUnit : IUnitType => resource.GetCurrent();
public void Set<TResource, TUnit>(EffectInput data, TResource resource, Unit<TUnit> value)
where TResource : Resource<TUnit> where TUnit : IUnitType => data.StatAccessor.AddCurrentModifier(resource, value);
public override string ToString() => nameof(Current);
}
[Serializable]
public class Capacity : IPawnResourceProperty
{
public Unit<TUnit> Get<TResource, TUnit>(TResource resource)
where TResource : IAccessibleResource<TUnit> where TUnit : IUnitType => resource.GetCapacity();
public void Set<TResource, TUnit>(EffectInput data, TResource resource, Unit<TUnit> value)
where TResource : Resource<TUnit> where TUnit : IUnitType => data.StatAccessor.AddCapacityModifier(resource, value);
public override string ToString() => nameof(Capacity);
}
}
namespace Get
{
using PawnProperties;
[Serializable]
public class Pawn : IResourceLocationGet
{
[SerializeReference, ShowSerializeReference]
public IPawnResourceProperty Property;
public IEnumerable<Unit<TUnit>> Get<TResource, TUnit>(EffectInput data)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
return data.Affected.Select(transform => transform.GetComponent<TResource>())
.Select(resource => resource ? Property.Get<TResource, TUnit>(resource) : (Unit<TUnit>)0);
}
public override string ToString() => $"{nameof(Pawn)}.{Property}";
}
}
namespace Set
{
using PawnProperties;
[Serializable]
public class Pawn : IResourceLocationSet
{
[SerializeReference, ShowSerializeReference]
public IPawnResourceProperty Property;
public void Set<TResource, TUnit>(EffectInput data, IEnumerable<Unit<TUnit>> values)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
var repeatedValues = Enumerable.Repeat(values.ToList(), int.MaxValue).SelectMany(value => value);
foreach (var tuple in data.Affected.Zip(repeatedValues, (transform, value) => (resource: transform.GetComponent<TResource>(), value))
.Where(tuple => tuple.resource)) {
Property.Set(data, tuple.resource, tuple.value);
}
}
public override string ToString() => $"{nameof(Pawn)}.{Property}";
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using CareBoo.Serially;
using TagFighter.Resources;
using UnityEngine;
namespace TagFighter.Effects.ResourceLocationAccessors
{
namespace PawnProperties
{
public interface IPawnResourceProperty
{
public Unit<TUnit> Get<TResource, TUnit>(TResource resource)
where TResource : IAccessibleResource<TUnit> where TUnit : IUnitType;
public void Set<TResource, TUnit>(EffectInput data, TResource resource, Unit<TUnit> value)
where TResource : Resource<TUnit> where TUnit : IUnitType;
}
[ProvideSourceInfo]
[Serializable]
public class Current : IPawnResourceProperty
{
public Unit<TUnit> Get<TResource, TUnit>(TResource resource)
where TResource : IAccessibleResource<TUnit> where TUnit : IUnitType => resource.GetCurrent();
public void Set<TResource, TUnit>(EffectInput data, TResource resource, Unit<TUnit> value)
where TResource : Resource<TUnit> where TUnit : IUnitType => data.StatAccessor.AddCurrentModifier(resource, value);
public override string ToString() => nameof(Current);
}
[ProvideSourceInfo]
[Serializable]
public class Capacity : IPawnResourceProperty
{
public Unit<TUnit> Get<TResource, TUnit>(TResource resource)
where TResource : IAccessibleResource<TUnit> where TUnit : IUnitType => resource.GetCapacity();
public void Set<TResource, TUnit>(EffectInput data, TResource resource, Unit<TUnit> value)
where TResource : Resource<TUnit> where TUnit : IUnitType => data.StatAccessor.AddCapacityModifier(resource, value);
public override string ToString() => nameof(Capacity);
}
}
namespace Get
{
using PawnProperties;
[ProvideSourceInfo]
[Serializable]
public class Pawn : IResourceLocationGet
{
[SerializeReference, ShowSerializeReference]
public IPawnResourceProperty Property;
public IEnumerable<Unit<TUnit>> Get<TResource, TUnit>(EffectInput data)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
return data.Affected.Select(transform => transform.GetComponent<TResource>())
.Select(resource => resource ? Property.Get<TResource, TUnit>(resource) : (Unit<TUnit>)0);
}
public override string ToString() => $"{nameof(Pawn)}.{Property}";
}
}
namespace Set
{
using PawnProperties;
[ProvideSourceInfo]
[Serializable]
public class Pawn : IResourceLocationSet
{
[SerializeReference, ShowSerializeReference]
public IPawnResourceProperty Property;
public void Set<TResource, TUnit>(EffectInput data, IEnumerable<Unit<TUnit>> values)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
var repeatedValues = Enumerable.Repeat(values.ToList(), int.MaxValue).SelectMany(value => value);
foreach (var tuple in data.Affected.Zip(repeatedValues, (transform, value) => (resource: transform.GetComponent<TResource>(), value))
.Where(tuple => tuple.resource)) {
Property.Set(data, tuple.resource, tuple.value);
}
}
public override string ToString() => $"{nameof(Pawn)}.{Property}";
}
}
}
using System;
using System.Collections.Generic;
using CareBoo.Serially;
using TagFighter.Resources;
using UnityEngine;
namespace TagFighter.Effects.ResourceLocationAccessors
{
namespace ContextRegisters
{
public interface IRegisterType { }
public class CurrentRegisterType : IRegisterType { }
public class AddedRegisterType : IRegisterType { }
public class RemovedRegisterType : IRegisterType { }
public interface IContextRegister
{
public IEnumerable<Unit<TUnit>> Get<TResource, TUnit>(EffectContext context)
where TResource : Resource<TUnit>
where TUnit : IUnitType;
public void Set<TResource, TUnit>(EffectContext context, Unit<TUnit> value)
where TResource : Resource<TUnit>
where TUnit : IUnitType;
}
public class ContextRegister<TRegisterType> : IContextRegister where TRegisterType : IRegisterType
{
public IEnumerable<Unit<TUnit>> Get<TResource, TUnit>(EffectContext context)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
yield return context.GetResource<TResource, TUnit, ContextRegister<TRegisterType>>();
}
public void Set<TResource, TUnit>(EffectContext context, Unit<TUnit> value)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
context.SetResource<TResource, TUnit, ContextRegister<TRegisterType>>(value);
}
public override string ToString() => typeof(TRegisterType).Name;
}
[Serializable] public sealed class Current : ContextRegister<CurrentRegisterType> { }
[Serializable] public sealed class Added : ContextRegister<AddedRegisterType> { }
[Serializable] public sealed class Removed : ContextRegister<RemovedRegisterType> { }
}
namespace Get
{
using ContextRegisters;
[Serializable]
public class Context : IResourceLocationGet
{
[SerializeReference, ShowSerializeReference]
public IContextRegister Register;
public IEnumerable<Unit<TUnit>> Get<TResource, TUnit>(EffectInput data)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
return Register.Get<TResource, TUnit>(data.Context);
}
public override string ToString() => $"{nameof(Context)}.{Register}";
}
}
namespace Set
{
using ContextRegisters;
[Serializable]
public class Context : IResourceLocationSet
{
[SerializeReference, ShowSerializeReference]
public IContextRegister Register;
[SerializeReference, ShowSerializeReference]
public IResourceOperator SetAs;
public void Set<TResource, TUnit>(EffectInput data, IEnumerable<Unit<TUnit>> values)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
Register.Set<TResource, TUnit>(data.Context, SetAs.OperateEnum(values));
}
public override string ToString() => $"{nameof(Context)}.{Register}";
}
}
}
using System;
using System.Collections.Generic;
using CareBoo.Serially;
using TagFighter.Resources;
using UnityEngine;
namespace TagFighter.Effects.ResourceLocationAccessors
{
namespace ContextRegisters
{
public interface IRegisterType { }
public class CurrentRegisterType : IRegisterType { }
public class AddedRegisterType : IRegisterType { }
public class RemovedRegisterType : IRegisterType { }
public interface IContextRegister
{
public IEnumerable<Unit<TUnit>> Get<TResource, TUnit>(EffectContext context)
where TResource : Resource<TUnit>
where TUnit : IUnitType;
public void Set<TResource, TUnit>(EffectContext context, Unit<TUnit> value)
where TResource : Resource<TUnit>
where TUnit : IUnitType;
}
public class ContextRegister<TRegisterType> : IContextRegister where TRegisterType : IRegisterType
{
public IEnumerable<Unit<TUnit>> Get<TResource, TUnit>(EffectContext context)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
yield return context.GetResource<TResource, TUnit, ContextRegister<TRegisterType>>();
}
public void Set<TResource, TUnit>(EffectContext context, Unit<TUnit> value)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
context.SetResource<TResource, TUnit, ContextRegister<TRegisterType>>(value);
}
public override string ToString() => typeof(TRegisterType).Name;
}
[ProvideSourceInfo][Serializable] public sealed class Current : ContextRegister<CurrentRegisterType> { }
[ProvideSourceInfo][Serializable] public sealed class Added : ContextRegister<AddedRegisterType> { }
[ProvideSourceInfo][Serializable] public sealed class Removed : ContextRegister<RemovedRegisterType> { }
}
namespace Get
{
using ContextRegisters;
[ProvideSourceInfo]
[Serializable]
public class Context : IResourceLocationGet
{
[SerializeReference, ShowSerializeReference]
public IContextRegister Register;
public IEnumerable<Unit<TUnit>> Get<TResource, TUnit>(EffectInput data)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
return Register.Get<TResource, TUnit>(data.Context);
}
public override string ToString() => $"{nameof(Context)}.{Register}";
}
}
namespace Set
{
using ContextRegisters;
[ProvideSourceInfo]
[Serializable]
public class Context : IResourceLocationSet
{
[SerializeReference, ShowSerializeReference]
public IContextRegister Register;
[SerializeReference, ShowSerializeReference]
public IResourceOperator SetAs;
public void Set<TResource, TUnit>(EffectInput data, IEnumerable<Unit<TUnit>> values)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
Register.Set<TResource, TUnit>(data.Context, SetAs.OperateEnum(values));
}
public override string ToString() => $"{nameof(Context)}.{Register}";
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using CareBoo.Serially;
using TagFighter.Effects.ResourceLocationAccessors.ContextRegisters;
using TagFighter.Resources;
using UnityEngine;
namespace TagFighter.Effects
{
public interface IDelayedEffect
{
void DelayedAction(EffectInput data);
}
public interface IImmediateEffect
{
void ImmediateAction(EffectContext context, IEffect effect);
}
public interface IEffectMode
{
void Apply(EffectContext context);
void Effect(EffectContext context, IEffect effect);
}
[Serializable]
public class DelayedEffect : IImmediateEffect, IDelayedEffect
{
IEffect _effect;
public void DelayedAction(EffectInput data) {
_effect.Apply(data);
// direction towards target
var directionVector = (data.Context.EffectLocation.position - data.Context.Caster.position).normalized;
directionVector.y = 0;
var direction = Quaternion.LookRotation(directionVector, Vector3.up);
var appliedResource = data.Context.GetAllResourcesInRegister<Added>();
data.Context.EffectSystem.ApplyTagsEffect(appliedResource, data.Context.EffectLocation, direction, data.Context.AreaOfEffect);
}
public void ImmediateAction(EffectContext context, IEffect effect) {
if (effect != null) {
_effect = effect;
context.EffectsToTrigger.Add(this);
}
}
}
[Serializable]
public class ImmediateEffect : IImmediateEffect
{
[SerializeReference, ShowSerializeReference]
AoeShapes.IAoeShape _areaOfEffect;
public void ImmediateAction(EffectContext context, IEffect effect) {
if (effect != null) {
// direction towards target
var directionVector = (context.EffectLocation.position - context.Caster.position).normalized;
directionVector.y = 0;
var direction = Quaternion.LookRotation(directionVector, Vector3.up);
EffectInput data = new(context, Enumerable.Empty<Transform>(), StatModifierAccessor.Permanent);
var areaOfEffect = _areaOfEffect.AreaOfEffect(data);
// Copy the location of the effect and merge with the direction caster -> target
GameObject tmpGo = new();
tmpGo.transform.position = context.EffectLocation.position;
tmpGo.transform.rotation = direction;
data.Affected = areaOfEffect.GetAffectedUnits(tmpGo.transform);
GameObject.Destroy(tmpGo);
effect.Apply(data);
var appliedResource = context.GetAllResourcesInRegister<Added>();
context.EffectSystem.ApplyTagsEffect(appliedResource, context.EffectLocation, direction, areaOfEffect);
}
}
}
[Serializable]
public class ImmediateWeave : IImmediateEffect
{
public void ImmediateAction(EffectContext context, IEffect effect) {
EffectInput data = new(context, context.GetAffectedUnits(), StatModifierAccessor.Permanent);
if (effect != null) {
effect.Apply(data);
data.Affected = context.GetAffectedUnits();
}
Materialize(data);
}
void Materialize(EffectInput data) {
foreach (var effect in data.Context.EffectsToTrigger) {
effect.DelayedAction(data);
}
data.Context.EffectsToTrigger.Clear();
}
}
[Serializable]
public class PeriodicWeave : IImmediateEffect
{
[SerializeReference, ShowSerializeReference]
public AoeShapes.IAoeShape AreaOfEffect;
[SerializeReference, ShowSerializeReference]
public Triggers.ITrigger ApplyTrigger;
[SerializeReference, ShowSerializeReference]
public Triggers.ITrigger EndTrigger;
public bool IsPermanent;
public void ImmediateAction(EffectContext context, IEffect effect) {
EffectInput data = new(context, context.GetAffectedUnits(), StatModifierAccessor.Permanent);
if (effect != null) {
effect.Apply(data);
data.Affected = context.GetAffectedUnits();
}
Materialize(data);
}
void Materialize(EffectInput data) {
var areaOfEffect = AreaOfEffect.AreaOfEffect(data);
/// Move all effects in context to condition context.
List<IDelayedEffect> effectsToTrigger = new(data.Context.EffectsToTrigger);
data.Context.EffectsToTrigger.Clear();
var origin = data.Context.Caster;
foreach (var affectedPawn in data.Affected) {
var condition = IsPermanent ? affectedPawn.gameObject.AddComponent<PawnCondition>() : affectedPawn.gameObject.AddComponent<TransientPawnCondition>();
condition.EndTrigger = EndTrigger?.ShallowCopy();
condition.ApplyTrigger = ApplyTrigger?.ShallowCopy();
condition.Origin = origin;
condition.Context = new EffectContext() {
AreaOfEffect = areaOfEffect,
Caster = affectedPawn,
EffectLocation = affectedPawn,
EffectsToTrigger = effectsToTrigger
};
condition.Apply();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using CareBoo.Serially;
using TagFighter.Effects.ResourceLocationAccessors.ContextRegisters;
using TagFighter.Resources;
using UnityEngine;
namespace TagFighter.Effects
{
public interface IDelayedEffect
{
void DelayedAction(EffectInput data);
}
public interface IImmediateEffect
{
void ImmediateAction(EffectContext context, IEffect effect);
}
public interface IEffectMode
{
void Apply(EffectContext context);
void Effect(EffectContext context, IEffect effect);
}
[ProvideSourceInfo]
[Serializable]
public class DelayedEffect : IImmediateEffect, IDelayedEffect
{
IEffect _effect;
public void DelayedAction(EffectInput data) {
_effect.Apply(data);
// direction towards target
var directionVector = (data.Context.EffectLocation.position - data.Context.Caster.position).normalized;
directionVector.y = 0;
var direction = Quaternion.LookRotation(directionVector, Vector3.up);
var appliedResource = data.Context.GetAllResourcesInRegister<Added>();
data.Context.EffectSystem.ApplyTagsEffect(appliedResource, data.Context.EffectLocation, direction, data.Context.AreaOfEffect);
}
public void ImmediateAction(EffectContext context, IEffect effect) {
if (effect != null) {
_effect = effect;
context.EffectsToTrigger.Add(this);
}
}
}
[ProvideSourceInfo]
[Serializable]
public class ImmediateEffect : IImmediateEffect
{
[SerializeReference, ShowSerializeReference]
AoeShapes.IAoeShape _areaOfEffect;
public void ImmediateAction(EffectContext context, IEffect effect) {
if (effect != null) {
// direction towards target
var directionVector = (context.EffectLocation.position - context.Caster.position).normalized;
directionVector.y = 0;
var direction = Quaternion.LookRotation(directionVector, Vector3.up);
EffectInput data = new(context, Enumerable.Empty<Transform>(), StatModifierAccessor.Permanent);
var areaOfEffect = _areaOfEffect.AreaOfEffect(data);
// Copy the location of the effect and merge with the direction caster -> target
GameObject tmpGo = new();
tmpGo.transform.position = context.EffectLocation.position;
tmpGo.transform.rotation = direction;
data.Affected = areaOfEffect.GetAffectedUnits(tmpGo.transform);
GameObject.Destroy(tmpGo);
effect.Apply(data);
var appliedResource = context.GetAllResourcesInRegister<Added>();
context.EffectSystem.ApplyTagsEffect(appliedResource, context.EffectLocation, direction, areaOfEffect);
}
}
}
[ProvideSourceInfo]
[Serializable]
public class ImmediateWeave : IImmediateEffect
{
public void ImmediateAction(EffectContext context, IEffect effect) {
EffectInput data = new(context, context.GetAffectedUnits(), StatModifierAccessor.Permanent);
if (effect != null) {
effect.Apply(data);
data.Affected = context.GetAffectedUnits();
}
Materialize(data);
}
void Materialize(EffectInput data) {
foreach (var effect in data.Context.EffectsToTrigger) {
effect.DelayedAction(data);
}
data.Context.EffectsToTrigger.Clear();
}
}
[ProvideSourceInfo]
[Serializable]
public class PeriodicWeave : IImmediateEffect
{
[SerializeReference, ShowSerializeReference]
public AoeShapes.IAoeShape AreaOfEffect;
[SerializeReference, ShowSerializeReference]
public Triggers.ITrigger ApplyTrigger;
[SerializeReference, ShowSerializeReference]
public Triggers.ITrigger EndTrigger;
public bool IsPermanent;
public void ImmediateAction(EffectContext context, IEffect effect) {
EffectInput data = new(context, context.GetAffectedUnits(), StatModifierAccessor.Permanent);
if (effect != null) {
effect.Apply(data);
data.Affected = context.GetAffectedUnits();
}
Materialize(data);
}
void Materialize(EffectInput data) {
var areaOfEffect = AreaOfEffect.AreaOfEffect(data);
/// Move all effects in context to condition context.
List<IDelayedEffect> effectsToTrigger = new(data.Context.EffectsToTrigger);
data.Context.EffectsToTrigger.Clear();
var origin = data.Context.Caster;
foreach (var affectedPawn in data.Affected) {
var condition = IsPermanent ? affectedPawn.gameObject.AddComponent<PawnCondition>() : affectedPawn.gameObject.AddComponent<TransientPawnCondition>();
condition.EndTrigger = EndTrigger?.ShallowCopy();
condition.ApplyTrigger = ApplyTrigger?.ShallowCopy();
condition.Origin = origin;
condition.Context = new EffectContext() {
AreaOfEffect = areaOfEffect,
Caster = affectedPawn,
EffectLocation = affectedPawn,
EffectsToTrigger = effectsToTrigger
};
condition.Apply();
}
}
}
}
using System;
using System.Linq;
using CareBoo.Serially;
using UnityEngine;
namespace TagFighter.Effects
{
[Serializable]
public class AoeEffect : IEffect
{
[SerializeReference, ShowSerializeReference]
public AoeShapes.IAoeShape Shape;
public void Apply(EffectInput data) {
data.Context.AreaOfEffect = Shape.AreaOfEffect(data);
}
}
namespace AoeShapes
{
public interface IAoeShape
{
public IAreaOfEffect AreaOfEffect(EffectInput data);
}
[Serializable]
public class Single : IAoeShape
{
SingleTarget _areaOfEffect;
public IAreaOfEffect AreaOfEffect(EffectInput data) {
return _areaOfEffect.ShallowCopy();
}
}
[Serializable]
public class Circle : IAoeShape
{
public ResourceInfoGet<IResourceTypeAccessor, ResourceLocationAccessors.Get.Context> Radius;
CircleArea _areaOfEffect;
public IAreaOfEffect AreaOfEffect(EffectInput data) {
/// Currently Radius is a Context getter so there's only a single value in the iterator.
/// To support get from pawns, requires somekind of aggregation operator from <see cref="IResourceOperator"/>
/// to be included in this
_areaOfEffect.Radius = (float)Radius.Get(data).First();
return _areaOfEffect.ShallowCopy();
}
}
[Serializable]
public class Cone : IAoeShape
{
public ResourceInfoGet<IResourceTypeAccessor, ResourceLocationAccessors.Get.Context> Radius;
public ResourceInfoGet<IResourceTypeAccessor, ResourceLocationAccessors.Get.Context> Angle;
ConeArea _areaOfEffect;
public IAreaOfEffect AreaOfEffect(EffectInput data) {
/// Currently Radius and Angle are a Context getter so there's only a single value in the iterator.
/// To support get from pawns, requires somekind of aggregation operator from <see cref="IResourceOperator"/>
/// to be included in this
_areaOfEffect.Radius = (float)Radius.Get(data).First();
_areaOfEffect.Angle = (float)Angle.Get(data).First();
return _areaOfEffect.ShallowCopy();
}
}
[Serializable]
public class Path : IAoeShape
{
public ResourceInfoGet<IResourceTypeAccessor, ResourceLocationAccessors.Get.Context> Width;
public ResourceInfoGet<IResourceTypeAccessor, ResourceLocationAccessors.Get.Context> Length;
PathArea _areaOfEffect;
public IAreaOfEffect AreaOfEffect(EffectInput data) {
/// Currently Radius and Length are a Context getter so there's only a single value in the iterator.
/// To support get from pawns, requires somekind of aggregation operator from <see cref="IResourceOperator"/>
/// to be included in this
_areaOfEffect.Width = (float)Width.Get(data).First();
_areaOfEffect.Length = (float)Length.Get(data).First();
return _areaOfEffect.ShallowCopy();
}
}
}
}
using System;
using System.Linq;
using CareBoo.Serially;
using UnityEngine;
namespace TagFighter.Effects
{
[ProvideSourceInfo]
[Serializable]
public class AoeEffect : IEffect
{
[SerializeReference, ShowSerializeReference]
public AoeShapes.IAoeShape Shape;
public void Apply(EffectInput data) {
data.Context.AreaOfEffect = Shape.AreaOfEffect(data);
}
}
namespace AoeShapes
{
public interface IAoeShape
{
public IAreaOfEffect AreaOfEffect(EffectInput data);
}
[ProvideSourceInfo]
[Serializable]
public class Single : IAoeShape
{
SingleTarget _areaOfEffect;
public IAreaOfEffect AreaOfEffect(EffectInput data) {
return _areaOfEffect.ShallowCopy();
}
}
[ProvideSourceInfo]
[Serializable]
public class Circle : IAoeShape
{
public ResourceInfoGet<IResourceTypeAccessor, ResourceLocationAccessors.Get.Context> Radius;
CircleArea _areaOfEffect;
public IAreaOfEffect AreaOfEffect(EffectInput data) {
/// Currently Radius is a Context getter so there's only a single value in the iterator.
/// To support get from pawns, requires somekind of aggregation operator from <see cref="IResourceOperator"/>
/// to be included in this
_areaOfEffect.Radius = (float)Radius.Get(data).First();
return _areaOfEffect.ShallowCopy();
}
}
[ProvideSourceInfo]
[Serializable]
public class Cone : IAoeShape
{
public ResourceInfoGet<IResourceTypeAccessor, ResourceLocationAccessors.Get.Context> Radius;
public ResourceInfoGet<IResourceTypeAccessor, ResourceLocationAccessors.Get.Context> Angle;
ConeArea _areaOfEffect;
public IAreaOfEffect AreaOfEffect(EffectInput data) {
/// Currently Radius and Angle are a Context getter so there's only a single value in the iterator.
/// To support get from pawns, requires somekind of aggregation operator from <see cref="IResourceOperator"/>
/// to be included in this
_areaOfEffect.Radius = (float)Radius.Get(data).First();
_areaOfEffect.Angle = (float)Angle.Get(data).First();
return _areaOfEffect.ShallowCopy();
}
}
[ProvideSourceInfo]
[Serializable]
public class Path : IAoeShape
{
public ResourceInfoGet<IResourceTypeAccessor, ResourceLocationAccessors.Get.Context> Width;
public ResourceInfoGet<IResourceTypeAccessor, ResourceLocationAccessors.Get.Context> Length;
PathArea _areaOfEffect;
public IAreaOfEffect AreaOfEffect(EffectInput data) {
/// Currently Radius and Length are a Context getter so there's only a single value in the iterator.
/// To support get from pawns, requires somekind of aggregation operator from <see cref="IResourceOperator"/>
/// to be included in this
_areaOfEffect.Width = (float)Width.Get(data).First();
_areaOfEffect.Length = (float)Length.Get(data).First();
return _areaOfEffect.ShallowCopy();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using CareBoo.Serially;
using UnityEngine;
namespace TagFighter.Effects
{
[Serializable]
public class UnaryResourceEffect : IEffect
{
public ResourceInfoGet<IResourceTypeAccessor, IResourceLocationGet> From;
public ResourceInfoSet<IResourceTypeAccessor, IResourceLocationSet> To;
public void Apply(EffectInput data) {
var effectName = $"UnaryEffect ({From}) To ({To})";
Debug.Log($"{effectName} : Apply");
var resourceFrom = From.Get(data);
To.Set(data, resourceFrom);
}
}
[Serializable]
public class BinaryResourceEffect : IEffect
{
[SerializeReference, ShowSerializeReference]
public IResourceOperator Operator;
public ResourceInfoGet<IResourceTypeAccessor, IResourceLocationGet> FromA;
public ResourceInfoGet<IResourceTypeAccessor, IResourceLocationGet> FromB;
public ResourceInfoSet<IResourceTypeAccessor, IResourceLocationSet> To;
public void Apply(EffectInput data) {
var effectName = $"BinaryEffect({FromA} {Operator} {FromB})To({To})";
if (Operator == null) {
Debug.Log($"{effectName}: Apply missing operator, skipping");
return;
}
Debug.Log($"{effectName} : Apply");
var resourceFromA = FromA.Get(data).ToList();
var resourceFromB = FromB.Get(data).ToList();
var manipulated = Combine(resourceFromA, resourceFromB);
To.Set(data, manipulated);
}
IEnumerable<double> Combine(List<double> a, List<double> b) {
var (shortList, maybeLongList) = a.Count switch {
1 => (a, b),
_ => (b, a)
};
var repeatedShortList = Enumerable.Repeat(shortList, int.MaxValue).SelectMany((val) => val);
return maybeLongList.Zip(repeatedShortList, (x, y) => Operator.Operate(x, y));
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using CareBoo.Serially;
using UnityEngine;
namespace TagFighter.Effects
{
[ProvideSourceInfo]
[Serializable]
public class UnaryResourceEffect : IEffect
{
public ResourceInfoGet<IResourceTypeAccessor, IResourceLocationGet> From;
public ResourceInfoSet<IResourceTypeAccessor, IResourceLocationSet> To;
public void Apply(EffectInput data) {
var effectName = $"UnaryEffect ({From}) To ({To})";
Debug.Log($"{effectName} : Apply");
var resourceFrom = From.Get(data);
To.Set(data, resourceFrom);
}
}
[ProvideSourceInfo]
[Serializable]
public class BinaryResourceEffect : IEffect
{
[SerializeReference, ShowSerializeReference]
public IResourceOperator Operator;
public ResourceInfoGet<IResourceTypeAccessor, IResourceLocationGet> FromA;
public ResourceInfoGet<IResourceTypeAccessor, IResourceLocationGet> FromB;
public ResourceInfoSet<IResourceTypeAccessor, IResourceLocationSet> To;
public void Apply(EffectInput data) {
var effectName = $"BinaryEffect({FromA} {Operator} {FromB})To({To})";
if (Operator == null) {
Debug.Log($"{effectName}: Apply missing operator, skipping");
return;
}
Debug.Log($"{effectName} : Apply");
var resourceFromA = FromA.Get(data).ToList();
var resourceFromB = FromB.Get(data).ToList();
var manipulated = Combine(resourceFromA, resourceFromB);
To.Set(data, manipulated);
}
IEnumerable<double> Combine(List<double> a, List<double> b) {
var (shortList, maybeLongList) = a.Count switch {
1 => (a, b),
_ => (b, a)
};
var repeatedShortList = Enumerable.Repeat(shortList, int.MaxValue).SelectMany((val) => val);
return maybeLongList.Zip(repeatedShortList, (x, y) => Operator.Operate(x, y));
}
}
}