diff --git a/.gitignore b/.gitignore index 77526939..5424b547 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,6 @@ crashlytics-build.properties # Temporary auto-generated Android Assets /[Aa]ssets/[Ss]treamingAssets/aa.meta /[Aa]ssets/[Ss]treamingAssets/aa/* +.idea/.idea.AGD_CommandPattern/.idea +*.meta +*.zip diff --git a/Assets/Resources/Battle/Battle 3.asset b/Assets/Resources/Battle/Battle 3.asset index a709822d..425c82c0 100644 --- a/Assets/Resources/Battle/Battle 3.asset +++ b/Assets/Resources/Battle/Battle 3.asset @@ -13,6 +13,6 @@ MonoBehaviour: m_Name: Battle 3 m_EditorClassIdentifier: BattleID: 3 - BattleBackgroundImage: {fileID: 1144033053, guid: 53ddd195ebcffd74cba8e68bd465b5b3, type: 3} + BattleBackgroundImage: {fileID: 1039436393, guid: 53ddd195ebcffd74cba8e68bd465b5b3, type: 3} Player1Data: {fileID: 11400000, guid: 54c708d0404a70248a7953a3b2b83d35, type: 2} Player2Data: {fileID: 11400000, guid: 373f3a8c5b7afe145ba9ec6ed8c88612, type: 2} diff --git a/Assets/Resources/Battle/Battle 4.asset b/Assets/Resources/Battle/Battle 4.asset new file mode 100644 index 00000000..b3da161e --- /dev/null +++ b/Assets/Resources/Battle/Battle 4.asset @@ -0,0 +1,18 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 15700b09dee7b504c8b8f273851c4fcf, type: 3} + m_Name: Battle 4 + m_EditorClassIdentifier: + BattleID: 4 + BattleBackgroundImage: {fileID: -717732176, guid: 53ddd195ebcffd74cba8e68bd465b5b3, type: 3} + Player1Data: {fileID: 11400000, guid: 996fcce034046194db9c6bd9601b7408, type: 2} + Player2Data: {fileID: 11400000, guid: d0205d5e036b8bc4fa73d5c5df43022b, type: 2} diff --git a/Assets/Resources/Player/Battle 4/Player 4-1.asset b/Assets/Resources/Player/Battle 4/Player 4-1.asset new file mode 100644 index 00000000..9c4bfa51 --- /dev/null +++ b/Assets/Resources/Player/Battle 4/Player 4-1.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 053d310f426c4b8459cd32f46e3491d4, type: 3} + m_Name: Player 4-1 + m_EditorClassIdentifier: + PlayerID: 1 + UnitData: + - {fileID: 11400000, guid: 46887c785e3822641a4fd79c553bda84, type: 2} + - {fileID: 11400000, guid: 069734e5b96bc064e8178d914cdae626, type: 2} + - {fileID: 11400000, guid: f016d481b03f2a04d86423fcbc9490f6, type: 2} + - {fileID: 11400000, guid: 7ab14eabf1920bc4a84647022949a215, type: 2} + UnitPositions: + - {x: -6, y: 2, z: 0} + - {x: -3, y: 1.2, z: 0} + - {x: -3, y: -1.2, z: 0} + - {x: -6, y: -2, z: 0} diff --git a/Assets/Resources/Player/Battle 4/Player 4-2.asset b/Assets/Resources/Player/Battle 4/Player 4-2.asset new file mode 100644 index 00000000..8f8c6b9b --- /dev/null +++ b/Assets/Resources/Player/Battle 4/Player 4-2.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 053d310f426c4b8459cd32f46e3491d4, type: 3} + m_Name: Player 4-2 + m_EditorClassIdentifier: + PlayerID: 2 + UnitData: + - {fileID: 11400000, guid: 62c3582c913eb5248a8469ef1883da78, type: 2} + - {fileID: 11400000, guid: 30d0684e24d795a42867d64014aece86, type: 2} + - {fileID: 11400000, guid: 14e444cabb3ddd34fbdfcb9fce6e5331, type: 2} + - {fileID: 11400000, guid: d2d35ed629463e646a7614dd021a47a2, type: 2} + UnitPositions: + - {x: 4, y: 2, z: 0} + - {x: 6, y: 1.2, z: 0} + - {x: 6, y: -1.2, z: 0} + - {x: 4, y: -2, z: 0} diff --git a/Assets/Resources/Player/Battle 4/Units/Unit 1-1.asset b/Assets/Resources/Player/Battle 4/Units/Unit 1-1.asset new file mode 100644 index 00000000..6ef476da --- /dev/null +++ b/Assets/Resources/Player/Battle 4/Units/Unit 1-1.asset @@ -0,0 +1,22 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 66518e3bb2dd340478171f97ec326357, type: 3} + m_Name: Unit 1-1 + m_EditorClassIdentifier: + UnitID: 1 + UnitType: 1 + UnitPrefab: {fileID: 7170176875333329667, guid: 94eb109406780014b814de72f826ea1e, type: 3} + MaxHealth: 10 + Power: 5 + executableCommands: 010000000300000002000000 + EnemyBattlePositionOffset: {x: 3, y: 0, z: 0} + MovementSpeed: 20 diff --git a/Assets/Resources/Player/Battle 4/Units/Unit 1-2.asset b/Assets/Resources/Player/Battle 4/Units/Unit 1-2.asset new file mode 100644 index 00000000..c58fce58 --- /dev/null +++ b/Assets/Resources/Player/Battle 4/Units/Unit 1-2.asset @@ -0,0 +1,22 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 66518e3bb2dd340478171f97ec326357, type: 3} + m_Name: Unit 1-2 + m_EditorClassIdentifier: + UnitID: 2 + UnitType: 2 + UnitPrefab: {fileID: 7170176875333329667, guid: 696c0c4f156c7a94ba075ee5549f46d9, type: 3} + MaxHealth: 10 + Power: 5 + executableCommands: 020000000400000002000000 + EnemyBattlePositionOffset: {x: 3, y: 0, z: 0} + MovementSpeed: 20 diff --git a/Assets/Resources/Player/Battle 4/Units/Unit 1-3.asset b/Assets/Resources/Player/Battle 4/Units/Unit 1-3.asset new file mode 100644 index 00000000..6997ce1e --- /dev/null +++ b/Assets/Resources/Player/Battle 4/Units/Unit 1-3.asset @@ -0,0 +1,22 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 66518e3bb2dd340478171f97ec326357, type: 3} + m_Name: Unit 1-3 + m_EditorClassIdentifier: + UnitID: 3 + UnitType: 3 + UnitPrefab: {fileID: 7170176875333329667, guid: 8346e216771ef4d4d91d50605efc7328, type: 3} + MaxHealth: 10 + Power: 5 + executableCommands: 010000000500000002000000 + EnemyBattlePositionOffset: {x: 3, y: 0, z: 0} + MovementSpeed: 20 diff --git a/Assets/Resources/Player/Battle 4/Units/Unit 1-4.asset b/Assets/Resources/Player/Battle 4/Units/Unit 1-4.asset new file mode 100644 index 00000000..22b965d4 --- /dev/null +++ b/Assets/Resources/Player/Battle 4/Units/Unit 1-4.asset @@ -0,0 +1,22 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 66518e3bb2dd340478171f97ec326357, type: 3} + m_Name: Unit 1-4 + m_EditorClassIdentifier: + UnitID: 4 + UnitType: 4 + UnitPrefab: {fileID: 7170176875333329667, guid: 51727404ff102f747bbef208e93b2b3e, type: 3} + MaxHealth: 10 + Power: 5 + executableCommands: 010000000600000002000000 + EnemyBattlePositionOffset: {x: 3, y: 0, z: 0} + MovementSpeed: 20 diff --git a/Assets/Resources/Player/Battle 4/Units/Unit 2-1.asset b/Assets/Resources/Player/Battle 4/Units/Unit 2-1.asset new file mode 100644 index 00000000..f20b35bd --- /dev/null +++ b/Assets/Resources/Player/Battle 4/Units/Unit 2-1.asset @@ -0,0 +1,22 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 66518e3bb2dd340478171f97ec326357, type: 3} + m_Name: Unit 2-1 + m_EditorClassIdentifier: + UnitID: 1 + UnitType: 1 + UnitPrefab: {fileID: 3287956947383386545, guid: cc31d5544f3c02f48b8687eff615d8b4, type: 3} + MaxHealth: 10 + Power: 5 + executableCommands: 010000000300000002000000 + EnemyBattlePositionOffset: {x: 3, y: 0, z: 0} + MovementSpeed: 20 diff --git a/Assets/Resources/Player/Battle 4/Units/Unit 2-2.asset b/Assets/Resources/Player/Battle 4/Units/Unit 2-2.asset new file mode 100644 index 00000000..2845c4fd --- /dev/null +++ b/Assets/Resources/Player/Battle 4/Units/Unit 2-2.asset @@ -0,0 +1,22 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 66518e3bb2dd340478171f97ec326357, type: 3} + m_Name: Unit 2-2 + m_EditorClassIdentifier: + UnitID: 2 + UnitType: 2 + UnitPrefab: {fileID: 3287956947383386545, guid: 5063a7765cfdaa74e81c7cba7436cd7b, type: 3} + MaxHealth: 10 + Power: 5 + executableCommands: 020000000400000002000000 + EnemyBattlePositionOffset: {x: 3, y: 0, z: 0} + MovementSpeed: 20 diff --git a/Assets/Resources/Player/Battle 4/Units/Unit 2-3.asset b/Assets/Resources/Player/Battle 4/Units/Unit 2-3.asset new file mode 100644 index 00000000..206b474d --- /dev/null +++ b/Assets/Resources/Player/Battle 4/Units/Unit 2-3.asset @@ -0,0 +1,22 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 66518e3bb2dd340478171f97ec326357, type: 3} + m_Name: Unit 2-3 + m_EditorClassIdentifier: + UnitID: 3 + UnitType: 3 + UnitPrefab: {fileID: 3287956947383386545, guid: 81e11e62b52cbc74dbd90ed212f91beb, type: 3} + MaxHealth: 10 + Power: 5 + executableCommands: 010000000500000002000000 + EnemyBattlePositionOffset: {x: 3, y: 0, z: 0} + MovementSpeed: 20 diff --git a/Assets/Resources/Player/Battle 4/Units/Unit 2-4.asset b/Assets/Resources/Player/Battle 4/Units/Unit 2-4.asset new file mode 100644 index 00000000..3b2fe739 --- /dev/null +++ b/Assets/Resources/Player/Battle 4/Units/Unit 2-4.asset @@ -0,0 +1,22 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 66518e3bb2dd340478171f97ec326357, type: 3} + m_Name: Unit 2-4 + m_EditorClassIdentifier: + UnitID: 4 + UnitType: 4 + UnitPrefab: {fileID: 3287956947383386545, guid: 601934b181c76164cb9dc247b665588e, type: 3} + MaxHealth: 10 + Power: 5 + executableCommands: 010000000600000002000000 + EnemyBattlePositionOffset: {x: 3, y: 0, z: 0} + MovementSpeed: 20 diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 168f4635..ec9c53a9 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -218,7 +218,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!224 &101671527 RectTransform: m_ObjectHideFlags: 0 @@ -1445,6 +1445,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 53b82781cf2fb9a4aa3b0d3e0a71f056, type: 3} m_Name: m_EditorClassIdentifier: + undoButton: {fileID: 101671528} turnText: {fileID: 144807538} missedText: {fileID: 1222372628} Player1BackgroundOverlay: {fileID: 1242843364} @@ -1471,7 +1472,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!224 &988327834 RectTransform: m_ObjectHideFlags: 0 @@ -1885,7 +1886,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 0.23529412} - m_RaycastTarget: 1 + m_RaycastTarget: 0 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 m_OnCullStateChanged: @@ -1947,7 +1948,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!224 &1260659848 RectTransform: m_ObjectHideFlags: 0 @@ -2233,6 +2234,7 @@ MonoBehaviour: - {fileID: 11400000, guid: f9f1d2cf049ff604aab41d149ba596e9, type: 2} - {fileID: 11400000, guid: 32addf10f4370374993da88ffd77ac5c, type: 2} - {fileID: 11400000, guid: f6b3f84e1bf293a4d847b3c8ba69cb3f, type: 2} + - {fileID: 11400000, guid: 641b40954bf84b04aa75aad904451f0b, type: 2} sfxSource: {fileID: 363944623} bgMusicSource: {fileID: 927446004} --- !u!4 &1409757741 @@ -2376,7 +2378,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 0.23529412} - m_RaycastTarget: 1 + m_RaycastTarget: 0 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 m_OnCullStateChanged: @@ -2613,7 +2615,7 @@ RectTransform: m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} m_AnchoredPosition: {x: 0, y: 71} - m_SizeDelta: {x: 400, y: 32} + m_SizeDelta: {x: 400, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &1861826650 MonoBehaviour: @@ -2787,6 +2789,7 @@ MonoBehaviour: m_EditorClassIdentifier: resultText: {fileID: 1682630446} homeButton: {fileID: 799045267} + replayButton: {fileID: 988327835} --- !u!1 &2089575972 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Action/ActionService.cs b/Assets/Scripts/Action/ActionService.cs index 957c65c0..a3b546ec 100644 --- a/Assets/Scripts/Action/ActionService.cs +++ b/Assets/Scripts/Action/ActionService.cs @@ -1,27 +1,28 @@ using Command.Input; +using Command.Commands; using System.Collections.Generic; namespace Command.Actions { public class ActionService { - private Dictionary actions; + private Dictionary actions; public ActionService() => CreateActions(); private void CreateActions() { - actions = new Dictionary(); - actions.Add(ActionType.Attack, new AttackAction()); - actions.Add(ActionType.Heal, new HealAction()); - actions.Add(ActionType.AttackStance, new AttackStanceAction()); - actions.Add(ActionType.Cleanse, new CleanseAction()); - actions.Add(ActionType.Meditate, new MeditateAction()); - actions.Add(ActionType.BerserkAttack, new BerserkAttackAction()); - actions.Add(ActionType.ThirdEye, new ThirdEyeAction()); + actions = new Dictionary(); + actions.Add(CommandType.Attack, new AttackAction()); + actions.Add(CommandType.Heal, new HealAction()); + actions.Add(CommandType.AttackStance, new AttackStanceAction()); + actions.Add(CommandType.Cleanse, new CleanseAction()); + actions.Add(CommandType.Meditate, new MeditateAction()); + actions.Add(CommandType.BerserkAttack, new BerserkAttackAction()); + actions.Add(CommandType.ThirdEye, new ThirdEyeAction()); } - public IAction GetActionByType(ActionType type) + public IAction GetActionByType(CommandType type) { if (actions.ContainsKey(type)) return actions[type]; @@ -29,6 +30,6 @@ public IAction GetActionByType(ActionType type) throw new System.Exception($"No Action found for the type {type} in the dictionary"); } - public TargetType GetTargetTypeForAction(ActionType actionType) => actions[actionType].TargetType; + public TargetType GetTargetTypeForAction(CommandType actionType) => actions[actionType].TargetType; } } \ No newline at end of file diff --git a/Assets/Scripts/Action/Actions/AttackAction.cs b/Assets/Scripts/Action/Actions/AttackAction.cs index 75632f04..11ae16e6 100644 --- a/Assets/Scripts/Action/Actions/AttackAction.cs +++ b/Assets/Scripts/Action/Actions/AttackAction.cs @@ -1,3 +1,4 @@ +using Command.Commands; using Command.Input; using Command.Main; using Command.Player; @@ -9,28 +10,28 @@ public class AttackAction : IAction { private UnitController actorUnit; private UnitController targetUnit; + private bool isSuccessful; public TargetType TargetType => TargetType.Enemy; - public void PerformAction(UnitController actorUnit, UnitController targetUnit) + public void PerformAction(UnitController actorUnit, UnitController targetUnit, bool isSuccessful) { this.actorUnit = actorUnit; this.targetUnit = targetUnit; + this.isSuccessful = isSuccessful; - actorUnit.PlayBattleAnimation(ActionType.Attack, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); + actorUnit.PlayBattleAnimation(CommandType.Attack, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); } public void OnActionAnimationCompleted() { PlayAttackSound(); - if (IsSuccessful()) + if (isSuccessful) targetUnit.TakeDamage(actorUnit.CurrentPower); else GameService.Instance.UIService.ActionMissed(); } - public bool IsSuccessful() => true; - public Vector3 CalculateMovePosition(UnitController targetUnit) => targetUnit.GetEnemyPosition(); private void PlayAttackSound() diff --git a/Assets/Scripts/Action/Actions/AttackStanceAction.cs b/Assets/Scripts/Action/Actions/AttackStanceAction.cs index 9fc46d34..bc3f8aa8 100644 --- a/Assets/Scripts/Action/Actions/AttackStanceAction.cs +++ b/Assets/Scripts/Action/Actions/AttackStanceAction.cs @@ -1,6 +1,7 @@ using Command.Player; using Command.Input; using Command.Main; +using Command.Commands; using UnityEngine; namespace Command.Actions @@ -9,28 +10,28 @@ public class AttackStanceAction : IAction { private UnitController actorUnit; private UnitController targetUnit; + private bool isSuccessful; TargetType IAction.TargetType { get => TargetType.Self; } - public void PerformAction(UnitController actorUnit, UnitController targetUnit) + public void PerformAction(UnitController actorUnit, UnitController targetUnit, bool isSuccessful) { this.actorUnit = actorUnit; this.targetUnit = targetUnit; + this.isSuccessful = isSuccessful; - actorUnit.PlayBattleAnimation(ActionType.AttackStance, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); + actorUnit.PlayBattleAnimation(CommandType.AttackStance, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); } public void OnActionAnimationCompleted() { GameService.Instance.SoundService.PlaySoundEffects(Sound.SoundType.ATTACK_STANCE); - if (IsSuccessful()) + if (isSuccessful) targetUnit.CurrentPower += (int)(targetUnit.CurrentPower * 0.2f); else GameService.Instance.UIService.ActionMissed(); } - public bool IsSuccessful() => true; - public Vector3 CalculateMovePosition(UnitController targetUnit) => targetUnit.GetEnemyPosition(); } } \ No newline at end of file diff --git a/Assets/Scripts/Action/Actions/BerserkAttackAction.cs b/Assets/Scripts/Action/Actions/BerserkAttackAction.cs index 42ce5acd..5ed281e9 100644 --- a/Assets/Scripts/Action/Actions/BerserkAttackAction.cs +++ b/Assets/Scripts/Action/Actions/BerserkAttackAction.cs @@ -1,3 +1,4 @@ +using Command.Commands; using Command.Input; using Command.Main; using Command.Player; @@ -7,34 +8,35 @@ namespace Command.Actions { public class BerserkAttackAction : IAction { - private const float hitChance = 0.66f; private UnitController actorUnit; private UnitController targetUnit; + private bool isSuccessful; + public TargetType TargetType => TargetType.Enemy; - public void PerformAction(UnitController actorUnit, UnitController targetUnit) + public void PerformAction(UnitController actorUnit, UnitController targetUnit, bool isSuccessful) { this.actorUnit = actorUnit; this.targetUnit = targetUnit; + this.isSuccessful = isSuccessful; - actorUnit.PlayBattleAnimation(ActionType.BerserkAttack, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); + actorUnit.PlayBattleAnimation(CommandType.BerserkAttack, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); } public void OnActionAnimationCompleted() { GameService.Instance.SoundService.PlaySoundEffects(Sound.SoundType.BERSERK_ATTACK); - if (IsSuccessful()) + if (isSuccessful) targetUnit.TakeDamage(actorUnit.CurrentPower * 2); else { actorUnit.TakeDamage(actorUnit.CurrentPower * 2); + actorUnit.OnActionExecuted(); Debug.Log("actor unit must be hit now."); } } - public bool IsSuccessful() => Random.Range(0f, 1f) < hitChance; - public Vector3 CalculateMovePosition(UnitController targetUnit) => targetUnit.GetEnemyPosition(); } } \ No newline at end of file diff --git a/Assets/Scripts/Action/Actions/CleanseAction.cs b/Assets/Scripts/Action/Actions/CleanseAction.cs index 469071ea..34eea7d6 100644 --- a/Assets/Scripts/Action/Actions/CleanseAction.cs +++ b/Assets/Scripts/Action/Actions/CleanseAction.cs @@ -2,36 +2,37 @@ using Command.Player; using Command.Main; using UnityEngine; +using Command.Commands; namespace Command.Actions { public class CleanseAction : IAction { - private const float hitChance = 0.2f; private UnitController actorUnit; private UnitController targetUnit; + private bool isSuccessful; + public TargetType TargetType => TargetType.Enemy; - public void PerformAction(UnitController actorUnit, UnitController targetUnit) + public void PerformAction(UnitController actorUnit, UnitController targetUnit, bool isSuccessful) { this.actorUnit = actorUnit; this.targetUnit = targetUnit; + this.isSuccessful = isSuccessful; - actorUnit.PlayBattleAnimation(ActionType.Cleanse, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); + actorUnit.PlayBattleAnimation(CommandType.Cleanse, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); } public void OnActionAnimationCompleted() { GameService.Instance.SoundService.PlaySoundEffects(Sound.SoundType.CLEANSE); - if (IsSuccessful()) + if (isSuccessful) targetUnit.ResetStats(); else GameService.Instance.UIService.ActionMissed(); } - public bool IsSuccessful() => Random.Range(0f, 1f) < hitChance; - public Vector3 CalculateMovePosition(UnitController targetUnit) => targetUnit.GetEnemyPosition(); } } diff --git a/Assets/Scripts/Action/Actions/HealAction.cs b/Assets/Scripts/Action/Actions/HealAction.cs index d05b6d47..f98df74c 100644 --- a/Assets/Scripts/Action/Actions/HealAction.cs +++ b/Assets/Scripts/Action/Actions/HealAction.cs @@ -1,3 +1,4 @@ +using Command.Commands; using Command.Input; using Command.Main; using Command.Player; @@ -9,26 +10,26 @@ public class HealAction : IAction { private UnitController actorUnit; private UnitController targetUnit; + private bool isSuccessful; public TargetType TargetType => TargetType.Friendly; - public void PerformAction(UnitController actorUnit, UnitController targetUnit) + public void PerformAction(UnitController actorUnit, UnitController targetUnit, bool isSuccessful) { this.actorUnit = actorUnit; this.targetUnit = targetUnit; + this.isSuccessful = isSuccessful; - actorUnit.PlayBattleAnimation(ActionType.Heal, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); + actorUnit.PlayBattleAnimation(CommandType.Heal, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); } public void OnActionAnimationCompleted() { GameService.Instance.SoundService.PlaySoundEffects(Sound.SoundType.HEAL); - if (IsSuccessful()) + if (isSuccessful) targetUnit.RestoreHealth(actorUnit.CurrentPower); } - public bool IsSuccessful() => true; - public Vector3 CalculateMovePosition(UnitController targetUnit) => targetUnit.GetEnemyPosition(); } } \ No newline at end of file diff --git a/Assets/Scripts/Action/Actions/MeditateAction.cs b/Assets/Scripts/Action/Actions/MeditateAction.cs index 869e159b..26259374 100644 --- a/Assets/Scripts/Action/Actions/MeditateAction.cs +++ b/Assets/Scripts/Action/Actions/MeditateAction.cs @@ -1,3 +1,4 @@ +using Command.Commands; using Command.Input; using Command.Main; using Command.Player; @@ -9,21 +10,24 @@ public class MeditateAction : IAction { private UnitController actorUnit; private UnitController targetUnit; + private bool isSuccessful; + public TargetType TargetType => TargetType.Self; - public void PerformAction(UnitController actorUnit, UnitController targetUnit) + public void PerformAction(UnitController actorUnit, UnitController targetUnit, bool isSuccessful) { this.actorUnit = actorUnit; this.targetUnit = targetUnit; + this.isSuccessful = isSuccessful; - actorUnit.PlayBattleAnimation(ActionType.Meditate, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); + actorUnit.PlayBattleAnimation(CommandType.Meditate, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); } public void OnActionAnimationCompleted() { GameService.Instance.SoundService.PlaySoundEffects(Sound.SoundType.MEDITATE); - if (IsSuccessful()) + if (isSuccessful) { var healthToIncrease = (int)(targetUnit.CurrentMaxHealth * 0.2f); targetUnit.CurrentMaxHealth += healthToIncrease; @@ -33,8 +37,6 @@ public void OnActionAnimationCompleted() GameService.Instance.UIService.ActionMissed(); } - public bool IsSuccessful() => true; - public Vector3 CalculateMovePosition(UnitController targetUnit) => targetUnit.GetEnemyPosition(); } } \ No newline at end of file diff --git a/Assets/Scripts/Action/Actions/ThirdEyeAction.cs b/Assets/Scripts/Action/Actions/ThirdEyeAction.cs index 8a24ba01..7dbd9bfa 100644 --- a/Assets/Scripts/Action/Actions/ThirdEyeAction.cs +++ b/Assets/Scripts/Action/Actions/ThirdEyeAction.cs @@ -1,3 +1,4 @@ +using Command.Commands; using Command.Input; using Command.Main; using Command.Player; @@ -9,19 +10,22 @@ public class ThirdEyeAction : IAction { private UnitController actorUnit; private UnitController targetUnit; + private bool isSuccessful; + public TargetType TargetType => TargetType.Self; - public void PerformAction(UnitController actorUnit, UnitController targetUnit) + public void PerformAction(UnitController actorUnit, UnitController targetUnit, bool isSuccessful) { this.actorUnit = actorUnit; this.targetUnit = targetUnit; + this.isSuccessful = isSuccessful; - actorUnit.PlayBattleAnimation(ActionType.BerserkAttack, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); + actorUnit.PlayBattleAnimation(CommandType.BerserkAttack, CalculateMovePosition(targetUnit), OnActionAnimationCompleted); } public void OnActionAnimationCompleted() { - if (IsSuccessful()) + if (isSuccessful) { int healthToConvert = (int)(targetUnit.CurrentHealth * 0.25f); targetUnit.TakeDamage(healthToConvert); @@ -31,8 +35,6 @@ public void OnActionAnimationCompleted() GameService.Instance.UIService.ActionMissed(); } - public bool IsSuccessful() => true; - public Vector3 CalculateMovePosition(UnitController targetUnit) => targetUnit.GetEnemyPosition(); } } \ No newline at end of file diff --git a/Assets/Scripts/Action/IAction.cs b/Assets/Scripts/Action/IAction.cs index 610560d8..a73327e7 100644 --- a/Assets/Scripts/Action/IAction.cs +++ b/Assets/Scripts/Action/IAction.cs @@ -11,9 +11,7 @@ public interface IAction { public TargetType TargetType { get; } - public void PerformAction(UnitController actorUnit, UnitController targetUnit); - - public bool IsSuccessful(); + public void PerformAction(UnitController actorUnit, UnitController targetUnit, bool isSuccessful); public Vector3 CalculateMovePosition(UnitController targetUnit); } diff --git a/Assets/Scripts/Battle/BattleService.cs b/Assets/Scripts/Battle/BattleService.cs index 0709f35f..b3d53f65 100644 --- a/Assets/Scripts/Battle/BattleService.cs +++ b/Assets/Scripts/Battle/BattleService.cs @@ -16,8 +16,12 @@ public BattleService(List battleScriptableObjects) SubscribeToEvents(); } - private void SubscribeToEvents() => GameService.Instance.EventService.OnBattleSelected.AddListener(LoadBattle); - + private void SubscribeToEvents() + { + GameService.Instance.EventService.OnBattleSelected.AddListener(LoadBattle); + GameService.Instance.EventService.OnReplayButtonClicked.AddListener(ReplayBattle); + } + private void LoadBattle(int battleId) { currentBattleId = battleId; @@ -29,5 +33,7 @@ private void LoadBattle(int battleId) } private BattleScriptableObject GetBattleDataByID(int battleId) => battleScriptableObjects.Find(battleSO => battleSO.BattleID == battleId); + + private void ReplayBattle() => LoadBattle(currentBattleId); } } diff --git a/Assets/Scripts/Command.meta b/Assets/Scripts/Command.meta new file mode 100644 index 00000000..1e9e808d --- /dev/null +++ b/Assets/Scripts/Command.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 057c0ab2ac9ca0e4fa171bc5a7b7c2dd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Command/Abstract Commands.meta b/Assets/Scripts/Command/Abstract Commands.meta new file mode 100644 index 00000000..69cc3bee --- /dev/null +++ b/Assets/Scripts/Command/Abstract Commands.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6bd3bf9b13445164c8eae27ef19b4ca3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Command/Abstract Commands/ICommand.cs b/Assets/Scripts/Command/Abstract Commands/ICommand.cs new file mode 100644 index 00000000..bc817aa7 --- /dev/null +++ b/Assets/Scripts/Command/Abstract Commands/ICommand.cs @@ -0,0 +1,25 @@ +namespace Command.Commands +{ + public interface ICommand + { + public void Execute(); + + public void Undo(); + } + + public struct CommandData + { + public int ActorUnitID; + public int TargetUnitID; + public int ActorPlayerID; + public int TargetPlayerID; + + public CommandData(int ActorUnitID, int TargetUnitID,int ActorPlayerID, int TargetPlayerID) + { + this.ActorUnitID = ActorUnitID; + this.TargetUnitID = TargetUnitID; + this.ActorPlayerID = ActorPlayerID; + this.TargetPlayerID = TargetPlayerID; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Command/Abstract Commands/ICommand.cs.meta b/Assets/Scripts/Command/Abstract Commands/ICommand.cs.meta new file mode 100644 index 00000000..16fb8f1e --- /dev/null +++ b/Assets/Scripts/Command/Abstract Commands/ICommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1694b2a5c5fb77e4b8c12b63c23898ca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Command/Abstract Commands/UnitCommand.cs b/Assets/Scripts/Command/Abstract Commands/UnitCommand.cs new file mode 100644 index 00000000..944d847b --- /dev/null +++ b/Assets/Scripts/Command/Abstract Commands/UnitCommand.cs @@ -0,0 +1,22 @@ +using Command.Player; + +namespace Command.Commands +{ + public abstract class UnitCommand : ICommand + { + public CommandData commandData; + + protected UnitController actorUnit; + protected UnitController targetUnit; + + public abstract void Execute(); + + public abstract void Undo(); + + public abstract bool WillHitTarget(); + + public void SetActorUnit(UnitController actorUnit) => this.actorUnit = actorUnit; + + public void SetTargetUnit(UnitController targetUnit) => this.targetUnit = targetUnit; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Command/Abstract Commands/UnitCommand.cs.meta b/Assets/Scripts/Command/Abstract Commands/UnitCommand.cs.meta new file mode 100644 index 00000000..c015f0d6 --- /dev/null +++ b/Assets/Scripts/Command/Abstract Commands/UnitCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 90e5347a76c8bba418c5b957b9ccc682 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Command/CommandInvoker.cs b/Assets/Scripts/Command/CommandInvoker.cs new file mode 100644 index 00000000..06833926 --- /dev/null +++ b/Assets/Scripts/Command/CommandInvoker.cs @@ -0,0 +1,37 @@ +using Command.Main; +using System.Collections.Generic; +using UnityEngine; + +namespace Command.Commands +{ + public class CommandInvoker + { + private Stack commandRegistry = new(); + + public void ProcessCommand(ICommand commandToProcess) + { + ExecuteCommand(commandToProcess); + RegisterCommand(commandToProcess); + } + + public void ExecuteCommand(ICommand commandToExecute) => commandToExecute.Execute(); + + public void RegisterCommand(ICommand commandToRegister) => commandRegistry.Push(commandToRegister); + + public void Undo() + { + if (!RegistryEmpty() && CommandBelongsToActivePlayer()) + commandRegistry.Pop().Undo(); + } + + private bool RegistryEmpty() => commandRegistry.Count == 0; + + private bool CommandBelongsToActivePlayer() => (commandRegistry.Peek() as UnitCommand).commandData.ActorPlayerID == GameService.Instance.PlayerService.ActivePlayerID; + + public void SetReplayCommandStack() + { + GameService.Instance.ReplayService.SetCommandStack(commandRegistry); + commandRegistry.Clear(); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Command/CommandInvoker.cs.meta b/Assets/Scripts/Command/CommandInvoker.cs.meta new file mode 100644 index 00000000..afeecb98 --- /dev/null +++ b/Assets/Scripts/Command/CommandInvoker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef2285a6c836f4345b10e73a227cde34 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Action/ActionType.cs b/Assets/Scripts/Command/CommandType.cs similarity index 73% rename from Assets/Scripts/Action/ActionType.cs rename to Assets/Scripts/Command/CommandType.cs index f6c14302..0a1e430e 100644 --- a/Assets/Scripts/Action/ActionType.cs +++ b/Assets/Scripts/Command/CommandType.cs @@ -1,6 +1,6 @@ -namespace Command.Actions +namespace Command.Commands { - public enum ActionType + public enum CommandType { None, Attack, diff --git a/Assets/Scripts/Action/ActionType.cs.meta b/Assets/Scripts/Command/CommandType.cs.meta similarity index 100% rename from Assets/Scripts/Action/ActionType.cs.meta rename to Assets/Scripts/Command/CommandType.cs.meta diff --git a/Assets/Scripts/Command/ConcreteCommands.meta b/Assets/Scripts/Command/ConcreteCommands.meta new file mode 100644 index 00000000..23e370f1 --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 55cc47bf89042a94291adf77ae1962bc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Command/ConcreteCommands/AttackCommand.cs b/Assets/Scripts/Command/ConcreteCommands/AttackCommand.cs new file mode 100644 index 00000000..ddb31c17 --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/AttackCommand.cs @@ -0,0 +1,31 @@ +using Command.Main; + +namespace Command.Commands +{ + public class AttackCommand : UnitCommand + { + private bool willHitTarget; + + public AttackCommand(CommandData commandData) + { + this.commandData = commandData; + willHitTarget = WillHitTarget(); + } + + public override bool WillHitTarget() => true; + + public override void Execute() => GameService.Instance.ActionService.GetActionByType(CommandType.Attack).PerformAction(actorUnit, targetUnit, willHitTarget); + + public override void Undo() + { + if (willHitTarget) + { + if (!targetUnit.IsAlive()) + targetUnit.Revive(); + + targetUnit.RestoreHealth(actorUnit.CurrentPower); + actorUnit.Owner.ResetCurrentActiveUnit(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Command/ConcreteCommands/AttackCommand.cs.meta b/Assets/Scripts/Command/ConcreteCommands/AttackCommand.cs.meta new file mode 100644 index 00000000..22275d85 --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/AttackCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 00ed892a7cb8738439eb141a0e0cddb0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Command/ConcreteCommands/AttackStanceCommand.cs b/Assets/Scripts/Command/ConcreteCommands/AttackStanceCommand.cs new file mode 100644 index 00000000..126399f1 --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/AttackStanceCommand.cs @@ -0,0 +1,28 @@ +using Command.Main; + +namespace Command.Commands +{ + public class AttackStanceCommand : UnitCommand + { + private bool willHitTarget; + + public AttackStanceCommand(CommandData commandData) + { + this.commandData = commandData; + willHitTarget = WillHitTarget(); + } + + public override void Execute() => GameService.Instance.ActionService.GetActionByType(CommandType.AttackStance).PerformAction(actorUnit, targetUnit, willHitTarget); + + public override void Undo() + { + if (willHitTarget) + { + targetUnit.CurrentPower -= (int)(targetUnit.CurrentPower * 0.2f); + actorUnit.Owner.ResetCurrentActiveUnit(); + } + } + + public override bool WillHitTarget() => true; + } +} diff --git a/Assets/Scripts/Command/ConcreteCommands/AttackStanceCommand.cs.meta b/Assets/Scripts/Command/ConcreteCommands/AttackStanceCommand.cs.meta new file mode 100644 index 00000000..19e8d1aa --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/AttackStanceCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7d3197fa1f4b55f4dbcaa1635ee3e7e8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Command/ConcreteCommands/BerserkAttackCommand.cs b/Assets/Scripts/Command/ConcreteCommands/BerserkAttackCommand.cs new file mode 100644 index 00000000..ec99f1bd --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/BerserkAttackCommand.cs @@ -0,0 +1,40 @@ +using Command.Main; +using UnityEngine; + +namespace Command.Commands +{ + public class BerserkAttackCommand : UnitCommand + { + private bool willHitTarget; + private const float hitChance = 0.66f; + + public BerserkAttackCommand(CommandData commandData) + { + this.commandData = commandData; + willHitTarget = WillHitTarget(); + } + + public override void Execute() => GameService.Instance.ActionService.GetActionByType(CommandType.BerserkAttack).PerformAction(actorUnit, targetUnit, willHitTarget); + + public override void Undo() + { + if (willHitTarget) + { + if (!targetUnit.IsAlive()) + targetUnit.Revive(); + + targetUnit.RestoreHealth(actorUnit.CurrentPower * 2); + } + else + { + if (!actorUnit.IsAlive()) + actorUnit.Revive(); + + actorUnit.RestoreHealth(actorUnit.CurrentPower * 2); + } + actorUnit.Owner.ResetCurrentActiveUnit(); + } + + public override bool WillHitTarget() => Random.Range(0f, 1f) < hitChance; + } +} diff --git a/Assets/Scripts/Command/ConcreteCommands/BerserkAttackCommand.cs.meta b/Assets/Scripts/Command/ConcreteCommands/BerserkAttackCommand.cs.meta new file mode 100644 index 00000000..31dc3a0e --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/BerserkAttackCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4f62618eba9ffa542a5f213d150803ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Command/ConcreteCommands/CleanseCommand.cs b/Assets/Scripts/Command/ConcreteCommands/CleanseCommand.cs new file mode 100644 index 00000000..6f00986b --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/CleanseCommand.cs @@ -0,0 +1,34 @@ +using Command.Main; +using UnityEngine; + +namespace Command.Commands +{ + public class CleanseCommand : UnitCommand + { + private bool willHitTarget; + private const float hitChance = 0.2f; + private int previousPower; + + public CleanseCommand(CommandData commandData) + { + this.commandData = commandData; + willHitTarget = WillHitTarget(); + } + + public override void Execute() + { + previousPower = targetUnit.CurrentPower; + GameService.Instance.ActionService.GetActionByType(CommandType.Cleanse).PerformAction(actorUnit, targetUnit, willHitTarget); + } + + public override void Undo() + { + if (willHitTarget) + targetUnit.CurrentPower = previousPower; + + actorUnit.Owner.ResetCurrentActiveUnit(); + } + + public override bool WillHitTarget() => Random.Range(0f, 1f) < hitChance; + } +} diff --git a/Assets/Scripts/Command/ConcreteCommands/CleanseCommand.cs.meta b/Assets/Scripts/Command/ConcreteCommands/CleanseCommand.cs.meta new file mode 100644 index 00000000..4f8620f0 --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/CleanseCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 309efdff4d5eb594399f96309278aecc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Command/ConcreteCommands/HealCommand.cs b/Assets/Scripts/Command/ConcreteCommands/HealCommand.cs new file mode 100644 index 00000000..ef90ef33 --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/HealCommand.cs @@ -0,0 +1,28 @@ +using Command.Main; + +namespace Command.Commands +{ + public class HealCommand : UnitCommand + { + private bool willHitTarget; + + public HealCommand(CommandData commandData) + { + this.commandData = commandData; + willHitTarget = WillHitTarget(); + } + + public override void Execute() => GameService.Instance.ActionService.GetActionByType(CommandType.Heal).PerformAction(actorUnit, targetUnit, willHitTarget); + + public override void Undo() + { + if (willHitTarget) + { + targetUnit.TakeDamage(actorUnit.CurrentPower); + actorUnit.Owner.ResetCurrentActiveUnit(); + } + } + + public override bool WillHitTarget() => true; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Command/ConcreteCommands/HealCommand.cs.meta b/Assets/Scripts/Command/ConcreteCommands/HealCommand.cs.meta new file mode 100644 index 00000000..f55e3d0f --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/HealCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c01465896d721740947c4d0328cfb17 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Command/ConcreteCommands/MeditateCommand.cs b/Assets/Scripts/Command/ConcreteCommands/MeditateCommand.cs new file mode 100644 index 00000000..d176f4a0 --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/MeditateCommand.cs @@ -0,0 +1,35 @@ +using Command.Main; + +namespace Command.Commands +{ + public class MeditateCommand : UnitCommand + { + private bool willHitTarget; + private int previousMaxHealth; + + public MeditateCommand(CommandData commandData) + { + this.commandData = commandData; + willHitTarget = WillHitTarget(); + } + + public override void Execute() + { + previousMaxHealth = targetUnit.CurrentMaxHealth; + GameService.Instance.ActionService.GetActionByType(CommandType.Meditate).PerformAction(actorUnit, targetUnit, willHitTarget); + } + + public override void Undo() + { + if (willHitTarget) + { + var healthToReduce = targetUnit.CurrentMaxHealth - previousMaxHealth; + targetUnit.CurrentMaxHealth = previousMaxHealth; + targetUnit.TakeDamage(healthToReduce); + } + actorUnit.Owner.ResetCurrentActiveUnit(); + } + + public override bool WillHitTarget() => true; + } +} diff --git a/Assets/Scripts/Command/ConcreteCommands/MeditateCommand.cs.meta b/Assets/Scripts/Command/ConcreteCommands/MeditateCommand.cs.meta new file mode 100644 index 00000000..40eab923 --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/MeditateCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7eb8278659a46384982ecbd6a0f52c81 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Command/ConcreteCommands/ThirdEyeCommand.cs b/Assets/Scripts/Command/ConcreteCommands/ThirdEyeCommand.cs new file mode 100644 index 00000000..901ad28c --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/ThirdEyeCommand.cs @@ -0,0 +1,35 @@ +using Command.Main; + +namespace Command.Commands +{ + public class ThirdEyeCommand : UnitCommand + { + private bool willHitTarget; + private int previousHealth; + + public ThirdEyeCommand(CommandData commandData) + { + this.commandData = commandData; + willHitTarget = WillHitTarget(); + } + + public override void Execute() + { + previousHealth = targetUnit.CurrentHealth; + GameService.Instance.ActionService.GetActionByType(CommandType.ThirdEye).PerformAction(actorUnit, targetUnit, willHitTarget); + } + + public override void Undo() + { + if(!targetUnit.IsAlive()) + targetUnit.Revive(); + + int healthToRestore = (int)(previousHealth * 0.25f); + targetUnit.RestoreHealth(healthToRestore); + targetUnit.CurrentPower -= healthToRestore; + actorUnit.Owner.ResetCurrentActiveUnit(); + } + + public override bool WillHitTarget() => true; + } +} diff --git a/Assets/Scripts/Command/ConcreteCommands/ThirdEyeCommand.cs.meta b/Assets/Scripts/Command/ConcreteCommands/ThirdEyeCommand.cs.meta new file mode 100644 index 00000000..6fcf2e51 --- /dev/null +++ b/Assets/Scripts/Command/ConcreteCommands/ThirdEyeCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6981291794a59074f9e544d5aacecf35 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Events/EventService.cs b/Assets/Scripts/Events/EventService.cs index 59b664c2..7241c75e 100644 --- a/Assets/Scripts/Events/EventService.cs +++ b/Assets/Scripts/Events/EventService.cs @@ -1,4 +1,4 @@ -using Command.Actions; +using Command.Commands; /** This script demonstrates implementation of the Observer Pattern. * If you're interested in learning about Observer Pattern, @@ -11,12 +11,14 @@ namespace Command.Events public class EventService { public GameEventController OnBattleSelected { get; private set; } - public GameEventController OnActionSelected { get; private set; } + public GameEventController OnActionSelected { get; private set; } + public GameEventController OnReplayButtonClicked { get; private set; } public EventService() { OnBattleSelected = new GameEventController(); - OnActionSelected = new GameEventController(); + OnActionSelected = new GameEventController(); + OnReplayButtonClicked = new GameEventController(); } } } \ No newline at end of file diff --git a/Assets/Scripts/Input/InputService.cs b/Assets/Scripts/Input/InputService.cs index de088222..eb89498a 100644 --- a/Assets/Scripts/Input/InputService.cs +++ b/Assets/Scripts/Input/InputService.cs @@ -1,6 +1,6 @@ using Command.Main; using Command.Player; -using Command.Actions; +using Command.Commands; namespace Command.Input { @@ -9,7 +9,7 @@ public class InputService private MouseInputHandler mouseInputHandler; private InputState currentState; - private ActionType selectedActionType; + private CommandType selectedCommandType; private TargetType targetType; public InputService() @@ -29,9 +29,9 @@ public void UpdateInputService() mouseInputHandler.HandleTargetSelection(targetType); } - public void OnActionSelected(ActionType selectedActionType) + public void OnActionSelected(CommandType selectedActionType) { - this.selectedActionType = selectedActionType; + this.selectedCommandType = selectedActionType; SetInputState(InputState.SELECTING_TARGET); TargetType targetType = SetTargetType(selectedActionType); ShowTargetSelectionUI(targetType); @@ -43,12 +43,47 @@ private void ShowTargetSelectionUI(TargetType selectedTargetType) GameService.Instance.UIService.ShowTargetOverlay(playerID, selectedTargetType); } - private TargetType SetTargetType(ActionType selectedActionType) => targetType = GameService.Instance.ActionService.GetTargetTypeForAction(selectedActionType); + private TargetType SetTargetType(CommandType selectedCommandType) => targetType = GameService.Instance.ActionService.GetTargetTypeForAction(selectedCommandType); public void OnTargetSelected(UnitController targetUnit) { SetInputState(InputState.EXECUTING_INPUT); - GameService.Instance.PlayerService.PerformAction(selectedActionType, targetUnit); + UnitCommand commandToProcess = CreateUnitCommand(targetUnit); + GameService.Instance.ProcessUnitCommand(commandToProcess); + } + + private UnitCommand CreateUnitCommand(UnitController targetUnit) + { + + CommandData commandData = CreateCommandData(targetUnit); + + switch (selectedCommandType) + { + case CommandType.Attack: + return new AttackCommand(commandData); + case CommandType.Heal: + return new HealCommand(commandData); + case CommandType.AttackStance: + return new AttackStanceCommand(commandData); + case CommandType.Cleanse: + return new CleanseCommand(commandData); + case CommandType.BerserkAttack: + return new BerserkAttackCommand(commandData); + case CommandType.Meditate: + return new MeditateCommand(commandData); + case CommandType.ThirdEye: + return new ThirdEyeCommand(commandData); + default: + throw new System.Exception($"No Command found of type: {selectedCommandType}"); + } + } + + private CommandData CreateCommandData(UnitController targetUnit) + { + return new CommandData(GameService.Instance.PlayerService.ActiveUnitID, + targetUnit.UnitID, + GameService.Instance.PlayerService.ActivePlayerID, + targetUnit.Owner.PlayerID); } } } \ No newline at end of file diff --git a/Assets/Scripts/Main/GameService.cs b/Assets/Scripts/Main/GameService.cs index e8a709be..33868430 100644 --- a/Assets/Scripts/Main/GameService.cs +++ b/Assets/Scripts/Main/GameService.cs @@ -9,6 +9,8 @@ using Command.Battle; using Command.Actions; using UnityEngine.UI; +using Command.Commands; +using Replay; namespace Command.Main { @@ -28,6 +30,8 @@ public class GameService : GenericMonoSingleton public InputService InputService { get; private set; } public BattleService BattleService { get; private set; } public PlayerService PlayerService { get; private set; } + public CommandInvoker CommandInvoker { get; private set; } + public ReplayService ReplayService { get; private set; } [SerializeField] private UIService uiService; public UIService UIService => uiService; @@ -49,8 +53,12 @@ private void Start() BattleService = new BattleService(battleScriptableObjects); PlayerService = new PlayerService(); uiService.Init(battleScriptableObjects.Count); + CommandInvoker = new CommandInvoker(); + ReplayService = new ReplayService(); } private void Update() => InputService.UpdateInputService(); + + public void ProcessUnitCommand(ICommand commandToProcess) => PlayerService.ProcessUnitCommand(commandToProcess as UnitCommand); } } \ No newline at end of file diff --git a/Assets/Scripts/Player/PlayerController.cs b/Assets/Scripts/Player/PlayerController.cs index 3860582a..faff057c 100644 --- a/Assets/Scripts/Player/PlayerController.cs +++ b/Assets/Scripts/Player/PlayerController.cs @@ -1,3 +1,4 @@ +using Command.Commands; using System.Collections.Generic; using UnityEngine; @@ -82,12 +83,24 @@ public void DestroyAllUnits() units.Clear(); } - // TODO: What is this?? - public void ResetCurrentActivePlayer() + public void ProcessUnitCommand(UnitCommand commandToProcess) => GetUnitByID(commandToProcess.commandData.ActorUnitID).ProcessUnitCommand(commandToProcess); + + public void ResetCurrentActiveUnit() { units[activeUnitIndex].ResetUnitIndicator(); + activeUnitIndex--; - units[activeUnitIndex].StartUnitTurn(); + + while(activeUnitIndex >= 0) + { + if (!units[activeUnitIndex].IsAlive()) + activeUnitIndex--; + else + { + units[activeUnitIndex].StartUnitTurn(); + break; + } + } } } } \ No newline at end of file diff --git a/Assets/Scripts/Player/PlayerService.cs b/Assets/Scripts/Player/PlayerService.cs index ec1f8bb4..c420830d 100644 --- a/Assets/Scripts/Player/PlayerService.cs +++ b/Assets/Scripts/Player/PlayerService.cs @@ -1,4 +1,4 @@ -using Command.Actions; +using Command.Commands; using Command.Main; namespace Command.Player @@ -65,8 +65,6 @@ private void SetActivePlayer() public void OnPlayerTurnCompleted() => StartNextTurn(); - public void PerformAction(ActionType actionSelected, UnitController targetUnit) => GameService.Instance.ActionService.GetActionByType(actionSelected).PerformAction(activePlayer.GetUnitByID(ActiveUnitID), targetUnit); - public void PlayerDied(PlayerController deadPlayer) { int winnerId; @@ -77,6 +75,21 @@ public void PlayerDied(PlayerController deadPlayer) winnerId = player1.PlayerID; GameService.Instance.UIService.ShowBattleEndUI(winnerId); + GameService.Instance.CommandInvoker.SetReplayCommandStack(); + } + + public void ProcessUnitCommand(UnitCommand commandToProcess) + { + SetUnitReferences(commandToProcess); + GetPlayerById(commandToProcess.commandData.ActorPlayerID).ProcessUnitCommand(commandToProcess); + } + + private void SetUnitReferences(UnitCommand commandToProcess) + { + var actorUnit = GetPlayerById(commandToProcess.commandData.ActorPlayerID).GetUnitByID(commandToProcess.commandData.ActorUnitID); + var targetUnit = GetPlayerById(commandToProcess.commandData.TargetPlayerID).GetUnitByID(commandToProcess.commandData.TargetUnitID); + commandToProcess.SetActorUnit(actorUnit); + commandToProcess.SetTargetUnit(targetUnit); } private PlayerController GetPlayerById(int playerId) diff --git a/Assets/Scripts/Player/Unit/UnitController.cs b/Assets/Scripts/Player/Unit/UnitController.cs index 863dc14f..e8a4c7a9 100644 --- a/Assets/Scripts/Player/Unit/UnitController.cs +++ b/Assets/Scripts/Player/Unit/UnitController.cs @@ -1,6 +1,6 @@ using UnityEngine; using Command.Main; -using Command.Actions; +using Command.Commands; using System.Collections; using System; using Object = UnityEngine.Object; @@ -91,19 +91,19 @@ private void UnitDied() unitView.PlayAnimation(UnitAnimations.DEATH); } - public void PlayBattleAnimation(ActionType actionType, Vector3 battlePosition, Action callback) + public void PlayBattleAnimation(CommandType commandType, Vector3 battlePosition, Action callback) { GameService.Instance.UIService.ResetBattleBackgroundOverlay(); - MoveToBattlePosition(battlePosition, callback, true, actionType); + MoveToBattlePosition(battlePosition, callback, true, commandType); } - private void MoveToBattlePosition(Vector3 battlePosition, Action callback = null, bool shouldPlayActionAnimation = true, ActionType actionTypeToExecute = ActionType.None) + private void MoveToBattlePosition(Vector3 battlePosition, Action callback = null, bool shouldPlayActionAnimation = true, CommandType commandTypeToExecute = CommandType.None) { float moveTime = Vector3.Distance(unitView.transform.position, battlePosition) / unitScriptableObject.MovementSpeed; - unitView.StartCoroutine(MoveToPositionOverTime(battlePosition, moveTime, callback, shouldPlayActionAnimation, actionTypeToExecute)); + unitView.StartCoroutine(MoveToPositionOverTime(battlePosition, moveTime, callback, shouldPlayActionAnimation, commandTypeToExecute)); } - private IEnumerator MoveToPositionOverTime(Vector3 targetPosition, float time, Action callback, bool shouldPlayActionAnimation, ActionType actionTypeToExecute) + private IEnumerator MoveToPositionOverTime(Vector3 targetPosition, float time, Action callback, bool shouldPlayActionAnimation, CommandType actionTypeToExecute) { float elapsedTime = 0; Vector3 startingPosition = unitView.transform.position; @@ -124,9 +124,9 @@ private IEnumerator MoveToPositionOverTime(Vector3 targetPosition, float time, A callback.Invoke(); } - private void PlayActionAnimation(ActionType actionType) + private void PlayActionAnimation(CommandType actionType) { - if (actionType == ActionType.None) + if (actionType == CommandType.None) return; if (actionType == unitScriptableObject.executableCommands[0]) @@ -147,12 +147,18 @@ public void OnActionExecuted() public void ResetStats() => CurrentPower = unitScriptableObject.Power; - public void Revive() => SetAliveState(UnitAliveState.ALIVE); + public void Revive() + { + SetAliveState(UnitAliveState.ALIVE); + unitView.PlayAnimation(UnitAnimations.IDLE); + } public void Destroy() => UnityEngine.Object.Destroy(unitView.gameObject); public void ResetUnitIndicator() => unitView.SetUnitIndicator(false); + public void ProcessUnitCommand(UnitCommand commandToProcess) => GameService.Instance.CommandInvoker.ProcessCommand(commandToProcess); + public Vector3 GetEnemyPosition() { if (Owner.PlayerID == 1) diff --git a/Assets/Scripts/Player/Unit/UnitScriptableObject.cs b/Assets/Scripts/Player/Unit/UnitScriptableObject.cs index 3c0b6305..4bb5aeab 100644 --- a/Assets/Scripts/Player/Unit/UnitScriptableObject.cs +++ b/Assets/Scripts/Player/Unit/UnitScriptableObject.cs @@ -1,4 +1,4 @@ -using Command.Actions; +using Command.Commands; using System.Collections.Generic; using UnityEngine; @@ -12,7 +12,7 @@ public class UnitScriptableObject : ScriptableObject public UnitView UnitPrefab; public int MaxHealth; public int Power; - public List executableCommands; + public List executableCommands; public Vector3 EnemyBattlePositionOffset; public float MovementSpeed; } diff --git a/Assets/Scripts/Replay.meta b/Assets/Scripts/Replay.meta new file mode 100644 index 00000000..1cecf593 --- /dev/null +++ b/Assets/Scripts/Replay.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 77de5fc2182f49e4b7ef70b74862cc50 +timeCreated: 1711705685 \ No newline at end of file diff --git a/Assets/Scripts/Replay/ReplayService.cs b/Assets/Scripts/Replay/ReplayService.cs new file mode 100644 index 00000000..fc5180ed --- /dev/null +++ b/Assets/Scripts/Replay/ReplayService.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Command.Commands; +using Command.Main; +using UnityEngine; + +namespace Replay +{ + public class ReplayService + { + private const int waitTime = 1000; + private Stack replayCommandStack; + + public ReplayState ReplayState { get; private set; } + + public ReplayService() => SetReplayState(ReplayState.DEACTIVE); + + public void SetReplayState(ReplayState newState) => ReplayState = newState; + + public void SetCommandStack(Stack commandStack) => + replayCommandStack = new Stack(commandStack); + + public void ExecuteNext() + { + if (replayCommandStack.Count > 0) + { + WaitReplay(); + } + } + + private async void WaitReplay() + { + await Task.Delay(waitTime); + GameService.Instance.ProcessUnitCommand(replayCommandStack.Pop()); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Replay/ReplayState.cs b/Assets/Scripts/Replay/ReplayState.cs new file mode 100644 index 00000000..a0d982ef --- /dev/null +++ b/Assets/Scripts/Replay/ReplayState.cs @@ -0,0 +1,8 @@ +namespace Replay +{ + public enum ReplayState + { + ACTIVE, + DEACTIVE + } +} \ No newline at end of file diff --git a/Assets/Scripts/UI/ActionSelectionUI/ActionButtonView.cs b/Assets/Scripts/UI/ActionSelectionUI/ActionButtonView.cs index f3016d06..69863dff 100644 --- a/Assets/Scripts/UI/ActionSelectionUI/ActionButtonView.cs +++ b/Assets/Scripts/UI/ActionSelectionUI/ActionButtonView.cs @@ -1,4 +1,4 @@ -using Command.Actions; +using Command.Commands; using TMPro; using UnityEngine; using UnityEngine.UI; @@ -9,7 +9,7 @@ public class ActionButtonView : MonoBehaviour { [SerializeField] private TextMeshProUGUI buttonText; private ActionSelectionUIController owner; - private ActionType actionType; + private CommandType actionType; private void Start() => GetComponent