7QKPEDFDFQJFTXM4BFJ4CFHOOZKOI6NKRRSBDLMP7SELPJMFOQRAC
JMMGK6VQWZOLY6C6YWUPAIHLQXUZ2ZZTVJQAL7ODPZAWUSZQIJJAC
AHVLR4STJDGDBXUW23XPHTTP24T6BMWG3FYIY7S26YYVAQYZ4CDAC
VPXUP5WZTVC3OVD73TNKPK43IAGFXGUGCEJT56JM4IT4APYQXUHAC
XF52N4U7HWXOF4PDSCR7LCUENLTSXLWEZGS2IJ6562KYI567Z2GAC
7BZ73FLUK5ANK44V7EMAROTHHVE2IGJ65GTA26DRWY65566HMNPAC
HUULCHM5GFGZ7GKLCULFHC333LQ3LBI62VKII3YL5O4C5CDGCT4AC
VZRSH4U473FCZOP5EXURPXXN5J6F3ZLT435YY7A2JHLG2ZZB5KLQC
IDXWT3DH3C3X7PP4VVKUZTCGDALW6NH7KREI4E2VFQVMCBJKDMTAC
XIPU27GAVXMAKDP42DDSYNA6DSN5WBHH6AG4EK6YIIM43AQQHQAAC
ZZLU6UG75ALN7BYLP4SLGT4SIHDKJPFZPMNSYST25RQT3KLTFHPAC
WKHLLZ3K732M7VJ5KWDSLRWZUARDNDP6ODAXD6SW43CHCT5DX5SAC
QOAVQCDV2MRAPUX62ZLDTUB6AXYSAGEEWIEZIG4TGIQKCLP5T5GAC
DGUHVA7XX4HWCIXCARJCI7T6VTXEJUOPUYZOLDOOOWIZYFEJQYFQC
R5JJA7VQ5HCQ6TZEFMORFMPYBXTMIOBAH6YMDCG4QZKBJZCQLR4AC
S5OSCH7CRN2YEKVTCTJXNLYR2B3PEGCCBUGTN2M6QOCKBNJR62NAC
J75RIWLT42QXABT6GQMAVIOP5XDUF7UAGFQUSSKDIULB3LEB22EQC
62YQ7EMUYX7GS3AB6FAJDKNX53LVG6T2EH6NMVS6JV36J5VCOKIAC
FNS4LRFQNFM4BCB23CYHOWA2N4MG2DEUMNK6D55BQ26TX6OJLIBQC
MHN2B5YZ2Y4G3O7UOZJKFQ3SSP5HTNJCXFKCO3KYY46I2GHM3TIQC
G4XIS2NEM4WHRP2775YBCLFDT7JZZS52CMEHY3PA43QSXL45XNDAC
JCJJQHBBV2KJGV46NWH3RHF5XSFVZUB56DVGR5XTCUOXHWD2KCJAC
JZVIQ3IPEXQ5OWCAKZQW666LXIZLMP5U247YI6Y2EJ7MDNWPGCZQC
2RUZ7TTRT7SMZT2V7YWUCCTJJXNRT2LNJ2QBBVN4RMREMOGMGMHQC
MQD6ISMHW27RCHAGJUINEULYXSY3JQ3UKVQPEM5PYDMM32TUYAYQC
6TAXWREAGU2AW2MHM447UBAE6FNJFTBEGHZCAMVYRI4RKAODDLIQC
RZAMG2H2NY73KZJIV4VXLJHJVSRGJDRWWZJERAI6O7AVDW64JEQQC
3JTZIZGE6WPLZCIWXXLG3SQA2LVSVP26P7U52YBMBTY2VCC6LBLAC
DGC7DHJWSP6BZMDKZ6FG6YS7P2RXZWKFROBYHEX4KZCG7HFBLSUQC
P5O6MKCMZL3DK7ZO5SBWTCHOQB6O2MZA5VPSCQX6X4LJQVOWYV7AC
UZML3EYZI5YSVYMADFBG3HBQUQAAYVLAS4R2BIR7BOVWQKIHE4IAC
FQZF2IY4T2F7KEVSHMFID35WNAU55CRRDF6XEXZB7PYZH26UGYPQC
426KOWJWOX7ZE24UIJCIHRI5KUZYO6NIGK7KC2HOONFDX242UYIQC
AZN3UTBQLTKMGIHW5UCAMLC4GGHG6MAORBQ7OIR2U7NTZ53GWGNQC
OXMN3LHBNH7CWHEZRPSZTN244O3ACTOEKZEAKQNKFXQ7VQSM26YQC
MML56TWYWB6SUY5JEWHG2PNLAH3JY72PGCEXIGOYE54EAC2WSWBAC
4PLSNSVW4VOQW5ZXXZGUWB56WI33SXTGWOCD7PNE36OWDGD7NRJAC
G4ODCLUUQ6V23B2DSMLQTRVLSBVBVO5CFZBXVZ6C3S63N7TECDHAC
4JF2MUNF23IFAVVECZNP3JJLFPEB36V7FDRQOKIZNF6Q2FAGOFRQC
DTKCWM4J7PFNWAAES3RZHQGDA6PTDNX4TZVOXAKF5V7LCZBI3XUAC
2SLVO3SYIJQOEV2YNSD73BSUSWQNZVROQCGHJCPCDSMCCNKZTQFQC
EF6FXKYIVJCURLSC2CLS27FCTECIIIU2EEPI352ZTCIKYKW5VOBQC
VU32ZIRYU6LCQJFGN4ZA3IQ5HNY5J4PNI5OCPW24L7YBOI3BOTYAC
A6K2SVTQ3JQ3TC3F44H3ERSX47TRQ6R5EJGIRJKFGKZG6I4HOATQC
M2C63XUU3TKYAUPPSPEFVF4CMBQMCVLZATANFWQW35MMYNRB2SEAC
VUAVVMQEUYSXHBIUJHGRX237EZFT5MCB73ZKVWMGJDRHYZH4XZKAC
R475KN7MR3OG7EBLVNOO7QRIKXDGY2PIDXXV3HW4KBD5QM7B5OJQC
TKLR43RQKXB47J2YVVSJ7CAZAJZYOKXSDUXAUOVQMFUN73KZVUVQC
R6RQ2RKQV3YFYIRN5JED6NAFB4E34WQJRDHHKZ4JO7KLBXRKNFYAC
HMDPEJRZK3PO6M5Z655Y4HWCUKC5I35GRMVVQOZYXWWCIH5ZWNPQC
GBGS6RTZTCKRMLLDVCBGMRTJNNOSAUTXN5D2EMEQMQAREORE54PAC
L2SE4UCTEU4R7JSHG2J5H6RZPRN4SGBMXK3WCRED2HARX5JEN2AQC
UBKE7KXKA35CBKZLD366TUQXK72GYT7RLPEMMLCR4XC3TLMXD7EQC
R52YYK6WMYXCCIMHE4CKMSAQO7I4AHTJ2UHK4Z3V5UHI5KQWV5IAC
CD5FF75KTOBTMVMTMCKMR6F5DFKOF26I5K43ITNHGBI3ZAZHA4RAC
G6KBRZNCPEBI5YF2ZJYRAFCYDO3CDGFPQBDC3I4JQEYJ4DNT234AC
using System.Collections;
using TagFighter;
using TagFighter.Resources;
using Testing.Line;
using Testing.TimeDialation;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
public class Tester : MonoBehaviour
{
[SerializeField] Vector3 _forceToApply;
[SerializeField] Transform _affected;
[SerializeField] LayerMask _unitMovementLayerMask;
[SerializeField] ForceMode _forceMode;
[SerializeField] EventAggregator _eventAggregator;
[SerializeField] bool _shouldTestTags = false;
[SerializeField] bool _shouldTestPhysics = false;
[SerializeField] bool _shouldTestPawnConditions = false;
Renderer _r;
Rigidbody _rb;
NavMeshAgent _nma;
bool _pushed;
Vector3 _resetPosition;
protected void Start() {
if (_affected) {
_r = _affected.GetComponent<Renderer>();
_rb = _affected.GetComponent<Rigidbody>();
_nma = _affected.GetComponent<NavMeshAgent>();
_resetPosition = _affected.transform.position;
}
Reset();
}
protected void Update() {
if (_shouldTestTags) {
TestTags();
}
if (_shouldTestPhysics) {
TestPhysics();
}
if (_shouldTestPawnConditions) {
TestAddPawnCondition();
}
}
void TestAddPawnCondition() {
if (Input.GetKeyDown(KeyCode.T)) {
var condition = _affected.gameObject.AddComponent<TagFighter.Effects.PawnCondition>();
condition.Apply();
}
}
void TestTags() {
if (Input.GetKeyDown(KeyCode.L)) {
var color = UnityEngine.Random.Range(0, 3);
switch (color) {
case 0: {
var modifier = new StatModifier<BlueTagUnit> {
Amount = (Unit<BlueTagUnit>)1
};
_affected.GetComponent<BlueTag>().AddCurrentModifier(modifier, System.Threading.CancellationToken.None);
break;
}
case 1: {
var modifier = new StatModifier<RedTagUnit> {
Amount = (Unit<RedTagUnit>)1
};
_affected.GetComponent<RedTag>().AddCurrentModifier(modifier, System.Threading.CancellationToken.None);
break;
}
case 2: {
var modifier = new StatModifier<GreenTagUnit> {
Amount = (Unit<GreenTagUnit>)1
};
_affected.GetComponent<GreenTag>().AddCurrentModifier(modifier, System.Threading.CancellationToken.None);
break;
}
}
}
if (Input.GetKeyDown(KeyCode.M)) {
SystemsHandler.EffectSystem.ApplyTagsEffect(new TagCounter() { }, _affected, _affected.transform.rotation, new CircleArea() { Radius = 15 });
}
}
void TestPhysics() {
if (Input.GetKeyDown(KeyCode.T)) {
if (Input.GetKey(KeyCode.LeftShift)) {
Test();
}
else {
_pushed = true;
}
}
if (Input.GetKeyDown(KeyCode.B) && !EventSystem.current.IsPointerOverGameObject()) {
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit)) {
var objectHit = hit.transform;
if (_unitMovementLayerMask.IsLayerInMask(objectHit.gameObject.layer)) {
_nma.Warp(hit.point);
}
}
}
if (Input.GetKeyDown(KeyCode.R)) {
Reset();
}
if (Input.GetKeyDown(KeyCode.P)) {
print($"Velocity ({_rb.velocity}), Magnitude {_rb.velocity.magnitude}");
print($"world bounds {_r.bounds} local bounds {_r.localBounds}");
}
}
protected void FixedUpdate() {
if (_rb != null && !_rb.isKinematic && _nma.isOnNavMesh && _rb.velocity.sqrMagnitude < 0.25f) {
if (Physics.Raycast(_affected.transform.position, Vector3.down, _r.bounds.extents.y + 0.1f, _unitMovementLayerMask)) {
_rb.isKinematic = true;
_nma.updatePosition = true;
_nma.updateRotation = true;
_nma.Warp(_affected.transform.position);
}
//nma.enabled = true;
}
if (_pushed) {
// nma.enabled = false;
_nma.updatePosition = false;
_nma.updateRotation = false;
_rb.isKinematic = false;
_rb.AddForce(_forceToApply, _forceMode);
_pushed = false;
}
}
void Reset() {
if (_rb != null) {
_rb.isKinematic = true;
}
if (_nma) {
_nma.updatePosition = true;
_nma.updateRotation = true;
_nma.enabled = true;
_pushed = false;
}
if (_affected) {
_affected.transform.position = _resetPosition;
}
}
void Test() {
TimeDialationTester timeDialationTester = new(_eventAggregator);
timeDialationTester.TestAll();
LineTester lineTester = new();
lineTester.TestAll();
}
}
namespace Testing.TimeDialation
{
public class TimeDialationTester
{
EventAggregator _eventAggregator;
public TimeDialationTester(EventAggregator eventAggregator) {
_eventAggregator = eventAggregator;
}
public void TestAll() {
TestTimeDialationSpeedUp();
TestTimeDialationSpeedDown();
TestTimeDialationSpeedPause();
TestTimeDialationSpeedReset();
}
public void TestTimeDialationSpeedUp() {
var currentTimeScale = Time.timeScale;
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
_eventAggregator.OnTimeDilationSpeedUp(this, System.EventArgs.Empty);
if (Time.timeScale > currentTimeScale) {
Debug.Log($"<color=green>PASSED: {testName}</color>");
}
else {
Debug.Log($"<color=red>FAILED: {testName}</color>");
}
}
public void TestTimeDialationSpeedDown() {
var currentTimeScale = Time.timeScale;
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
_eventAggregator.OnTimeDilationSpeedDown(this, System.EventArgs.Empty);
if (Time.timeScale < currentTimeScale) {
Debug.Log($"<color=green>PASSED: {testName}</color>");
}
else {
Debug.Log($"<color=red>FAILED: {testName}</color>");
}
}
public void TestTimeDialationSpeedPause() {
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
_eventAggregator.OnTimeDilationSpeedPause(this, System.EventArgs.Empty);
if (Time.timeScale == 0) {
Debug.Log($"<color=green>PASSED: {testName}</color>");
}
else {
Debug.Log($"<color=red>FAILED: {testName}</color>");
}
}
public void TestTimeDialationSpeedReset() {
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
Time.timeScale = 4;
_eventAggregator.OnTimeDilationSpeedReset(this, System.EventArgs.Empty);
if (Time.timeScale == 1) {
Debug.Log($"<color=green>PASSED: {testName}</color>");
}
else {
Debug.Log($"<color=red>FAILED: {testName}</color>");
}
}
}
}
namespace Testing.Line
{
public class LineTester
{
public void TestAll() {
TestWaitInLine();
TestCutInLine();
TestTryRemoveAt();
TestCircularInsert();
}
public void TestWaitInLine() {
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
var anyFail = false;
int insert;
int[] insertArr = { 5, 4, 3, 2, 1 };
Line<int> l = new(insertArr.Length);
foreach (var item in insertArr) {
if (l.TryWaitInLine(item) == false) {
Debug.Log($"<color=red>FAILED: {testName} {item} </color>");
anyFail = true;
}
}
insert = 0;
if (l.TryWaitInLine(insert) == true) {
Debug.Log($"<color=red>FAILED: {testName} {insert} </color>");
anyFail = true;
}
if (!l.TryGetFirstOutOfLine(out var n) || (n != insertArr[0])) {
Debug.Log($"<color=red>FAILED: {testName} TryGetFirstOutOfLine {insertArr[0]} </color>");
anyFail = true;
}
int[] resultArr = { 4, 3, 2, 1 };
var count = 1;
foreach (var item in l) {
if (item != insertArr[count]) {
Debug.Log($"<color=red>FAILED: {testName} foreach {item} != {insertArr[count]} </color>");
anyFail = true;
}
count++;
}
if (count != insertArr.Length) {
Debug.Log($"<color=red>FAILED: {testName} incorrect number of items in Line {count != resultArr.Length}</color>");
anyFail = true;
}
if (anyFail == false) {
Debug.Log($"<color=green>PASSED: {testName} </color>");
}
}
public void TestCutInLine() {
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
var anyFail = false;
int[] insertArr = { 1, 2, 3, 4, 5 };
Line<int> l = new(insertArr.Length);
foreach (var item in insertArr) {
if (l.TryWaitInLine(item) == false) {
Debug.Log($"<color=red>FAILED: {testName} {item} </color>");
anyFail = true;
}
}
var insert = 6;
l.CutInLine(insert);
if (l.TryWaitInLine(insert) == true) {
}
if (!l.TryGetFirstOutOfLine(out var n) || (n != insert)) {
Debug.Log($"<color=red>FAILED: {testName} get out {insert} </color>");
anyFail = true;
}
int[] resultArr = { 1, 2, 3, 4 };
var count = 0;
foreach (var item in l) {
if (item != resultArr[count]) {
Debug.Log($"<color=red>FAILED: {testName} foreach {item} != {resultArr[count]} </color>");
anyFail = true;
}
count++;
}
if (count != resultArr.Length) {
Debug.Log($"<color=red>FAILED: {testName} incorrect number of items in Line {count != resultArr.Length}</color>");
anyFail = true;
}
if (anyFail == false) {
Debug.Log($"<color=green>PASSED: {testName} </color>");
}
}
public void TestTryRemoveAt() {
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
var anyFail = false;
int[] insertArr = { 1, 2, 3, 4, 5 };
Line<int> l = new(insertArr.Length);
foreach (var item in insertArr) {
if (l.TryWaitInLine(item) == false) {
Debug.Log($"<color=red>FAILED: TryWaitInLine foreach {testName} {item} </color>");
anyFail = true;
}
}
var position = 2;
if (!l.TryRemoveAt(position, out var n) || n != insertArr[position]) {
Debug.Log($"<color=red>FAILED: TryRemoveAt {testName} {insertArr[position]} </color>");
anyFail = true;
}
if (l.TryWaitInLine(insertArr[position]) == false) {
Debug.Log($"<color=red>FAILED: TryWaitInLine {testName} {insertArr[position]} </color>");
anyFail = true;
}
l.CutInLine(insertArr[position]);
int[] resultArr = { 3, 1, 2, 4, 5 };
position = 4;
if (!l.TryRemoveAt(position, out n) || n != resultArr[position]) {
Debug.Log($"<color=red>FAILED: TryRemoveAt {testName} {n} != {resultArr[position]} </color>");
anyFail = true;
}
if (l.TryWaitInLine(insertArr[position]) == false) {
Debug.Log($"<color=red>FAILED: TryWaitInLine {testName} {insertArr[position]} </color>");
anyFail = true;
}
resultArr = new int[] { 3, 1, 2, 4, insertArr[position] };
if (!l.TryRemoveAt(position, out n) || n != resultArr[position]) {
Debug.Log($"<color=red>FAILED: TryRemoveAt {testName} {n} != {resultArr[position]} </color>");
anyFail = true;
}
resultArr = new int[] { 3, 1, 2, 4 };
var count = 0;
foreach (var item in l) {
if (item != resultArr[count]) {
Debug.Log($"<color=red>FAILED: {testName} foreach {item} != {resultArr[count]} </color>");
anyFail = true;
}
count++;
}
if (count != resultArr.Length) {
Debug.Log($"<color=red>FAILED: {testName} incorrect number of items in Line {count != resultArr.Length}</color>");
anyFail = true;
}
if (anyFail == false) {
Debug.Log($"<color=green>PASSED: {testName} </color>");
}
}
public void TestCircularInsert() {
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
var anyFail = false;
int[] insertArr = { 1, 2, 3, 4, 5 };
Line<int> l = new(insertArr);
l.TryGetFirstOutOfLine(out var _);
l.TryGetFirstOutOfLine(out var _);
l.TryWaitInLine(6);
l.TryWaitInLine(7);
int[] resultArr = { 3, 4, 5, 6, 7 };
var count = 0;
foreach (var item in l) {
if (item != resultArr[count]) {
Debug.Log($"<color=red>FAILED: {testName} foreach {item} != {resultArr[count]} </color>");
anyFail = true;
}
count++;
}
if (count != resultArr.Length) {
Debug.Log($"<color=red>FAILED: {testName} incorrect number of items in Line {count != resultArr.Length} </color>");
anyFail = true;
}
if (anyFail == false) {
Debug.Log($"<color=green>PASSED: {testName} </color>");
}
}
}
}
using System.Collections;
using TagFighter;
using TagFighter.Resources;
using Testing.Line;
using Testing.TimeDialation;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
public class Tester : MonoBehaviour
{
[SerializeField] Vector3 _forceToApply;
[SerializeField] Transform _affected;
[SerializeField] LayerMask _unitMovementLayerMask;
[SerializeField] ForceMode _forceMode;
[SerializeField] EventAggregator _eventAggregator;
[SerializeField] bool _shouldTestTags = false;
[SerializeField] bool _shouldTestPhysics = false;
[SerializeField] bool _shouldTestPawnConditions = false;
Renderer _r;
Rigidbody _rb;
NavMeshAgent _nma;
bool _pushed;
Vector3 _resetPosition;
protected void Start() {
if (_affected) {
_r = _affected.GetComponent<Renderer>();
_rb = _affected.GetComponent<Rigidbody>();
_nma = _affected.GetComponent<NavMeshAgent>();
_resetPosition = _affected.transform.position;
}
Reset();
}
protected void Update() {
if (_shouldTestTags) {
TestTags();
}
if (_shouldTestPhysics) {
TestPhysics();
}
if (_shouldTestPawnConditions) {
TestAddPawnCondition();
}
}
void TestAddPawnCondition() {
if (Input.GetKeyDown(KeyCode.T)) {
var condition = _affected.gameObject.AddComponent<TagFighter.Effects.PawnCondition>();
condition.Apply();
}
}
void TestTags() {
if (Input.GetKeyDown(KeyCode.L)) {
var color = UnityEngine.Random.Range(0, 3);
switch (color) {
case 0: {
var modifier = new StatModifier<BlueTagUnit> {
Amount = (Unit<BlueTagUnit>)1
};
_affected.GetComponent<BlueTag>().AddCurrentModifier(modifier, System.Threading.CancellationToken.None);
break;
}
case 1: {
var modifier = new StatModifier<RedTagUnit> {
Amount = (Unit<RedTagUnit>)1
};
_affected.GetComponent<RedTag>().AddCurrentModifier(modifier, System.Threading.CancellationToken.None);
break;
}
case 2: {
var modifier = new StatModifier<GreenTagUnit> {
Amount = (Unit<GreenTagUnit>)1
};
_affected.GetComponent<GreenTag>().AddCurrentModifier(modifier, System.Threading.CancellationToken.None);
break;
}
}
}
}
void TestPhysics() {
if (Input.GetKeyDown(KeyCode.T)) {
if (Input.GetKey(KeyCode.LeftShift)) {
Test();
}
else {
_pushed = true;
}
}
if (Input.GetKeyDown(KeyCode.B) && !EventSystem.current.IsPointerOverGameObject()) {
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit)) {
var objectHit = hit.transform;
if (_unitMovementLayerMask.IsLayerInMask(objectHit.gameObject.layer)) {
_nma.Warp(hit.point);
}
}
}
if (Input.GetKeyDown(KeyCode.R)) {
Reset();
}
if (Input.GetKeyDown(KeyCode.P)) {
print($"Velocity ({_rb.velocity}), Magnitude {_rb.velocity.magnitude}");
print($"world bounds {_r.bounds} local bounds {_r.localBounds}");
}
}
protected void FixedUpdate() {
if (_rb != null && !_rb.isKinematic && _nma.isOnNavMesh && _rb.velocity.sqrMagnitude < 0.25f) {
if (Physics.Raycast(_affected.transform.position, Vector3.down, _r.bounds.extents.y + 0.1f, _unitMovementLayerMask)) {
_rb.isKinematic = true;
_nma.updatePosition = true;
_nma.updateRotation = true;
_nma.Warp(_affected.transform.position);
}
//nma.enabled = true;
}
if (_pushed) {
// nma.enabled = false;
_nma.updatePosition = false;
_nma.updateRotation = false;
_rb.isKinematic = false;
_rb.AddForce(_forceToApply, _forceMode);
_pushed = false;
}
}
void Reset() {
if (_rb != null) {
_rb.isKinematic = true;
}
if (_nma) {
_nma.updatePosition = true;
_nma.updateRotation = true;
_nma.enabled = true;
_pushed = false;
}
if (_affected) {
_affected.transform.position = _resetPosition;
}
}
void Test() {
TimeDialationTester timeDialationTester = new(_eventAggregator);
timeDialationTester.TestAll();
LineTester lineTester = new();
lineTester.TestAll();
}
}
namespace Testing.TimeDialation
{
public class TimeDialationTester
{
EventAggregator _eventAggregator;
public TimeDialationTester(EventAggregator eventAggregator) {
_eventAggregator = eventAggregator;
}
public void TestAll() {
TestTimeDialationSpeedUp();
TestTimeDialationSpeedDown();
TestTimeDialationSpeedPause();
TestTimeDialationSpeedReset();
}
public void TestTimeDialationSpeedUp() {
var currentTimeScale = Time.timeScale;
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
_eventAggregator.OnTimeDilationSpeedUp(this, System.EventArgs.Empty);
if (Time.timeScale > currentTimeScale) {
Debug.Log($"<color=green>PASSED: {testName}</color>");
}
else {
Debug.Log($"<color=red>FAILED: {testName}</color>");
}
}
public void TestTimeDialationSpeedDown() {
var currentTimeScale = Time.timeScale;
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
_eventAggregator.OnTimeDilationSpeedDown(this, System.EventArgs.Empty);
if (Time.timeScale < currentTimeScale) {
Debug.Log($"<color=green>PASSED: {testName}</color>");
}
else {
Debug.Log($"<color=red>FAILED: {testName}</color>");
}
}
public void TestTimeDialationSpeedPause() {
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
_eventAggregator.OnTimeDilationSpeedPause(this, System.EventArgs.Empty);
if (Time.timeScale == 0) {
Debug.Log($"<color=green>PASSED: {testName}</color>");
}
else {
Debug.Log($"<color=red>FAILED: {testName}</color>");
}
}
public void TestTimeDialationSpeedReset() {
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
Time.timeScale = 4;
_eventAggregator.OnTimeDilationSpeedReset(this, System.EventArgs.Empty);
if (Time.timeScale == 1) {
Debug.Log($"<color=green>PASSED: {testName}</color>");
}
else {
Debug.Log($"<color=red>FAILED: {testName}</color>");
}
}
}
}
namespace Testing.Line
{
public class LineTester
{
public void TestAll() {
TestWaitInLine();
TestCutInLine();
TestTryRemoveAt();
TestCircularInsert();
}
public void TestWaitInLine() {
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
var anyFail = false;
int insert;
int[] insertArr = { 5, 4, 3, 2, 1 };
Line<int> l = new(insertArr.Length);
foreach (var item in insertArr) {
if (l.TryWaitInLine(item) == false) {
Debug.Log($"<color=red>FAILED: {testName} {item} </color>");
anyFail = true;
}
}
insert = 0;
if (l.TryWaitInLine(insert) == true) {
Debug.Log($"<color=red>FAILED: {testName} {insert} </color>");
anyFail = true;
}
if (!l.TryGetFirstOutOfLine(out var n) || (n != insertArr[0])) {
Debug.Log($"<color=red>FAILED: {testName} TryGetFirstOutOfLine {insertArr[0]} </color>");
anyFail = true;
}
int[] resultArr = { 4, 3, 2, 1 };
var count = 1;
foreach (var item in l) {
if (item != insertArr[count]) {
Debug.Log($"<color=red>FAILED: {testName} foreach {item} != {insertArr[count]} </color>");
anyFail = true;
}
count++;
}
if (count != insertArr.Length) {
Debug.Log($"<color=red>FAILED: {testName} incorrect number of items in Line {count != resultArr.Length}</color>");
anyFail = true;
}
if (anyFail == false) {
Debug.Log($"<color=green>PASSED: {testName} </color>");
}
}
public void TestCutInLine() {
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
var anyFail = false;
int[] insertArr = { 1, 2, 3, 4, 5 };
Line<int> l = new(insertArr.Length);
foreach (var item in insertArr) {
if (l.TryWaitInLine(item) == false) {
Debug.Log($"<color=red>FAILED: {testName} {item} </color>");
anyFail = true;
}
}
var insert = 6;
l.CutInLine(insert);
if (l.TryWaitInLine(insert) == true) {
}
if (!l.TryGetFirstOutOfLine(out var n) || (n != insert)) {
Debug.Log($"<color=red>FAILED: {testName} get out {insert} </color>");
anyFail = true;
}
int[] resultArr = { 1, 2, 3, 4 };
var count = 0;
foreach (var item in l) {
if (item != resultArr[count]) {
Debug.Log($"<color=red>FAILED: {testName} foreach {item} != {resultArr[count]} </color>");
anyFail = true;
}
count++;
}
if (count != resultArr.Length) {
Debug.Log($"<color=red>FAILED: {testName} incorrect number of items in Line {count != resultArr.Length}</color>");
anyFail = true;
}
if (anyFail == false) {
Debug.Log($"<color=green>PASSED: {testName} </color>");
}
}
public void TestTryRemoveAt() {
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
var anyFail = false;
int[] insertArr = { 1, 2, 3, 4, 5 };
Line<int> l = new(insertArr.Length);
foreach (var item in insertArr) {
if (l.TryWaitInLine(item) == false) {
Debug.Log($"<color=red>FAILED: TryWaitInLine foreach {testName} {item} </color>");
anyFail = true;
}
}
var position = 2;
if (!l.TryRemoveAt(position, out var n) || n != insertArr[position]) {
Debug.Log($"<color=red>FAILED: TryRemoveAt {testName} {insertArr[position]} </color>");
anyFail = true;
}
if (l.TryWaitInLine(insertArr[position]) == false) {
Debug.Log($"<color=red>FAILED: TryWaitInLine {testName} {insertArr[position]} </color>");
anyFail = true;
}
l.CutInLine(insertArr[position]);
int[] resultArr = { 3, 1, 2, 4, 5 };
position = 4;
if (!l.TryRemoveAt(position, out n) || n != resultArr[position]) {
Debug.Log($"<color=red>FAILED: TryRemoveAt {testName} {n} != {resultArr[position]} </color>");
anyFail = true;
}
if (l.TryWaitInLine(insertArr[position]) == false) {
Debug.Log($"<color=red>FAILED: TryWaitInLine {testName} {insertArr[position]} </color>");
anyFail = true;
}
resultArr = new int[] { 3, 1, 2, 4, insertArr[position] };
if (!l.TryRemoveAt(position, out n) || n != resultArr[position]) {
Debug.Log($"<color=red>FAILED: TryRemoveAt {testName} {n} != {resultArr[position]} </color>");
anyFail = true;
}
resultArr = new int[] { 3, 1, 2, 4 };
var count = 0;
foreach (var item in l) {
if (item != resultArr[count]) {
Debug.Log($"<color=red>FAILED: {testName} foreach {item} != {resultArr[count]} </color>");
anyFail = true;
}
count++;
}
if (count != resultArr.Length) {
Debug.Log($"<color=red>FAILED: {testName} incorrect number of items in Line {count != resultArr.Length}</color>");
anyFail = true;
}
if (anyFail == false) {
Debug.Log($"<color=green>PASSED: {testName} </color>");
}
}
public void TestCircularInsert() {
var testName = System.Reflection.MethodBase.GetCurrentMethod().Name;
var anyFail = false;
int[] insertArr = { 1, 2, 3, 4, 5 };
Line<int> l = new(insertArr);
l.TryGetFirstOutOfLine(out var _);
l.TryGetFirstOutOfLine(out var _);
l.TryWaitInLine(6);
l.TryWaitInLine(7);
int[] resultArr = { 3, 4, 5, 6, 7 };
var count = 0;
foreach (var item in l) {
if (item != resultArr[count]) {
Debug.Log($"<color=red>FAILED: {testName} foreach {item} != {resultArr[count]} </color>");
anyFail = true;
}
count++;
}
if (count != resultArr.Length) {
Debug.Log($"<color=red>FAILED: {testName} incorrect number of items in Line {count != resultArr.Length} </color>");
anyFail = true;
}
if (anyFail == false) {
Debug.Log($"<color=green>PASSED: {testName} </color>");
}
}
}
}
using UnityEngine;
public interface IEffectSystem
{
void ApplyTagsEffect(TagCounter tags, Transform origin, Quaternion direction, IAreaOfEffect areaOfEffect);
Color GetEffectColor(TagCounter 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;
public interface IEffectSystem
{
void ApplyTagsEffect(IEnumerable<(Type, IUnit)> tags, Transform origin, Quaternion direction, 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;
using System.Collections;
using UnityEngine;
[Serializable]
public class EffectSystem : IEffectSystem
{
ParticleSystem _rippleOutVfx;
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(TagCounter 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(TagCounter 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(TagCounter 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(TagCounter 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(TagCounter tags) {
var total = tags[TagColor.Red] + tags[TagColor.Green] + tags[TagColor.Blue];
var red = tags[TagColor.Red] / total;
var green = tags[TagColor.Green] / total;
var blue = tags[TagColor.Blue] / total;
Color color = new(red, green, blue);
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 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()}");
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 UnityEngine;
class DummyEffectSystem : IEffectSystem
{
public void ApplyTagsEffect(TagCounter tags, Transform origin, Quaternion direction, IAreaOfEffect areaOfEffect) {
Debug.Log("Dummy:ApplyTagsEffect");
}
public Color GetEffectColor(TagCounter 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;
}
}
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 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;
}
}
using System;
using UnityEngine;
namespace TagFighter.Resources
{
public interface IUnit { }
[Serializable]
public struct Unit<TUnitType> : IUnit, IEquatable<Unit<TUnitType>>, IComparable<Unit<TUnitType>> where TUnitType : IUnitType
{
[SerializeField] int _value;
Unit(int value) => _value = value;
public int AsPrimitive() => _value;
public static explicit operator Unit<TUnitType>(int value) => new(value);
public static explicit operator int(Unit<TUnitType> resource) => resource._value;
public static bool operator ==(Unit<TUnitType> a, Unit<TUnitType> b) => a._value == b._value;
public int CompareTo(Unit<TUnitType> other) => _value.CompareTo(other._value);
public static bool operator >(Unit<TUnitType> a, Unit<TUnitType> b) => a._value > b._value;
public static bool operator <(Unit<TUnitType> a, Unit<TUnitType> b) => a._value < b._value;
public static bool operator !=(Unit<TUnitType> a, Unit<TUnitType> b) => !(a == b);
public static bool operator >=(Unit<TUnitType> a, Unit<TUnitType> b) => !(a < b);
public static bool operator <=(Unit<TUnitType> a, Unit<TUnitType> b) => !(a > b);
public static Unit<TUnitType> operator ++(in Unit<TUnitType> a) => (Unit<TUnitType>)(a._value + 1);
public static Unit<TUnitType> operator --(in Unit<TUnitType> a) => (Unit<TUnitType>)(a._value - 1);
public static Unit<TUnitType> operator +(Unit<TUnitType> a, Unit<TUnitType> b) => (Unit<TUnitType>)(a._value + b._value);
public static Unit<TUnitType> operator -(Unit<TUnitType> a, Unit<TUnitType> b) => (Unit<TUnitType>)(a._value - b._value);
public static float operator /(Unit<TUnitType> a, Unit<TUnitType> b) => a._value / (float)b._value;
public static Unit<TUnitType> operator /(Unit<TUnitType> a, int b) => a / (float)b;
public static Unit<TUnitType> operator /(Unit<TUnitType> a, float b) => a / (float)b;
public static Unit<TUnitType> operator *(Unit<TUnitType> a, float b) => (Unit<TUnitType>)(int)(a._value * b);
public override bool Equals(object obj) => obj is Unit<TUnitType> other && _value.Equals(other._value);
public bool Equals(Unit<TUnitType> other) => _value.Equals(other._value);
public override int GetHashCode() => HashCode.Combine(_value);
public override string ToString() => _value.ToString();
public static Unit<TUnitType> Min(Unit<TUnitType> a, Unit<TUnitType> b) => (Unit<TUnitType>)Math.Min(a._value, b._value);
public static Unit<TUnitType> Max(Unit<TUnitType> a, Unit<TUnitType> b) => (Unit<TUnitType>)Math.Max(a._value, b._value);
public static Unit<TUnitType> Clamp(Unit<TUnitType> value, Unit<TUnitType> min, Unit<TUnitType> max) => (Unit<TUnitType>)Math.Clamp(value._value, min._value, max._value);
}
public interface IUnitType { }
public sealed class PainUnit : IUnitType { }
public sealed class FatigueUnit : IUnitType { }
// public class StrainUnit : IUnit { }
public sealed class RedTagUnit : IUnitType { }
public sealed class BlueTagUnit : IUnitType { }
public sealed class GreenTagUnit : IUnitType { }
public sealed class Centimeter : IUnitType { }
public sealed class RecklessFormKP : IUnitType { }
public sealed class SwordKP : IUnitType { }
public sealed class ShieldKP : IUnitType { }
}
using System;
using UnityEngine;
namespace TagFighter.Resources
{
public interface IUnit { public int AsPrimitive(); }
[Serializable]
public struct Unit<TUnitType> : IUnit, IEquatable<Unit<TUnitType>>, IComparable<Unit<TUnitType>> where TUnitType : IUnitType
{
[SerializeField] int _value;
Unit(int value) => _value = value;
public int AsPrimitive() => _value;
public static explicit operator Unit<TUnitType>(int value) => new(value);
public static explicit operator int(Unit<TUnitType> resource) => resource._value;
public static bool operator ==(Unit<TUnitType> a, Unit<TUnitType> b) => a._value == b._value;
public int CompareTo(Unit<TUnitType> other) => _value.CompareTo(other._value);
public static bool operator >(Unit<TUnitType> a, Unit<TUnitType> b) => a._value > b._value;
public static bool operator <(Unit<TUnitType> a, Unit<TUnitType> b) => a._value < b._value;
public static bool operator !=(Unit<TUnitType> a, Unit<TUnitType> b) => !(a == b);
public static bool operator >=(Unit<TUnitType> a, Unit<TUnitType> b) => !(a < b);
public static bool operator <=(Unit<TUnitType> a, Unit<TUnitType> b) => !(a > b);
public static Unit<TUnitType> operator ++(in Unit<TUnitType> a) => (Unit<TUnitType>)(a._value + 1);
public static Unit<TUnitType> operator --(in Unit<TUnitType> a) => (Unit<TUnitType>)(a._value - 1);
public static Unit<TUnitType> operator +(Unit<TUnitType> a, Unit<TUnitType> b) => (Unit<TUnitType>)(a._value + b._value);
public static Unit<TUnitType> operator -(Unit<TUnitType> a, Unit<TUnitType> b) => (Unit<TUnitType>)(a._value - b._value);
public static float operator /(Unit<TUnitType> a, Unit<TUnitType> b) => a._value / (float)b._value;
public static Unit<TUnitType> operator /(Unit<TUnitType> a, int b) => a / (float)b;
public static Unit<TUnitType> operator /(Unit<TUnitType> a, float b) => a / (float)b;
public static Unit<TUnitType> operator *(Unit<TUnitType> a, float b) => (Unit<TUnitType>)(int)(a._value * b);
public override bool Equals(object obj) => obj is Unit<TUnitType> other && _value.Equals(other._value);
public bool Equals(Unit<TUnitType> other) => _value.Equals(other._value);
public override int GetHashCode() => HashCode.Combine(_value);
public override string ToString() => _value.ToString();
public static Unit<TUnitType> Min(Unit<TUnitType> a, Unit<TUnitType> b) => (Unit<TUnitType>)Math.Min(a._value, b._value);
public static Unit<TUnitType> Max(Unit<TUnitType> a, Unit<TUnitType> b) => (Unit<TUnitType>)Math.Max(a._value, b._value);
public static Unit<TUnitType> Clamp(Unit<TUnitType> value, Unit<TUnitType> min, Unit<TUnitType> max) => (Unit<TUnitType>)Math.Clamp(value._value, min._value, max._value);
}
public interface IUnitType { }
public sealed class PainUnit : IUnitType { }
public sealed class FatigueUnit : IUnitType { }
// public class StrainUnit : IUnit { }
public sealed class RedTagUnit : IUnitType { }
public sealed class BlueTagUnit : IUnitType { }
public sealed class GreenTagUnit : IUnitType { }
public sealed class Centimeter : IUnitType { }
public sealed class RecklessFormKP : IUnitType { }
public sealed class SwordKP : IUnitType { }
public sealed class ShieldKP : IUnitType { }
}
using System;
namespace TagFighter.Resources
{
[Serializable]
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;
namespace TagFighter.Resources
{
[Serializable]
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;
namespace TagFighter.Resources
{
[Serializable]
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;
namespace TagFighter.Resources
{
[Serializable]
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;
namespace TagFighter.Resources
{
[Serializable]
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;
namespace TagFighter.Resources
{
[Serializable]
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;
namespace TagFighter.Resources
{
[Serializable]
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;
namespace TagFighter.Resources
{
[Serializable]
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;
namespace TagFighter.Resources
{
[Serializable]
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;
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 Move
timeContext.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 section
positionalReleaseMultiplier = 1f;
}
else if (posInAnimation < currentMove.StartReleaseNormalized) {
// otherwise, get a partial bonus in reletaion to how close we are to the relese
positionalReleaseMultiplier = posInAnimation / currentMove.StartReleaseNormalized;
}
else if (currentMove.EndReleaseNormalized < posInAnimation) {
// otherwise, get a partial bonus in reletaion to how far we are from the release
positionalReleaseMultiplier = (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 Move
timeContext.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 section
positionalReleaseMultiplier = 1f;
}
else if (posInAnimation < currentMove.StartReleaseNormalized) {
// otherwise, get a partial bonus in reletaion to how close we are to the relese
positionalReleaseMultiplier = posInAnimation / currentMove.StartReleaseNormalized;
}
else if (currentMove.EndReleaseNormalized < posInAnimation) {
// otherwise, get a partial bonus in reletaion to how far we are from the release
positionalReleaseMultiplier = (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 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, TRegisterType>();
}
public void Set<TResource, TUnit>(EffectContext context, Unit<TUnit> value)
where TResource : Resource<TUnit>
where TUnit : IUnitType {
context.SetResource<TResource, TUnit, 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;
}
[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 System.Linq;
using CareBoo.Serially;
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);
TagCounter c = new();
c[TagColor.Red] = 1;
// direction towards target
var directionVector = (data.Context.EffectLocation.position - data.Context.Caster.position).normalized;
directionVector.y = 0;
var direction = Quaternion.LookRotation(directionVector, Vector3.up);
data.Context.EffectSystem.ApplyTagsEffect(c, 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);
TagCounter c = new();
c[TagColor.Red] = 1;
context.EffectSystem.ApplyTagsEffect(c, 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);
}
[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 TagFighter.Effects.ResourceLocationAccessors.ContextRegisters;
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 class EffectContext
{
Dictionary<System.Type, IUnit> _resourceRegistry = new();
public Transform Caster { get; set; }
public Transform EffectLocation { get; set; }
public IAreaOfEffect AreaOfEffect;
public List<IDelayedEffect> EffectsToTrigger { get; set; } = new();
public IEffectSystem EffectSystem { get; private set; }
public ReleaseMultiplier ReleaseMultiplier { get; set; }
public EffectContext() {
EffectSystem = SystemsHandler.EffectSystem;
ReleaseMultiplier = new();
}
public Unit<TUnit> GetResource<TResource, TUnit, TRegister>()
where TResource : Resource<TUnit>
where TUnit : IUnitType
where TRegister : IRegisterType {
var key = typeof((TResource, TRegister));
var value = (Unit<TUnit>)_resourceRegistry.GetValueOrDefault(key, (Unit<TUnit>)0);
Debug.Log($"{nameof(GetResource)} ({typeof(TResource).Name},{typeof(TRegister).Name}) = {value}");
return value;
}
public Unit<TUnit> SetResource<TResource, TUnit, TRegister>(Unit<TUnit> value)
where TResource : Resource<TUnit>
where TUnit : IUnitType
where TRegister : IRegisterType {
var key = typeof((TResource, TRegister));
var newValue = (Unit<TUnit>)(_resourceRegistry[key] = value);
Debug.Log($"{nameof(SetResource)} ({typeof(TResource).Name},{typeof(TRegister).Name}) = {newValue}");
return newValue;
}
public IEnumerable<Transform> GetAffectedUnits() {
if (AreaOfEffect == null) {
return Enumerable.Empty<Transform>();
}
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();
}
public void Reset() {
ResetEffects();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Cecil;
using TagFighter.Effects.ResourceLocationAccessors.ContextRegisters;
using TagFighter.Resources;
using Unity.VisualScripting.FullSerializer.Internal;
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 class 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 IEffectSystem EffectSystem { get; private set; }
public ReleaseMultiplier ReleaseMultiplier { get; set; }
public EffectContext() {
EffectSystem = SystemsHandler.EffectSystem;
ReleaseMultiplier = new();
}
public Unit<TUnit> GetResource<TResource, TUnit, TContextRegister>()
where TResource : Resource<TUnit>
where TUnit : IUnitType
where 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 : IUnitType
where 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 {
Type t = typeof(TContextRegister).BaseType;
return _resourceRegistry.Where(x => x.Key.ContextRegisterType == t).Select(x => (x.Key.ResourceType, x.Value));
}
public IEnumerable<Transform> GetAffectedUnits() {
if (AreaOfEffect == null) {
return Enumerable.Empty<Transform>();
}
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();
}
public void Reset() {
ResetEffects();
}
}
}
Addend: 1
- rid: 1353921146486259729
type: {class: Pawn, ns: TagFighter.Effects.ResourceLocationAccessors.Set, asm: Assembly-CSharp}
Addend: 10
- rid: 2536212716021350404
type: {class: Context, ns: TagFighter.Effects.ResourceLocationAccessors.Set,
asm: Assembly-CSharp}
Property:
rid: 1452634394371555352
- rid: 1353921146486259730
Register:
rid: 2536212716021350405
SetAs:
rid: 2536212716021350406
- rid: 2536212716021350405
type: {class: Added, ns: TagFighter.Effects.ResourceLocationAccessors.ContextRegisters,
asm: Assembly-CSharp}
- rid: 2536212716021350406
type: {class: Sum, ns: TagFighter.Effects.Operators, asm: Assembly-CSharp}
- rid: 2536212716021350407
- rid: 1452634394371555352
type: {class: Current, ns: TagFighter.Effects.ResourceLocationAccessors.PawnProperties,
- rid: 2536212716021350408
type: {class: Context, ns: TagFighter.Effects.ResourceLocationAccessors.Get,
asm: Assembly-CSharp}
data:
Register:
rid: 2536212716021350409
- rid: 2536212716021350409
type: {class: Current, ns: TagFighter.Effects.ResourceLocationAccessors.ContextRegisters,
- rid: 2536212716021350418
type: {class: BlueTag, ns: TagFighter.Effects.ResourceTypeAccessors, asm: Assembly-CSharp}