ZJ77PUPSEGVVS6C2RNGGSJCBSOXRR4ZXNSUVB5LL2R5NBPE7TT5QC A5CUHNRA24QIBOJ2MSSUSXDL6JXVWEVDQS4WDJE46NICUOAVBAZAC J75RIWLT42QXABT6GQMAVIOP5XDUF7UAGFQUSSKDIULB3LEB22EQC X6CHZAXRC53ABZQSK5QK5PP3QTNJOSGRFGJHNEQBLRSD2UB32AFQC VZRSH4U473FCZOP5EXURPXXN5J6F3ZLT435YY7A2JHLG2ZZB5KLQC 7BZ73FLUK5ANK44V7EMAROTHHVE2IGJ65GTA26DRWY65566HMNPAC AZN3UTBQLTKMGIHW5UCAMLC4GGHG6MAORBQ7OIR2U7NTZ53GWGNQC W42U55HSXS45MZUEXGCSKLO5UV4CWBQN2IZPCKZPWPDSB56FVZDAC MML56TWYWB6SUY5JEWHG2PNLAH3JY72PGCEXIGOYE54EAC2WSWBAC 7QKPEDFDFQJFTXM4BFJ4CFHOOZKOI6NKRRSBDLMP7SELPJMFOQRAC G4XIS2NEM4WHRP2775YBCLFDT7JZZS52CMEHY3PA43QSXL45XNDAC 3UN6NREN32ZBQW4EWI7ED4WVQILCU2EIE7DQGFWZR3OUDCO3ZSPQC R475KN7MR3OG7EBLVNOO7QRIKXDGY2PIDXXV3HW4KBD5QM7B5OJQC DTKCWM4J7PFNWAAES3RZHQGDA6PTDNX4TZVOXAKF5V7LCZBI3XUAC 62S5AKAC5VGAT4KZYRO4R6XIHO4CCD3RAUHQSW47VEGVEBNZGTGAC RJXFDWT7OWTX3DQ7SBJFK6M66AQ2LGGIO32QD6G7VTJJS7U2R7XQC 2RUZ7TTRT7SMZT2V7YWUCCTJJXNRT2LNJ2QBBVN4RMREMOGMGMHQC XRWOXKR3MD3O73SH33CWRUYMTS6KVWGN6U2AIKNVNGHN37MY7UYQC RZAMG2H2NY73KZJIV4VXLJHJVSRGJDRWWZJERAI6O7AVDW64JEQQC 426KOWJWOX7ZE24UIJCIHRI5KUZYO6NIGK7KC2HOONFDX242UYIQC GBGS6RTZTCKRMLLDVCBGMRTJNNOSAUTXN5D2EMEQMQAREORE54PAC L2SE4UCTEU4R7JSHG2J5H6RZPRN4SGBMXK3WCRED2HARX5JEN2AQC F6P3X2CWO6LA5VH5U64XMPQXIKA3FMDK5MFSKZJFJTFISAL7WKMQC R6RQ2RKQV3YFYIRN5JED6NAFB4E34WQJRDHHKZ4JO7KLBXRKNFYAC IXGU2SOXBCQYBV3S5EHZFEFJKSCVUQPVZ3NY7KPG2UHWTEVGRZCAC Y4T55M6RWGCCDBFO6OPEEVDBO3SZ4F3XESUZJST3LUQYGTIFG72AC G6KBRZNCPEBI5YF2ZJYRAFCYDO3CDGFPQBDC3I4JQEYJ4DNT234AC CD5FF75KTOBTMVMTMCKMR6F5DFKOF26I5K43ITNHGBI3ZAZHA4RAC JMMGK6VQWZOLY6C6YWUPAIHLQXUZ2ZZTVJQAL7ODPZAWUSZQIJJAC VU32ZIRYU6LCQJFGN4ZA3IQ5HNY5J4PNI5OCPW24L7YBOI3BOTYAC HXTSBPAP75A7EC4RKWYQMVPPHPNZFPHUORBZWDHGEB6MPAGI7G7AC 3AONCSBYJ6T2HXAZFLCJGGV6SRNYJW3PEJ5GMGN3FYB2NGPVIQIQC JAZ27QX53QXAN4JVMMX2KYKN4GCULWFMXYSPFZ5HWW4T7FUB5EHAC S256EPZUSOF4TV2KGOFZDJXUFDD57GZFYTCARFJ3SD24RPC56PHAC 754VCJRLAZAVIQP7STLUIHP3U7PUHBTYAHLNQK4A2H6IKYVNTDKAC COV4RS6N6Z7PJ5S6LZGNSTP77UJNTKN42OI6K7CBQH6TKCS7ITLQC using System;using TagFighter.Effects;using TagFighter.Resources;using UnityEngine;namespace TagFighter{public class WeaveAction : IAction{FollowAction _followAction;Transform _target;Weaver _weaver;RuneWeavingContainer _runeWeaving;Resources.Range _range;bool _startedWeaving = false;static State s_resetState = new(true, 1f, false, default);bool _disposed = false;int _lastRange;EffectContext _context;ITimeContextContainer _timeContextContainer;public WeaveAction(Weaver unit, RuneWeavingContainer runeWeaving, Transform target, Resources.Range range) {if (range == null) {throw new ArgumentNullException("range");}_target = target;_range = range;_weaver = unit;_runeWeaving = runeWeaving;var currentRange = _range.GetCurrent();_lastRange = currentRange.AsPrimitive();_followAction = new(_weaver, _target, currentRange.ToMeter());_range.ResourceChanged += OnResourceChanged;_context = new EffectContext(caster: unit.transform, effectLocation: target);}void OnResourceChanged(object sender, ResourceChangeArgs e) {if (_lastRange != e.Current) {_followAction.Dispose();_followAction = new(_weaver, _target, _range.GetCurrent().ToMeter());_lastRange = e.Current;}}public IActionState Advance() {var stateToReturn = _followAction.Advance();if (IsInAttackRange()) {if (_startedWeaving == false) {Debug.Log("Target got in range, weaving");_timeContextContainer = _runeWeaving.RuneWeaving.CreateTimeContexts();}_startedWeaving = true;var isAdvanced = _runeWeaving.RuneWeaving.Advance(_timeContextContainer, _context, Time.deltaTime);stateToReturn = new State(isAdvanced, CompletionStatus(), false, _runeWeaving.RuneWeaving.GetCurrentMove(_timeContextContainer));}else {if (_startedWeaving) {Debug.Log("Target escaped");stateToReturn = new State(false, CompletionStatus(), stateToReturn.IsMoving, _runeWeaving.RuneWeaving.GetCurrentMove(_timeContextContainer));}}return stateToReturn;}IActionState Cancel() {_timeContextContainer = null;return s_resetState;}public float CompletionStatus() => _runeWeaving.RuneWeaving.CompletionStatus(_timeContextContainer);public bool IsSimilarAction(IActionRead action) {if (action is not WeaveAction other) {return false;}return other != null && _target == other._target && _weaver == other._weaver && _runeWeaving.WeaveName == other._runeWeaving.WeaveName;}public override string ToString() {return $"{_runeWeaving.WeaveName} -> {_target.name}";}bool IsInAttackRange() {// Incorrect in case there are hills. should calc range from feet.Vector3 source = new(_weaver.transform.position.x, 0, _weaver.transform.position.z);Vector3 target = new(_target.position.x, 0, _target.position.z);return Vector3.Distance(source, target) <= _range.GetCurrent().ToMeter();}public void Dispose() {Dispose(true);GC.SuppressFinalize(this);}protected virtual void Dispose(bool disposing) {if (!_disposed) {if (disposing) {Cancel();_followAction.Dispose();_followAction = null;_range.ResourceChanged -= OnResourceChanged;_range = null;_runeWeaving = null;_target = null;_weaver = null;}_disposed = true;}}public readonly struct State : IActionState{public bool IsAdvanced { get; }public float CompletionStatus { get; }public bool IsMoving { get; }public CombatMove Move { get; }public State(bool isAdvanced, float completionStatus, bool isMoving, CombatMove move) {IsAdvanced = isAdvanced;CompletionStatus = completionStatus;IsMoving = isMoving;Move = move;}}}}
using System;using TagFighter.Effects;using TagFighter.Resources;using UnityEngine;namespace TagFighter{public class WeaveAction : IAction{FollowAction _followAction;Transform _target;Weaver _weaver;RuneWeavingContainer _runeWeaving;Resources.Range _range;bool _startedWeaving = false;static State s_resetState = new(true, 1f, false, default);bool _disposed = false;int _lastRange;EffectContext _context;ITimeContextContainer _timeContextContainer;public WeaveAction(Weaver unit, RuneWeavingContainer runeWeaving, Transform target, Resources.Range range) {if (range == null) {throw new ArgumentNullException("range");}_target = target;_range = range;_weaver = unit;_runeWeaving = runeWeaving;var currentRange = _range.GetCurrent();_lastRange = currentRange.AsPrimitive();_followAction = new(_weaver, _target, currentRange.ToMeter());_range.ResourceChanged += OnResourceChanged;_context = new EffectContext(new(unit.transform), new(target));}void OnResourceChanged(object sender, ResourceChangeArgs e) {if (_lastRange != e.Current) {_followAction.Dispose();_followAction = new(_weaver, _target, _range.GetCurrent().ToMeter());_lastRange = e.Current;}}public IActionState Advance() {var stateToReturn = _followAction.Advance();if (IsInAttackRange()) {if (_startedWeaving == false) {Debug.Log("Target got in range, weaving");_timeContextContainer = _runeWeaving.RuneWeaving.CreateTimeContexts();}_startedWeaving = true;var isAdvanced = _runeWeaving.RuneWeaving.Advance(_timeContextContainer, _context, Time.deltaTime);stateToReturn = new State(isAdvanced, CompletionStatus(), false, _runeWeaving.RuneWeaving.GetCurrentMove(_timeContextContainer));}else {if (_startedWeaving) {Debug.Log("Target escaped");stateToReturn = new State(false, CompletionStatus(), stateToReturn.IsMoving, _runeWeaving.RuneWeaving.GetCurrentMove(_timeContextContainer));}}return stateToReturn;}IActionState Cancel() {_timeContextContainer = null;return s_resetState;}public float CompletionStatus() => _runeWeaving.RuneWeaving.CompletionStatus(_timeContextContainer);public bool IsSimilarAction(IActionRead action) {if (action is not WeaveAction other) {return false;}return other != null && _target == other._target && _weaver == other._weaver && _runeWeaving.WeaveName == other._runeWeaving.WeaveName;}public override string ToString() {return $"{_runeWeaving.WeaveName} -> {_target.name}";}bool IsInAttackRange() {// Incorrect in case there are hills. should calc range from feet.Vector3 source = new(_weaver.transform.position.x, 0, _weaver.transform.position.z);Vector3 target = new(_target.position.x, 0, _target.position.z);return Vector3.Distance(source, target) <= _range.GetCurrent().ToMeter();}public void Dispose() {Dispose(true);GC.SuppressFinalize(this);}protected virtual void Dispose(bool disposing) {if (!_disposed) {if (disposing) {Cancel();_followAction.Dispose();_followAction = null;_range.ResourceChanged -= OnResourceChanged;_range = null;_runeWeaving = null;_target = null;_weaver = null;}_disposed = true;}}public readonly struct State : IActionState{public bool IsAdvanced { get; }public float CompletionStatus { get; }public bool IsMoving { get; }public CombatMove Move { get; }public State(bool isAdvanced, float completionStatus, bool isMoving, CombatMove move) {IsAdvanced = isAdvanced;CompletionStatus = completionStatus;IsMoving = isMoving;Move = move;}}}}
using System.Collections.Generic;using TagFighter.Resources;using UnityEngine;using System;public interface IEffectSystem{void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, Transform origin, Quaternion direction, IAreaOfEffect areaOfEffect);void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, Transform origin, Transform effectLocation, IAreaOfEffect areaOfEffect);Color GetEffectColor(IEnumerable<(Type, IUnit)> tags);Mesh CreateArcMesh(Vector3 direction, float arc, float length, int numberOfVerticesInArc, Vector3 rotationAxis);Mesh CreateQuadMesh(Vector3 direction, float width, float length, Vector3 rotationAxis);}
using System.Collections.Generic;using TagFighter.Resources;using UnityEngine;using System;namespace TagFighter{public interface IEffectSystem{void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, IAreaOfEffect areaOfEffect);void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, EffectTarget effectLocation, IAreaOfEffect areaOfEffect);Color GetEffectColor(IEnumerable<(Type, IUnit)> tags);Mesh CreateArcMesh(float arc, float length, int numberOfVerticesInArc, Vector3 rotationAxis);Mesh CreateQuadMesh(float width, float length, Vector3 rotationAxis);}}
#nullable enableusing 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(material, PlayTime));}public IEnumerator PlayEffect(Material material, float playTime) {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;}}public void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, Transform origin, Transform effectLocation, IAreaOfEffect areaOfEffect) {var directionVector = (effectLocation.position - origin.position).normalized;directionVector.y = 0;var direction = Quaternion.LookRotation(directionVector, Vector3.up);ApplyTagsEffect(tags, origin, direction, areaOfEffect);}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 resourceMaterial 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 resourceMaterial 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 resourceMaterial 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 amountcolor += 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? directionvar 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 triangle0, 2, 1,// upper right triangle2, 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;}}
#nullable enablenamespace TagFighter{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] 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(material, PlayTime));}public IEnumerator PlayEffect(Material material, float playTime) {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, EffectOrigin 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;}}public void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, EffectTarget effectLocation, IAreaOfEffect areaOfEffect) {var directionVector = (effectLocation.Transform.position - origin.Transform.position).normalized;directionVector.y = 0;var direction = Quaternion.LookRotation(directionVector, Vector3.up);ApplyTagsEffect(tags, origin, direction, areaOfEffect);}void ApplyTagsEffectSingle() {Debug.Log("ApplyTagsEffectSingle");}void ApplyTagsEffectPath(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, PathArea areaOfEffect) {var color = GetEffectColor(tags);var mesh = CreateQuadMeshForUnit(origin.Transform, areaOfEffect.Width, areaOfEffect.Length);// Add a new to clone the shared resourceMaterial material = new(UnityEngine.Resources.Load<Material>(PulseMaterial));material.SetColor("_Color", color);DisplayEffect(origin, direction, mesh, material);}void ApplyTagsEffectRadius(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, CircleArea areaOfEffect) {var color = GetEffectColor(tags);var mesh = CreateArcMeshForUnit(origin.Transform, 360, areaOfEffect.Radius);// Add a new to clone the shared resourceMaterial material = new(UnityEngine.Resources.Load<Material>(PulseMaterial));material.SetColor("_Color", color);DisplayEffect(origin, direction, mesh, material);}void ApplyTagsEffectCone(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, ConeArea areaOfEffect) {Debug.Log("ApplyTagsEffectCone");var color = GetEffectColor(tags);var mesh = CreateArcMeshForUnit(origin.Transform, areaOfEffect.Angle, areaOfEffect.Radius);// Add a new to clone the shared resourceMaterial material = new(UnityEngine.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 amountcolor += mappedColor;}}}Debug.Log("GetEffectColor Finished");return color;}public Mesh CreateArcMeshForUnit(Transform unit, float arc, float length, int numberOfVerticesInArc = 100) {return CreateArcMesh(arc, length, numberOfVerticesInArc, Vector3.up);}public Mesh CreateQuadMeshForUnit(Transform unit, float width, float length) {return CreateQuadMesh(width, length, Vector3.up);}void DisplayEffect(EffectOrigin originUnit, Quaternion direction, Mesh mesh, Material material) {GameObject effectObj = new();effectObj.SetActive(false);effectObj.transform.position = originUnit.Transform.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(float arc, float length, int numberOfVerticesInArc, Vector3 rotationAxis) {var origin = Vector3.zero;var direction = Vector3.forward;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(float width, float length, Vector3 rotationAxis) {Mesh mesh = new();var origin = Vector3.zero;// TODO: how to calculate local rotation? directionvar 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 triangle0, 2, 1,// upper right triangle2, 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.Collections.Generic;using TagFighter.Resources;using UnityEngine;using System;class DummyEffectSystem : IEffectSystem{public void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, Transform origin, Quaternion direction, IAreaOfEffect areaOfEffect) {Debug.Log("Dummy:ApplyTagsEffect");}public void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, Transform origin, Transform effectLocation, IAreaOfEffect areaOfEffect) {Debug.Log("Dummy:ApplyTagsEffect");}public Color GetEffectColor(IEnumerable<(Type, IUnit)> tags) {Debug.Log("Dummy:GetEffectColor");return Color.cyan;}public Mesh CreateArcMesh(Vector3 direction, float arc, float length, int numberOfVerticesInArc, Vector3 rotationAxis) {Debug.Log("Dummy:CreateArcMesh");return null;}public Mesh CreateQuadMesh(Vector3 direction, float width, float length, Vector3 rotationAxis) {Debug.Log("Dummy:CreateQuadMesh");return null;}}
namespace TagFighter{using System.Collections.Generic;using TagFighter.Resources;using UnityEngine;using System;class DummyEffectSystem : IEffectSystem{public void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, Quaternion direction, IAreaOfEffect areaOfEffect) {Debug.Log("Dummy:ApplyTagsEffect");}public void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, EffectOrigin origin, EffectTarget effectLocation, IAreaOfEffect areaOfEffect) {Debug.Log("Dummy:ApplyTagsEffect");}public Color GetEffectColor(IEnumerable<(Type, IUnit)> tags) {Debug.Log("Dummy:GetEffectColor");return Color.cyan;}public Mesh CreateArcMesh(float arc, float length, int numberOfVerticesInArc, Vector3 rotationAxis) {Debug.Log("Dummy:CreateArcMesh");return null;}public Mesh CreateQuadMesh(float width, float length, Vector3 rotationAxis) {Debug.Log("Dummy:CreateQuadMesh");return null;}}}
using System;using System.Collections.Generic;using System.Linq;using TagFighter.Effects;using TagFighter.Martial;using UnityEngine;[Serializable]public class MartialSequence : ISequence{[UnityEngine.Serialization.FormerlySerializedAs("combatMoveRefs")][SerializeField] List<CombatMoveRef> _combatMoveRefs;public MartialSequence(IEnumerable<CombatMoveRef> combatMoveRefsSequence) {_combatMoveRefs = combatMoveRefsSequence.ToList();}public bool Advance(ITimeContextContainer timeContextContainer, EffectContext effectContext, float deltaTime) {var timeContext = timeContextContainer.GetTimeContext<MartialSequence>();if (timeContext.CurrentIdx >= _combatMoveRefs.Count) {Debug.Log($"Executed Martial Sequence {timeContext.CurrentIdx}/{_combatMoveRefs.Count} moves in {timeContext.CurrentTime} seconds");return false;}timeContext.CurrentTime += deltaTime;while ((timeContext.CurrentIdx < _combatMoveRefs.Count) && (timeContext.CurrentTime - timeContext.LastTime >= _combatMoveRefs[timeContext.CurrentIdx].CombatMove.Speed)) {Debug.Log($"Finished executing Martial move {_combatMoveRefs[timeContext.CurrentIdx].CombatMove.MoveName} {timeContext.CurrentIdx + 1}/{_combatMoveRefs.Count} at {timeContext.CurrentTime}");// TODO : Actual Execute MovetimeContext.LastTime += _combatMoveRefs[timeContext.CurrentIdx].CombatMove.Speed;timeContext.CurrentIdx++;}SetReleaseMultiplier(timeContextContainer, effectContext);return true;}void SetReleaseMultiplier(ITimeContextContainer timeContextContainer, EffectContext context) {var currentMove = GetCurrentMove(timeContextContainer);if (currentMove == null) {return;}var caster = context.Caster;var animator = caster.gameObject.GetComponentInChildren<Animator>();var currentAnimationState = animator.GetCurrentAnimatorStateInfo(0);var posInAnimation = currentAnimationState.normalizedTime;//Debug.Log($"posInAnimation {posInAnimation}");var positionalReleaseMultiplier = 1f;if ((currentMove.StartReleaseNormalized < posInAnimation) && (posInAnimation < currentMove.EndReleaseNormalized)) {// this means we're in the maximal release sectionpositionalReleaseMultiplier = 1f;}else if (posInAnimation < currentMove.StartReleaseNormalized) {// otherwise, get a partial bonus in reletaion to how close we are to the relesepositionalReleaseMultiplier = posInAnimation / currentMove.StartReleaseNormalized;}else if (currentMove.EndReleaseNormalized < posInAnimation) {// otherwise, get a partial bonus in reletaion to how far we are from the releasepositionalReleaseMultiplier = (1 - posInAnimation) / (1 - currentMove.EndReleaseNormalized);}// Debug.Log($"positionalReleaseMultiplier {positionalReleaseMultiplier}");context.ReleaseMultiplier = new() {MatchingAoe = currentMove.MatchingAoe,MatchingAoeReleaseMultiplier = currentMove.MatchingAoeReleaseMultiplier * positionalReleaseMultiplier,NonMatchingAoeReleaseMultiplier = currentMove.NonMatchingAoeReleaseMultiplier * positionalReleaseMultiplier,};}public void Simulate() {}public CombatMove GetCurrentMove(ITimeContextContainer timeContextContainer) {if (timeContextContainer == null) {return null;}var timeContext = timeContextContainer.GetTimeContext<MartialSequence>();CombatMove move = default;if (timeContext.CurrentIdx < _combatMoveRefs.Count) {move = _combatMoveRefs[timeContext.CurrentIdx];}return move;}public IEnumerable<CombatMoveRef> GetSequence() => _combatMoveRefs;public float CompletionStatus(ITimeContextContainer timeContextContainer) {if (timeContextContainer == null) {return 0;}var timeContext = timeContextContainer.GetTimeContext<MartialSequence>();return timeContext.CurrentTime / _combatMoveRefs.Sum((move) => move.CombatMove.Speed);}}
using System;using System.Collections.Generic;using System.Linq;using TagFighter.Effects;using TagFighter.Martial;using UnityEngine;[Serializable]public class MartialSequence : ISequence{[UnityEngine.Serialization.FormerlySerializedAs("combatMoveRefs")][SerializeField] List<CombatMoveRef> _combatMoveRefs;public MartialSequence(IEnumerable<CombatMoveRef> combatMoveRefsSequence) {_combatMoveRefs = combatMoveRefsSequence.ToList();}public bool Advance(ITimeContextContainer timeContextContainer, EffectContext effectContext, float deltaTime) {var timeContext = timeContextContainer.GetTimeContext<MartialSequence>();if (timeContext.CurrentIdx >= _combatMoveRefs.Count) {Debug.Log($"Executed Martial Sequence {timeContext.CurrentIdx}/{_combatMoveRefs.Count} moves in {timeContext.CurrentTime} seconds");return false;}timeContext.CurrentTime += deltaTime;while ((timeContext.CurrentIdx < _combatMoveRefs.Count) && (timeContext.CurrentTime - timeContext.LastTime >= _combatMoveRefs[timeContext.CurrentIdx].CombatMove.Speed)) {Debug.Log($"Finished executing Martial move {_combatMoveRefs[timeContext.CurrentIdx].CombatMove.MoveName} {timeContext.CurrentIdx + 1}/{_combatMoveRefs.Count} at {timeContext.CurrentTime}");// TODO : Actual Execute MovetimeContext.LastTime += _combatMoveRefs[timeContext.CurrentIdx].CombatMove.Speed;timeContext.CurrentIdx++;}SetReleaseMultiplier(timeContextContainer, effectContext);return true;}void SetReleaseMultiplier(ITimeContextContainer timeContextContainer, EffectContext context) {var currentMove = GetCurrentMove(timeContextContainer);if (currentMove == null) {return;}var caster = context.Caster;var animator = caster.Transform.gameObject.GetComponentInChildren<Animator>();var currentAnimationState = animator.GetCurrentAnimatorStateInfo(0);var posInAnimation = currentAnimationState.normalizedTime;//Debug.Log($"posInAnimation {posInAnimation}");var positionalReleaseMultiplier = 1f;if ((currentMove.StartReleaseNormalized < posInAnimation) && (posInAnimation < currentMove.EndReleaseNormalized)) {// this means we're in the maximal release sectionpositionalReleaseMultiplier = 1f;}else if (posInAnimation < currentMove.StartReleaseNormalized) {// otherwise, get a partial bonus in reletaion to how close we are to the relesepositionalReleaseMultiplier = posInAnimation / currentMove.StartReleaseNormalized;}else if (currentMove.EndReleaseNormalized < posInAnimation) {// otherwise, get a partial bonus in reletaion to how far we are from the releasepositionalReleaseMultiplier = (1 - posInAnimation) / (1 - currentMove.EndReleaseNormalized);}// Debug.Log($"positionalReleaseMultiplier {positionalReleaseMultiplier}");context.ReleaseMultiplier = new() {MatchingAoe = currentMove.MatchingAoe,MatchingAoeReleaseMultiplier = currentMove.MatchingAoeReleaseMultiplier * positionalReleaseMultiplier,NonMatchingAoeReleaseMultiplier = currentMove.NonMatchingAoeReleaseMultiplier * positionalReleaseMultiplier,};}public void Simulate() {}public CombatMove GetCurrentMove(ITimeContextContainer timeContextContainer) {if (timeContextContainer == null) {return null;}var timeContext = timeContextContainer.GetTimeContext<MartialSequence>();CombatMove move = default;if (timeContext.CurrentIdx < _combatMoveRefs.Count) {move = _combatMoveRefs[timeContext.CurrentIdx];}return move;}public IEnumerable<CombatMoveRef> GetSequence() => _combatMoveRefs;public float CompletionStatus(ITimeContextContainer timeContextContainer) {if (timeContextContainer == null) {return 0;}var timeContext = timeContextContainer.GetTimeContext<MartialSequence>();return timeContext.CurrentTime / _combatMoveRefs.Sum((move) => move.CombatMove.Speed);}}
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 targetvar 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 targetvar 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 -> targetGameObject 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(caster: affectedPawn, effectLocation: affectedPawn) {AreaOfEffect = areaOfEffect,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 targetvar directionVector = (data.Context.EffectLocation.Transform.position - data.Context.Caster.Transform.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.Caster, 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 targetvar directionVector = (context.EffectLocation.Transform.position - context.Caster.Transform.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 -> targetGameObject tmpGo = new();tmpGo.transform.position = context.EffectLocation.Transform.position;tmpGo.transform.rotation = direction;data.Affected = areaOfEffect.GetAffectedUnits(new(tmpGo.transform));GameObject.Destroy(tmpGo);effect.Apply(data);var appliedResource = context.GetAllResourcesInRegister<Added>();context.EffectSystem.ApplyTagsEffect(appliedResource, context.Caster, 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(new(affectedPawn), new(affectedPawn)) {AreaOfEffect = areaOfEffect,EffectsToTrigger = effectsToTrigger};condition.Apply();}}}}
#nullable enableusing System;using System.Collections.Generic;using System.Linq;using TagFighter.Effects.ResourceLocationAccessors.ContextRegisters;using TagFighter.Effects.Steps;using TagFighter.Resources;using UnityEngine;namespace TagFighter.Effects{public class ReleaseMultiplier{public Type? MatchingAoe { get; set; }public float MatchingAoeReleaseMultiplier { get; set; } = 1f;public float NonMatchingAoeReleaseMultiplier { get; set; } = 1f;}public record RegistryKey{public Type ContextRegisterType;public Type ResourceType;public RegistryKey(Type contextRegisterType, Type resourceType) {ContextRegisterType = contextRegisterType;ResourceType = resourceType;}}public class EffectContext{Dictionary<RegistryKey, IUnit> _resourceRegistry = new();public Transform Caster { get; set; }public Transform EffectLocation { get; set; }public IAreaOfEffect AreaOfEffect;public List<IDelayedEffect> EffectsToTrigger { get; set; } = new();public List<OutputStep<bool>> EffectStepsToTrigger { get; set; } = new();public IEffectSystem EffectSystem { get; private set; }public ReleaseMultiplier ReleaseMultiplier { get; set; }public EffectContext(Transform caster, Transform effectLocation) {EffectSystem = SystemsHandler.EffectSystem;ReleaseMultiplier = new();Caster = caster;EffectLocation = effectLocation;AreaOfEffect = new SingleTarget();}public Unit<TUnit> GetResource<TResource, TUnit, TContextRegister>()where TResource : Resource<TUnit>where TUnit : IUnitTypewhere TContextRegister : IContextRegister {var key = new RegistryKey(typeof(TContextRegister), typeof(TResource));var value = (Unit<TUnit>)_resourceRegistry.GetValueOrDefault(key, (Unit<TUnit>)0);Debug.Log($"{nameof(GetResource)} ({typeof(TResource).Name},{typeof(TContextRegister).Name}) = {value}");return value;}public Unit<TUnit> SetResource<TResource, TUnit, TContextRegister>(Unit<TUnit> value)where TResource : Resource<TUnit>where TUnit : IUnitTypewhere TContextRegister : IContextRegister {var key = new RegistryKey(typeof(TContextRegister), typeof(TResource));var newValue = (Unit<TUnit>)(_resourceRegistry[key] = value);Debug.Log($"{nameof(SetResource)} ({typeof(TResource).Name},{typeof(TContextRegister).Name}) = {newValue}");return newValue;}public IEnumerable<(Type, IUnit)> GetAllResourcesInRegister<TContextRegister>() where TContextRegister : IContextRegister {return _resourceRegistry.Where(x => x.Key.ContextRegisterType == typeof(TContextRegister)).Select(x => (x.Key.ResourceType, x.Value));}public IEnumerable<Transform> GetAffectedUnits() {var directionVector = (EffectLocation.position - Caster.position).normalized;directionVector.y = 0;var direction = Quaternion.LookRotation(directionVector, Vector3.up);GameObject tmpGo = new();tmpGo.transform.position = EffectLocation.position;tmpGo.transform.rotation = direction;var affectedUnits = AreaOfEffect.GetAffectedUnits(EffectLocation);GameObject.Destroy(tmpGo);return affectedUnits;}void ResetEffects() {EffectsToTrigger.Clear();EffectStepsToTrigger.Clear();}public void Reset() {ResetEffects();}}}
#nullable enableusing System;using System.Collections.Generic;using System.Linq;using TagFighter.Effects.ResourceLocationAccessors.ContextRegisters;using TagFighter.Effects.Steps;using TagFighter.Resources;using UnityEngine;namespace TagFighter{public struct EffectOrigin{public Transform Transform;public EffectOrigin(Transform transform) {Transform = transform;}}public struct EffectTarget{public Transform Transform;public EffectTarget(Transform transform) {Transform = transform;}}}namespace TagFighter.Effects{public class ReleaseMultiplier{public Type? MatchingAoe { get; set; }public float MatchingAoeReleaseMultiplier { get; set; } = 1f;public float NonMatchingAoeReleaseMultiplier { get; set; } = 1f;}public record RegistryKey{public Type ContextRegisterType;public Type ResourceType;public RegistryKey(Type contextRegisterType, Type resourceType) {ContextRegisterType = contextRegisterType;ResourceType = resourceType;}}public class EffectContext{Dictionary<RegistryKey, IUnit> _resourceRegistry = new();public EffectOrigin Caster { get; set; }public EffectTarget EffectLocation { get; set; }public IAreaOfEffect AreaOfEffect;public List<IDelayedEffect> EffectsToTrigger { get; set; } = new();public List<OutputStep<bool>> EffectStepsToTrigger { get; set; } = new();public IEffectSystem EffectSystem { get; private set; }public ReleaseMultiplier ReleaseMultiplier { get; set; }public EffectContext(EffectOrigin caster, EffectTarget effectLocation) {EffectSystem = SystemsHandler.EffectSystem;ReleaseMultiplier = new();Caster = caster;EffectLocation = effectLocation;AreaOfEffect = new SingleTarget();}public Unit<TUnit> GetResource<TResource, TUnit, TContextRegister>()where TResource : Resource<TUnit>where TUnit : IUnitTypewhere TContextRegister : IContextRegister {var key = new RegistryKey(typeof(TContextRegister), typeof(TResource));var value = (Unit<TUnit>)_resourceRegistry.GetValueOrDefault(key, (Unit<TUnit>)0);Debug.Log($"{nameof(GetResource)} ({typeof(TResource).Name},{typeof(TContextRegister).Name}) = {value}");return value;}public Unit<TUnit> SetResource<TResource, TUnit, TContextRegister>(Unit<TUnit> value)where TResource : Resource<TUnit>where TUnit : IUnitTypewhere TContextRegister : IContextRegister {var key = new RegistryKey(typeof(TContextRegister), typeof(TResource));var newValue = (Unit<TUnit>)(_resourceRegistry[key] = value);Debug.Log($"{nameof(SetResource)} ({typeof(TResource).Name},{typeof(TContextRegister).Name}) = {newValue}");return newValue;}public IEnumerable<(Type, IUnit)> GetAllResourcesInRegister<TContextRegister>() where TContextRegister : IContextRegister {return _resourceRegistry.Where(x => x.Key.ContextRegisterType == typeof(TContextRegister)).Select(x => (x.Key.ResourceType, x.Value));}public IEnumerable<Transform> GetAffectedUnits() {var directionVector = (EffectLocation.Transform.position - Caster.Transform.position).normalized;directionVector.y = 0;var direction = Quaternion.LookRotation(directionVector, Vector3.up);GameObject tmpGo = new();tmpGo.transform.position = EffectLocation.Transform.position;tmpGo.transform.rotation = direction;var affectedUnits = AreaOfEffect.GetAffectedUnits(Caster);GameObject.Destroy(tmpGo);return affectedUnits;}void ResetEffects() {EffectsToTrigger.Clear();EffectStepsToTrigger.Clear();}public void Reset() {ResetEffects();}}}
[Serializable]public class SingleTarget : IAreaOfEffect{public IEnumerable<Transform> GetAffectedUnits(Transform origin) {return new Transform[] { origin };
public interface IAreaOfEffect{public IEnumerable<Transform> GetAffectedUnits(EffectOrigin effectOrigin);public IAreaOfEffect ShallowCopy();
public IAreaOfEffect ShallowCopy() {return (IAreaOfEffect)MemberwiseClone();
[Serializable]public class SingleTarget : IAreaOfEffect{public IEnumerable<Transform> GetAffectedUnits(EffectOrigin effectOrigin) {var origin = effectOrigin.Transform;return new Transform[] { origin };}public IAreaOfEffect ShallowCopy() {return (IAreaOfEffect)MemberwiseClone();}
}
[Serializable]public class CircleArea : IAreaOfEffect{public float Radius;public IEnumerable<Transform> GetAffectedUnits(EffectOrigin effectOrigin) {var origin = effectOrigin.Transform;var hits = Physics.SphereCastAll(origin.position, Radius, origin.forward, 0, LayerMask.NameToLayer("units"));
[Serializable]public class CircleArea : IAreaOfEffect{public float Radius;public IEnumerable<Transform> GetAffectedUnits(Transform origin) {var hits = Physics.SphereCastAll(origin.position, Radius, origin.forward, 0, LayerMask.NameToLayer("units"));
return hits.Select(x => x.transform);}
public IAreaOfEffect ShallowCopy() {return (IAreaOfEffect)MemberwiseClone();}}
[Serializable]public class ConeArea : IAreaOfEffect{public float Radius;
[Range(0f, 360f)]public float Angle;
public IEnumerable<Transform> GetAffectedUnits(EffectOrigin effectOrigin) {var origin = effectOrigin.Transform;// Its problematic to cast a real cone, so we cast the sphere and later// calculate if the potential target is within the cone.var possibleHits = Physics.SphereCastAll(origin.position, Radius, origin.forward, 0, LayerMask.NameToLayer("units"));
// Its problematic to cast a real cone, so we cast the sphere and later// calculate if the potential target is within the cone.var possibleHits = Physics.SphereCastAll(origin.position, Radius, origin.forward, 0, LayerMask.NameToLayer("units"));
foreach (var h in possibleHits) {Debug.Log($"ConeArea:GetAffectedUnits possbile hit: {h.transform.gameObject}");}
if (possibleHits.Length == 0) {return Enumerable.Empty<Transform>();}
var hits = possibleHits.Where(h => {var targetDir = (h.transform.position - origin.position).normalized;var targetAngle = Math.Abs(Vector3.Angle(targetDir, origin.forward));Debug.Log($"ConeArea:GetAffectedUnits target: {h.transform.gameObject} angle: {targetAngle}");
var hits = possibleHits.Where(h => {var targetDir = (h.transform.position - origin.position).normalized;var targetAngle = Math.Abs(Vector3.Angle(targetDir, origin.forward));Debug.Log($"ConeArea:GetAffectedUnits target: {h.transform.gameObject} angle: {targetAngle}");
foreach (var h in hits) {Debug.Log($"ConeArea:GetAffectedUnits hit: {h.transform.gameObject}");}
public IAreaOfEffect ShallowCopy() {return (IAreaOfEffect)MemberwiseClone();}}
[Serializable]public class PathArea : IAreaOfEffect{public float Width;public float Length;public IEnumerable<Transform> GetAffectedUnits(EffectOrigin effectOrigin) {var origin = effectOrigin.Transform;
[Serializable]public class PathArea : IAreaOfEffect{public float Width;public float Length;public IEnumerable<Transform> GetAffectedUnits(Transform origin) {
// Get potential collisionsvar hits = Physics.BoxCastAll(origin.position, new Vector3(Width / 2, 0, 0), origin.forward, origin.rotation, Length, LayerMask.NameToLayer("units"));
// Get potential collisionsvar hits = Physics.BoxCastAll(origin.position, new Vector3(Width / 2, 0, 0), origin.forward, origin.rotation, Length, LayerMask.NameToLayer("units"));
foreach (var h in hits) {Debug.Log($"PathArea:GetAffectedUnits hit: {h.transform.gameObject}");}
--- !u!114 &-6555239679874132939
--- !u!114 &-6063848963083739922MonoBehaviour:m_ObjectHideFlags: 0m_CorrespondingSourceObject: {fileID: 0}m_PrefabInstance: {fileID: 0}m_PrefabAsset: {fileID: 0}m_GameObject: {fileID: 0}m_Enabled: 1m_EditorHideFlags: 0m_Script: {fileID: 11500000, guid: 5379282b606b40d41b3f107d66364266, type: 3}m_Name: SequenceTesterm_EditorClassIdentifier:Position: {x: 242, y: 264}Guid: 602aeaf6-13dd-4653-8b35-2cec2c5c86e4_in:Node: {fileID: -4792174090053785434}_value:- 5- 5_displayName: Pawn BlueTag--- !u!114 &-5807716216484026408
--- !u!114 &1913254018762623428MonoBehaviour:m_ObjectHideFlags: 0m_CorrespondingSourceObject: {fileID: 0}m_PrefabInstance: {fileID: 0}m_PrefabAsset: {fileID: 0}m_GameObject: {fileID: 0}m_Enabled: 1m_EditorHideFlags: 0m_Script: {fileID: 11500000, guid: e3d165e54b32e6d4cbcc75c5b0cf7a68, type: 3}m_Name: ConeAreaGetm_EditorClassIdentifier:Position: {x: 501.1667, y: 510.5}Guid: 086e1033-2340-463f-afb8-420e1aa3eb29_radius:Node: {fileID: -5807716216484026408}_angle:Node: {fileID: -8370226476145813476}
- rid: 6877512918992683008type: {class: EffectSystem, ns: , asm: Assembly-CSharp}
- rid: 1712398209768751105type: {class: EffectSystem, ns: TagFighter, asm: Assembly-CSharp}
--- !u!114 &1683100427 strippedMonoBehaviour:m_CorrespondingSourceObject: {fileID: 1763275424511731206, guid: 689a4763a3cde4b46a7c011ddb15ea97,type: 3}m_PrefabInstance: {fileID: 437407085}m_PrefabAsset: {fileID: 0}m_GameObject: {fileID: 0}m_Enabled: 1m_EditorHideFlags: 0m_Script: {fileID: 11500000, guid: 07f01f81836cb3d488d4164378aa326b, type: 3}m_Name:m_EditorClassIdentifier: