From e63db9d42bf3d4de4f5dd7f41f130f97ec3fd72d Mon Sep 17 00:00:00 2001
From: MuhamadAjiW <16521119@mahasiswa.itb.ac.id>
Date: Thu, 18 Apr 2024 22:15:04 +0700
Subject: [PATCH] feat: removed jumping, improved data modularity

---
 Assets/Resources.meta                         |  8 ++
 Assets/{ => Resources}/Prefabs.meta           |  2 +-
 Assets/Scenes/SampleScene.unity               | 92 +++++++++++++++++--
 Assets/Scripts/Config/EnvironmentConfig.cs    |  4 -
 Assets/Scripts/Config/GameConfig.cs           |  6 +-
 .../Scripts/Config/GameEnvironmentConfig.cs   |  8 ++
 ....cs.meta => GameEnvironmentConfig.cs.meta} |  0
 .../Entities/Mobs/AccompaniableEnemyEntity.cs |  7 ++
 .../Mobs/AccompaniableEnemyEntity.cs.meta     | 11 +++
 .../Scripts/Core/Entities/Mobs/Dummy/Dummy.cs |  3 +
 .../Mobs/Dummy/DummyStateController.cs        |  5 +
 .../Scripts/Core/Entities/Mobs/EnemyEntity.cs |  9 ++
 ...nemyObject.cs.meta => EnemyEntity.cs.meta} |  0
 .../Scripts/Core/Entities/Mobs/EnemyObject.cs |  0
 Assets/Scripts/Core/Game/Data.meta            |  8 ++
 Assets/Scripts/Core/Game/Data/GameControls.cs | 14 +++
 .../Core/Game/Data/GameControls.cs.meta       | 11 +++
 .../{GameData.cs => Data/GameSaveData.cs}     | 15 +--
 .../GameSaveData.cs.meta}                     |  0
 .../Scripts/Core/Game/GameCameraController.cs | 17 ++--
 Assets/Scripts/Core/Game/GameController.cs    | 13 +--
 .../Scripts/Core/Game/GameStateController.cs  | 63 +++++--------
 .../Core/Objects/Weapons/TestWeapon.cs        |  7 ++
 .../Core/Objects/Weapons/TestWeapon.cs.meta   | 11 +++
 Assets/Scripts/Core/Player/Player.cs          | 15 ++-
 .../Core/Player/PlayerAnimationController.cs  |  4 +-
 .../Core/Player/PlayerAttackController.cs     | 19 ++++
 .../Player/PlayerAttackController.cs.meta     | 11 +++
 .../Core/Player/PlayerMovementController.cs   |  8 +-
 .../Core/Player/PlayerStateController.cs      | 22 +----
 Assets/Scripts/Core/Player/PlayerStats.cs     | 17 +---
 .../BaseClasses/AccompaniableCombatant.cs     |  7 ++
 .../AccompaniableCombatant.cs.meta            | 11 +++
 .../Library/BaseClasses/AttackHitbox.cs       |  3 +-
 .../Scripts/Library/BaseClasses/Combatant.cs  | 10 +-
 .../Scripts/Library/BaseClasses/Companions.cs |  7 ++
 .../Library/BaseClasses/Companions.cs.meta    | 11 +++
 .../BaseClasses/Entity-Object/AttackEntity.cs |  4 +-
 .../BaseClasses/Entity-Object/AttackObject.cs |  6 +-
 .../Entity-Object/DamageableEntity.cs         | 14 +--
 .../Entity-Object/DamageableObject.cs         | 14 +--
 .../BaseClasses/Entity-Object/RigidEntity.cs  | 15 ++-
 .../BaseClasses/EntityStateController.meta    |  8 ++
 .../DamageableEntityStateController.cs        | 48 ++++++++++
 .../DamageableEntityStateController.cs.meta   | 11 +++
 .../EntityStateController.cs                  | 14 +++
 .../EntityStateController.cs.meta}            |  0
 .../Library/BaseClasses/StateController.cs    | 14 ---
 .../Library/BaseClasses/WeaponObject.cs       | 14 ++-
 .../CameraBehaviour/CameraBehaviour.cs        |  2 +-
 .../CameraBehaviour/CameraFollowObject.cs     |  2 +-
 .../Library/CameraBehaviour/CameraStatic.cs   |  2 +-
 .../Library/DataTypes/DifficultyData.cs       |  2 +-
 .../Library/Enum/CameraBehaviourType.cs       |  2 +-
 Assets/Scripts/Library/Enum/DifficultyType.cs |  2 +-
 Assets/Scripts/Library/Enum/EntityState.cs    |  3 -
 Assets/Scripts/Library/Enum/GameEventType.cs  |  2 +-
 Assets/Scripts/Library/Enum/GameState.cs      |  1 -
 .../Library/Enum/StackChangeEventType.cs      |  2 +-
 Assets/Scripts/Library/Events/GameEvent.cs    |  2 +-
 .../Library/Events/GameStateChangeEvent.cs    |  5 +-
 .../Library/Events/StackChangeEvent.cs        |  2 +-
 .../Library/Interfaces/IAccompanied.cs        |  5 +
 .../Library/Interfaces/IAccompanied.cs.meta   | 11 +++
 Assets/Scripts/Library/Interfaces/IArmed.cs   |  2 +-
 .../Scripts/Library/Interfaces/ICutscene.cs   |  2 +-
 .../Scripts/Library/Interfaces/IDamageable.cs |  6 +-
 .../Scripts/Library/Interfaces/IDamaging.cs   |  2 +-
 Assets/Scripts/Library/Interfaces/IMenu.cs    |  2 +-
 Assets/Scripts/Library/Interfaces/IRigid.cs   |  1 +
 Assets/Scripts/Library/Util/MathUtil.cs       |  7 +-
 Assets/Scripts/Library/Util/ObjectFactory.cs  |  2 +-
 ProjectSettings/TagManager.asset              |  3 +-
 73 files changed, 500 insertions(+), 193 deletions(-)
 create mode 100644 Assets/Resources.meta
 rename Assets/{ => Resources}/Prefabs.meta (77%)
 delete mode 100644 Assets/Scripts/Config/EnvironmentConfig.cs
 create mode 100644 Assets/Scripts/Config/GameEnvironmentConfig.cs
 rename Assets/Scripts/Config/{EnvironmentConfig.cs.meta => GameEnvironmentConfig.cs.meta} (100%)
 create mode 100644 Assets/Scripts/Core/Entities/Mobs/AccompaniableEnemyEntity.cs
 create mode 100644 Assets/Scripts/Core/Entities/Mobs/AccompaniableEnemyEntity.cs.meta
 create mode 100644 Assets/Scripts/Core/Entities/Mobs/EnemyEntity.cs
 rename Assets/Scripts/Core/Entities/Mobs/{EnemyObject.cs.meta => EnemyEntity.cs.meta} (100%)
 delete mode 100644 Assets/Scripts/Core/Entities/Mobs/EnemyObject.cs
 create mode 100644 Assets/Scripts/Core/Game/Data.meta
 create mode 100644 Assets/Scripts/Core/Game/Data/GameControls.cs
 create mode 100644 Assets/Scripts/Core/Game/Data/GameControls.cs.meta
 rename Assets/Scripts/Core/Game/{GameData.cs => Data/GameSaveData.cs} (50%)
 rename Assets/Scripts/Core/Game/{GameData.cs.meta => Data/GameSaveData.cs.meta} (100%)
 create mode 100644 Assets/Scripts/Core/Objects/Weapons/TestWeapon.cs
 create mode 100644 Assets/Scripts/Core/Objects/Weapons/TestWeapon.cs.meta
 create mode 100644 Assets/Scripts/Core/Player/PlayerAttackController.cs
 create mode 100644 Assets/Scripts/Core/Player/PlayerAttackController.cs.meta
 create mode 100644 Assets/Scripts/Library/BaseClasses/AccompaniableCombatant.cs
 create mode 100644 Assets/Scripts/Library/BaseClasses/AccompaniableCombatant.cs.meta
 create mode 100644 Assets/Scripts/Library/BaseClasses/Companions.cs
 create mode 100644 Assets/Scripts/Library/BaseClasses/Companions.cs.meta
 create mode 100644 Assets/Scripts/Library/BaseClasses/EntityStateController.meta
 create mode 100644 Assets/Scripts/Library/BaseClasses/EntityStateController/DamageableEntityStateController.cs
 create mode 100644 Assets/Scripts/Library/BaseClasses/EntityStateController/DamageableEntityStateController.cs.meta
 create mode 100644 Assets/Scripts/Library/BaseClasses/EntityStateController/EntityStateController.cs
 rename Assets/Scripts/Library/BaseClasses/{StateController.cs.meta => EntityStateController/EntityStateController.cs.meta} (100%)
 delete mode 100644 Assets/Scripts/Library/BaseClasses/StateController.cs
 create mode 100644 Assets/Scripts/Library/Interfaces/IAccompanied.cs
 create mode 100644 Assets/Scripts/Library/Interfaces/IAccompanied.cs.meta

diff --git a/Assets/Resources.meta b/Assets/Resources.meta
new file mode 100644
index 00000000..3886a8ab
--- /dev/null
+++ b/Assets/Resources.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 780ca0a004a37ad4da79df2418a084a3
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Prefabs.meta b/Assets/Resources/Prefabs.meta
similarity index 77%
rename from Assets/Prefabs.meta
rename to Assets/Resources/Prefabs.meta
index 4b405960..94e07611 100644
--- a/Assets/Prefabs.meta
+++ b/Assets/Resources/Prefabs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 6e7f2ce1b93e054448a962070d372d0d
+guid: 72da1ceec4d574b4cb94df3c670dac08
 folderAsset: yes
 DefaultImporter:
   externalObjects: {}
diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity
index 2a92e186..f05fbfc0 100644
--- a/Assets/Scenes/SampleScene.unity
+++ b/Assets/Scenes/SampleScene.unity
@@ -123,6 +123,52 @@ NavMeshSettings:
     debug:
       m_Flags: 0
   m_NavMeshData: {fileID: 0}
+--- !u!1 &6125821
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 6125823}
+  - component: {fileID: 6125822}
+  m_Layer: 0
+  m_Name: GameControls
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &6125822
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6125821}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 277e6d37ad3220543a05009070b3a2b8, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  backButton: 27
+  attackButton: 122
+--- !u!4 &6125823
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 6125821}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
 --- !u!1 &117855954
 GameObject:
   m_ObjectHideFlags: 0
@@ -222,6 +268,7 @@ MonoBehaviour:
   knockbackResistance: 0
   maxHealth: 0
   health: 0
+  baseDamage: 0
 --- !u!1 &239523005
 GameObject:
   m_ObjectHideFlags: 0
@@ -251,6 +298,8 @@ MonoBehaviour:
   m_Script: {fileID: 11500000, guid: 354f6ba1c1428a04da1f256d1da9f51e, type: 3}
   m_Name: 
   m_EditorClassIdentifier: 
+  player: {fileID: 0}
+  data: {fileID: 0}
 --- !u!4 &239523007
 Transform:
   m_ObjectHideFlags: 0
@@ -325,7 +374,7 @@ GameObject:
   - component: {fileID: 521822200}
   - component: {fileID: 521822199}
   m_Layer: 0
-  m_Name: GameData
+  m_Name: GameSaveData
   m_TagString: Untagged
   m_Icon: {fileID: 0}
   m_NavMeshLayer: 0
@@ -343,6 +392,7 @@ MonoBehaviour:
   m_Script: {fileID: 11500000, guid: 1e57b66e76eeafd4bb8ea101ee7598ae, type: 3}
   m_Name: 
   m_EditorClassIdentifier: 
+  difficulty: 1
 --- !u!4 &521822200
 Transform:
   m_ObjectHideFlags: 0
@@ -372,7 +422,7 @@ GameObject:
   - component: {fileID: 675919036}
   m_Layer: 0
   m_Name: Model
-  m_TagString: Model
+  m_TagString: Untagged
   m_Icon: {fileID: 0}
   m_NavMeshLayer: 0
   m_StaticEditorFlags: 0
@@ -462,7 +512,7 @@ MeshFilter:
   m_PrefabInstance: {fileID: 0}
   m_PrefabAsset: {fileID: 0}
   m_GameObject: {fileID: 675919034}
-  m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
+  m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
 --- !u!1 &705507993
 GameObject:
   m_ObjectHideFlags: 0
@@ -779,9 +829,10 @@ GameObject:
   serializedVersion: 6
   m_Component:
   - component: {fileID: 1093326602}
+  - component: {fileID: 1093326603}
   m_Layer: 0
-  m_Name: Weapon
-  m_TagString: Weapon
+  m_Name: TestWeapon
+  m_TagString: Untagged
   m_Icon: {fileID: 0}
   m_NavMeshLayer: 0
   m_StaticEditorFlags: 0
@@ -803,6 +854,19 @@ Transform:
   - {fileID: 2105743491}
   m_Father: {fileID: 117855957}
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1093326603
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1093326601}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 68705b8ed948aae4d98ef6e87b6f6961, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  baseDamage: 10
 --- !u!1 &1098815286
 GameObject:
   m_ObjectHideFlags: 0
@@ -1048,8 +1112,9 @@ GameObject:
   m_Component:
   - component: {fileID: 2105743491}
   - component: {fileID: 2105743492}
+  - component: {fileID: 2105743493}
   m_Layer: 0
-  m_Name: Hitbox
+  m_Name: WeaponHitbox
   m_TagString: Untagged
   m_Icon: {fileID: 0}
   m_NavMeshLayer: 0
@@ -1091,9 +1156,24 @@ BoxCollider:
   serializedVersion: 3
   m_Size: {x: 1, y: 1, z: 1}
   m_Center: {x: 0, y: 0, z: 0}
+--- !u!114 &2105743493
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2105743490}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: d305728f9c09ee84d861e4d2a18c0be0, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  damage: 10
+  knockbackPower: 500
 --- !u!1660057539 &9223372036854775807
 SceneRoots:
   m_ObjectHideFlags: 0
   m_Roots:
   - {fileID: 239523007}
   - {fileID: 521822200}
+  - {fileID: 6125823}
diff --git a/Assets/Scripts/Config/EnvironmentConfig.cs b/Assets/Scripts/Config/EnvironmentConfig.cs
deleted file mode 100644
index 20f5a33f..00000000
--- a/Assets/Scripts/Config/EnvironmentConfig.cs
+++ /dev/null
@@ -1,4 +0,0 @@
-public static class EnvironmentConfig{
-    // Tags
-    public static string GROUND_TAG = "Ground";
-}
\ No newline at end of file
diff --git a/Assets/Scripts/Config/GameConfig.cs b/Assets/Scripts/Config/GameConfig.cs
index 8c9270b8..60c7f44e 100644
--- a/Assets/Scripts/Config/GameConfig.cs
+++ b/Assets/Scripts/Config/GameConfig.cs
@@ -1,8 +1,12 @@
 using System.Collections.Generic;
 
 public static class GameConfig{
+    // Default damaged state delay value
+    public static float DAMAGED_DELAY_DURATION = 1.0f;
+
     // Movement lerp constants
     public static float MOVEMENT_SMOOTHING = 0.14f;
+    public static float MOVEMENT_SMOOTHING_JUMP_SNAPSHOT = 0.14f;
     public static float ROTATION_SMOOTHING = 720;
 
     // Difficulty multipliers
@@ -24,7 +28,7 @@ public static class GameConfig{
         PlayerDamageMultiplier = 0.5f,
         PlayerHealthMultiplier = 0.5f,
     };
-    
+
     public static Dictionary<DifficultyType, DifficultyData> DIFFICULTY_MODIFIERS = new(){
         { DifficultyType.EASY, EasyData},
         { DifficultyType.NORMAL, MediumData},
diff --git a/Assets/Scripts/Config/GameEnvironmentConfig.cs b/Assets/Scripts/Config/GameEnvironmentConfig.cs
new file mode 100644
index 00000000..f7088ea7
--- /dev/null
+++ b/Assets/Scripts/Config/GameEnvironmentConfig.cs
@@ -0,0 +1,8 @@
+public static class GameEnvironmentConfig{
+    // Tags
+    public static string UNTAGGED_TAG = "Untagged";
+    public static string PLAYER_TAG = "Player";
+    public static string ENEMY_TAG = "Enemy";
+    public static string COLLECTIBLES_TAG = "Collectibles";
+    public static string GROUND_TAG = "Ground";
+}
\ No newline at end of file
diff --git a/Assets/Scripts/Config/EnvironmentConfig.cs.meta b/Assets/Scripts/Config/GameEnvironmentConfig.cs.meta
similarity index 100%
rename from Assets/Scripts/Config/EnvironmentConfig.cs.meta
rename to Assets/Scripts/Config/GameEnvironmentConfig.cs.meta
diff --git a/Assets/Scripts/Core/Entities/Mobs/AccompaniableEnemyEntity.cs b/Assets/Scripts/Core/Entities/Mobs/AccompaniableEnemyEntity.cs
new file mode 100644
index 00000000..c94d7533
--- /dev/null
+++ b/Assets/Scripts/Core/Entities/Mobs/AccompaniableEnemyEntity.cs
@@ -0,0 +1,7 @@
+using System.Collections.Generic;
+
+public abstract class AccompaniableEnemyObject : EnemyEntity, IAccompaniable{
+    // Attributes
+    private readonly List<Companions> companionList = new();    
+    public List<Companions> Companions => companionList;
+}
diff --git a/Assets/Scripts/Core/Entities/Mobs/AccompaniableEnemyEntity.cs.meta b/Assets/Scripts/Core/Entities/Mobs/AccompaniableEnemyEntity.cs.meta
new file mode 100644
index 00000000..2a9f879b
--- /dev/null
+++ b/Assets/Scripts/Core/Entities/Mobs/AccompaniableEnemyEntity.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e8f8664fc9280974c8995cf856525826
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Core/Entities/Mobs/Dummy/Dummy.cs b/Assets/Scripts/Core/Entities/Mobs/Dummy/Dummy.cs
index e69de29b..84a354a2 100644
--- a/Assets/Scripts/Core/Entities/Mobs/Dummy/Dummy.cs
+++ b/Assets/Scripts/Core/Entities/Mobs/Dummy/Dummy.cs
@@ -0,0 +1,3 @@
+public class Dummy : EnemyEntity{
+    
+}
\ No newline at end of file
diff --git a/Assets/Scripts/Core/Entities/Mobs/Dummy/DummyStateController.cs b/Assets/Scripts/Core/Entities/Mobs/Dummy/DummyStateController.cs
index e69de29b..e66250dd 100644
--- a/Assets/Scripts/Core/Entities/Mobs/Dummy/DummyStateController.cs
+++ b/Assets/Scripts/Core/Entities/Mobs/Dummy/DummyStateController.cs
@@ -0,0 +1,5 @@
+public class DummyStateController : EntityStateController{
+    public override int UpdateState(){
+        throw new System.NotImplementedException();
+    }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/Core/Entities/Mobs/EnemyEntity.cs b/Assets/Scripts/Core/Entities/Mobs/EnemyEntity.cs
new file mode 100644
index 00000000..b3727e74
--- /dev/null
+++ b/Assets/Scripts/Core/Entities/Mobs/EnemyEntity.cs
@@ -0,0 +1,9 @@
+public abstract class EnemyEntity : Combatant {
+    // Functions
+    new void Start(){
+        base.Start();
+        Health *= GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].EnemyHealthMultiplier;
+        BaseDamage *= GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].EnemyDamageMultiplier;
+        tag = GameEnvironmentConfig.ENEMY_TAG;
+    }
+}
diff --git a/Assets/Scripts/Core/Entities/Mobs/EnemyObject.cs.meta b/Assets/Scripts/Core/Entities/Mobs/EnemyEntity.cs.meta
similarity index 100%
rename from Assets/Scripts/Core/Entities/Mobs/EnemyObject.cs.meta
rename to Assets/Scripts/Core/Entities/Mobs/EnemyEntity.cs.meta
diff --git a/Assets/Scripts/Core/Entities/Mobs/EnemyObject.cs b/Assets/Scripts/Core/Entities/Mobs/EnemyObject.cs
deleted file mode 100644
index e69de29b..00000000
diff --git a/Assets/Scripts/Core/Game/Data.meta b/Assets/Scripts/Core/Game/Data.meta
new file mode 100644
index 00000000..26fc8ee5
--- /dev/null
+++ b/Assets/Scripts/Core/Game/Data.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 37b61c2c546ff8a42a03da536564d42e
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Core/Game/Data/GameControls.cs b/Assets/Scripts/Core/Game/Data/GameControls.cs
new file mode 100644
index 00000000..3e86ad3f
--- /dev/null
+++ b/Assets/Scripts/Core/Game/Data/GameControls.cs
@@ -0,0 +1,14 @@
+using UnityEngine;
+
+public class GameControls : MonoBehaviour {
+    // Attributes
+    public static GameControls instance;
+    public KeyCode backButton = KeyCode.Escape;
+    public KeyCode attackButton = KeyCode.Z;
+
+    // Constructor
+    private void Awake(){
+        instance = this;
+        DontDestroyOnLoad(gameObject);
+    }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/Core/Game/Data/GameControls.cs.meta b/Assets/Scripts/Core/Game/Data/GameControls.cs.meta
new file mode 100644
index 00000000..be4708d2
--- /dev/null
+++ b/Assets/Scripts/Core/Game/Data/GameControls.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 277e6d37ad3220543a05009070b3a2b8
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Core/Game/GameData.cs b/Assets/Scripts/Core/Game/Data/GameSaveData.cs
similarity index 50%
rename from Assets/Scripts/Core/Game/GameData.cs
rename to Assets/Scripts/Core/Game/Data/GameSaveData.cs
index 2bcb2f62..9bed0027 100644
--- a/Assets/Scripts/Core/Game/GameData.cs
+++ b/Assets/Scripts/Core/Game/Data/GameSaveData.cs
@@ -3,20 +3,15 @@ using System.Collections.Generic;
 using Unity.VisualScripting;
 using UnityEngine;
 
-public class GameData : MonoBehaviour {
+public class GameSaveData : MonoBehaviour {
     // Attributes
-    public static GameData instance;
+    public static GameSaveData instance;
+
+    public DifficultyType difficulty = DifficultyType.NORMAL;
 
-    public static DifficultyType difficulty = DifficultyType.NORMAL;
-    
     // Constructor
     private void Awake(){
         instance = this;
         DontDestroyOnLoad(gameObject);
     }
-
-    // Functions
-    public void Save(PlayerStats playerStats){
-    
-    }
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Core/Game/GameData.cs.meta b/Assets/Scripts/Core/Game/Data/GameSaveData.cs.meta
similarity index 100%
rename from Assets/Scripts/Core/Game/GameData.cs.meta
rename to Assets/Scripts/Core/Game/Data/GameSaveData.cs.meta
diff --git a/Assets/Scripts/Core/Game/GameCameraController.cs b/Assets/Scripts/Core/Game/GameCameraController.cs
index 147cb6cf..257868a3 100644
--- a/Assets/Scripts/Core/Game/GameCameraController.cs
+++ b/Assets/Scripts/Core/Game/GameCameraController.cs
@@ -30,17 +30,12 @@ public class GameCameraController {
     public void SetCameraBehaviour(CameraBehaviourType cameraBehaviourType){
         GameObject.Destroy(activeCamera.GetComponent<CameraBehaviour>());
 
-        switch (cameraBehaviourType){
-            case CameraBehaviourType.STATIC:
-                behaviour = activeCamera.AddComponent<CameraStatic>();                
-                break;
-            case CameraBehaviourType.FOLLOW:
-                behaviour = activeCamera.AddComponent<CameraFollowObject>();                
-                break;
-            
-            default:
-                throw new Exception("Invalid cameraBehaviourType set, please refer to enum CameraBehaviourType for valid types");
-        }
+        behaviour = cameraBehaviourType switch{
+            CameraBehaviourType.STATIC => activeCamera.AddComponent<CameraStatic>(),
+            CameraBehaviourType.FOLLOW => activeCamera.AddComponent<CameraFollowObject>(),
+            _ => throw new Exception("Invalid cameraBehaviourType set, please refer to enum CameraBehaviourType for valid types")
+        };
+
         behaviourType = cameraBehaviourType;
     }
 }
\ No newline at end of file
diff --git a/Assets/Scripts/Core/Game/GameController.cs b/Assets/Scripts/Core/Game/GameController.cs
index 8de3b00a..61234df2 100644
--- a/Assets/Scripts/Core/Game/GameController.cs
+++ b/Assets/Scripts/Core/Game/GameController.cs
@@ -4,9 +4,10 @@ using UnityEngine;
 public class GameController : MonoBehaviour {
     // Attributes
     public static GameController instance;
-    public static GameCameraController mainCamera;
-    public static GameStateController stateController;
-    public static GameData data;
+    public Player player;
+    public GameCameraController mainCamera;
+    public GameStateController stateController;
+    public GameSaveData data;
     public bool IsPaused => Time.timeScale == 0;
 
     // Constructor
@@ -14,13 +15,13 @@ public class GameController : MonoBehaviour {
         if(instance == null) instance = this;
         mainCamera = new GameCameraController(GetComponentInChildren<Camera>());
         stateController = new GameStateController();
-        data = GameData.instance;
+        data = GameSaveData.instance;
     }
 
     // Functions
     void Update(){
-         if(Input.GetKeyDown(KeyCode.Escape)){
+         if(Input.GetKeyDown(GameControls.instance.backButton)){
             stateController.HandleEscape();
          }
     }
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Core/Game/GameStateController.cs b/Assets/Scripts/Core/Game/GameStateController.cs
index 29bb07cb..2f735226 100644
--- a/Assets/Scripts/Core/Game/GameStateController.cs
+++ b/Assets/Scripts/Core/Game/GameStateController.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
 using Unity.VisualScripting;
 using UnityEngine;
 
-public class GameStateController {
+public class GameStateController{
     // Attributes
     private readonly Stack<GameState> gameStateStack = new();
     event GameStateChangeEvent OnGameStateChange;
-    event Action OnPaused;
+    event Action OnPausedEvent;
 
     // Constructor
     public GameStateController(){
@@ -17,29 +17,20 @@ public class GameStateController {
     }
 
     // Functions
-    private void LogGameStateStack(StackChangeEventArgs<GameState> e){
-        Debug.Log(e.EventType);
-        Debug.Log(gameStateStack);
+    private void LogGameStateStack(GameStateChangeArgs e){
+        Debug.Log(string.Format("GameState {0}; Current gamestate is {1}", e.EventType, e.NewGameState));
     }
 
     public void PushState(GameState gameState){
-        switch(gameState){
-            case GameState.PAUSED:
-                Time.timeScale = 0;
-                break;
-            case GameState.RUNNING:
-                Time.timeScale = 1;
-                break;
-            //TODO: Review cutscenes and menu behaviour
-            case GameState.CUTSCENE:
-                Time.timeScale = 0;
-                break;
-            case GameState.MENU:
-                Time.timeScale = 0;
-                break;
-            default:
-                throw new Exception("Invalid gameState pushed to GameStateController, please refer to enum GameState for valid states");
-        }
+        //TODO: Review cutscenes and menu behaviour
+        Time.timeScale = gameState switch{
+            GameState.PAUSED => 0,
+            GameState.RUNNING => 1,
+            GameState.CUTSCENE => 0,
+            GameState.MENU => 0,
+            _ => throw new Exception("Invalid gameState pushed to GameStateController, please refer to enum GameState for valid states"),
+        };
+
         gameStateStack.Push(gameState);
         OnGameStateChange?.Invoke(new GameStateChangeArgs(
             StackChangeEventType.PUSH,
@@ -51,21 +42,15 @@ public class GameStateController {
     public void PopState(){
         gameStateStack.Pop();
         GameState gameState = gameStateStack.Peek();
-        switch(gameState){
-            case GameState.PAUSED:
-                Time.timeScale = 0;
-                break;
-            case GameState.RUNNING:
-                Time.timeScale = 1;
-                break;
-            //TODO: Review cutscenes behaviour
-            case GameState.CUTSCENE:
-                Time.timeScale = 0;
-                break;
-            case GameState.MENU:
-                Time.timeScale = 0;
-                break;
-        }
+        //TODO: Review cutscenes behaviour
+        Time.timeScale = gameState switch{
+            GameState.PAUSED => 0,
+            GameState.RUNNING => 1,
+            GameState.CUTSCENE => 0,
+            GameState.MENU => 0,
+            _ => throw new Exception("Invalid gameState popped to GameStateController, please refer to enum GameState for valid states"),
+        };
+
         OnGameStateChange?.Invoke(new GameStateChangeArgs(
             StackChangeEventType.POP,
             gameStateStack.Count,
@@ -77,7 +62,7 @@ public class GameStateController {
         switch (gameStateStack.Peek()){
             case GameState.RUNNING:
                 PushState(GameState.PAUSED);
-                OnPaused?.Invoke();
+                OnPausedEvent?.Invoke();
                 return;
 
             case GameState.PAUSED:
@@ -90,4 +75,4 @@ public class GameStateController {
                 return;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Core/Objects/Weapons/TestWeapon.cs b/Assets/Scripts/Core/Objects/Weapons/TestWeapon.cs
new file mode 100644
index 00000000..36ba66a2
--- /dev/null
+++ b/Assets/Scripts/Core/Objects/Weapons/TestWeapon.cs
@@ -0,0 +1,7 @@
+using UnityEngine;
+
+public class TestWeapon : WeaponObject{
+    public override void Attack(){
+        Debug.Log("Attacking using a Test Weapon");
+    }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/Core/Objects/Weapons/TestWeapon.cs.meta b/Assets/Scripts/Core/Objects/Weapons/TestWeapon.cs.meta
new file mode 100644
index 00000000..eb0b2e71
--- /dev/null
+++ b/Assets/Scripts/Core/Objects/Weapons/TestWeapon.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 68705b8ed948aae4d98ef6e87b6f6961
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Core/Player/Player.cs b/Assets/Scripts/Core/Player/Player.cs
index 481a74e6..980be6f2 100644
--- a/Assets/Scripts/Core/Player/Player.cs
+++ b/Assets/Scripts/Core/Player/Player.cs
@@ -3,31 +3,38 @@ using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
-public class Player : Combatant {
+public class Player : AccompaniableCombatant {
     private PlayerAnimationController animationController;
     private PlayerMovementController movementController;
+    private PlayerAttackController attackController;
     public PlayerStateController stateController;
     public PlayerStats stats;
 
     new void Start(){
         base.Start();
-        Health *= GameConfig.DIFFICULTY_MODIFIERS[GameData.difficulty].PlayerHealthMultiplier;
-        BaseDamage *= GameConfig.DIFFICULTY_MODIFIERS[GameData.difficulty].PlayerDamageMultiplier;
+        Health *= GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].PlayerHealthMultiplier;
+        BaseDamage *= GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].PlayerDamageMultiplier;
 
+        Weapon = GetComponentInChildren<WeaponObject>();
         stateController = new PlayerStateController(this);
         movementController = new PlayerMovementController(this);
         animationController = new PlayerAnimationController(this);
+        attackController = new PlayerAttackController(this);
         stats = new PlayerStats(this);
+
+        GameController.instance.player = this;
     }
 
     new void Update(){
         base.Update();
+
+        attackController.HandleInputs();
     }
 
     new void FixedUpdate(){
         base.FixedUpdate();
 
-        stateController.DetectState();
+        stateController.UpdateState();
         movementController.HandleMovement();
     }
 }
diff --git a/Assets/Scripts/Core/Player/PlayerAnimationController.cs b/Assets/Scripts/Core/Player/PlayerAnimationController.cs
index 24bd42b5..29a37e14 100644
--- a/Assets/Scripts/Core/Player/PlayerAnimationController.cs
+++ b/Assets/Scripts/Core/Player/PlayerAnimationController.cs
@@ -7,7 +7,7 @@ public class PlayerAnimationController{
     private const string SPRINT_TRIGGER = "sprint_param"; 
     
     // Attributes
-    private Player player;
+    private readonly Player player;
     private PlayerStateController playerStateController;
     private Transform modelTransform;
     private Animator animator;
@@ -18,7 +18,7 @@ public class PlayerAnimationController{
         modelTransform = player.transform.Find("Model");
         animator = modelTransform.GetComponent<Animator>();
 
-        player.stateController.OnStateChange += Animate;
+        player.stateController.OnStateChangeEvent += Animate;
     }
 
     // Functions
diff --git a/Assets/Scripts/Core/Player/PlayerAttackController.cs b/Assets/Scripts/Core/Player/PlayerAttackController.cs
new file mode 100644
index 00000000..999fec22
--- /dev/null
+++ b/Assets/Scripts/Core/Player/PlayerAttackController.cs
@@ -0,0 +1,19 @@
+using UnityEngine;
+
+public class PlayerAttackController{
+    private readonly Player player;
+    
+    public PlayerAttackController(Player player){
+        this.player = player;
+    }
+
+    public void HandleInputs(){
+        if(Input.GetKeyDown(GameControls.instance.attackButton)){
+            Debug.Log("Player is attacking");
+            
+            if(player.Weapon == null) return;
+
+            player.Weapon.Attack();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/Core/Player/PlayerAttackController.cs.meta b/Assets/Scripts/Core/Player/PlayerAttackController.cs.meta
new file mode 100644
index 00000000..82d65179
--- /dev/null
+++ b/Assets/Scripts/Core/Player/PlayerAttackController.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 24d96e02bfd50214984282c944c8e741
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Core/Player/PlayerMovementController.cs b/Assets/Scripts/Core/Player/PlayerMovementController.cs
index 3e31d626..9cd5490f 100644
--- a/Assets/Scripts/Core/Player/PlayerMovementController.cs
+++ b/Assets/Scripts/Core/Player/PlayerMovementController.cs
@@ -3,7 +3,7 @@ using UnityEngine;
 
 public class PlayerMovementController{
     // Attributes
-    private Player player;
+    private readonly Player player;
 
     // Constructor
     public PlayerMovementController(Player player){
@@ -19,12 +19,12 @@ public class PlayerMovementController{
     }
 
     public void HandleMovement(){
-        float keyPressAD = Input.GetAxisRaw("Horizontal");
-        float keyPressWS = Input.GetAxisRaw("Vertical");
+        float keyPressX = Input.GetAxisRaw("Horizontal");
+        float keyPressZ = Input.GetAxisRaw("Vertical");
         Vector3 velocity = new(player.Rigidbody.velocity.x, player.Rigidbody.velocity.y, player.Rigidbody.velocity.z);
         Vector3 dampVelocity = Vector3.zero;
 
-        Vector3 inputVector = new(keyPressAD, 0, keyPressWS);
+        Vector3 inputVector = new(keyPressX, 0, keyPressZ);
         Vector3 modifierVector = inputVector.normalized * player.stats.MaxSpeed;
         velocity.x = modifierVector.x;
         velocity.z = modifierVector.z;
diff --git a/Assets/Scripts/Core/Player/PlayerStateController.cs b/Assets/Scripts/Core/Player/PlayerStateController.cs
index 4aeac915..c61b8764 100644
--- a/Assets/Scripts/Core/Player/PlayerStateController.cs
+++ b/Assets/Scripts/Core/Player/PlayerStateController.cs
@@ -1,21 +1,15 @@
 using UnityEngine;
 
-public class PlayerStateController : StateController{
+public class PlayerStateController : DamageableEntityStateController {
     // Attributes
-    private Player player;
+    private readonly Player player;
 
     // Contstructor
-    public PlayerStateController(Player player){
+    public PlayerStateController(Player player) : base(player){
         this.player = player;
     }
 
     // Functions
-    private bool DetectJumping(){
-        return !player.Grounded && player.Rigidbody.velocity.y > 0;
-    }
-    private bool DetectFalling(){
-        return !player.Grounded && player.Rigidbody.velocity.y < 0;
-    }
     private bool DetectWalking(){
         return Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0;
     }
@@ -23,16 +17,10 @@ public class PlayerStateController : StateController{
         return (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0) && Input.GetKey(KeyCode.LeftShift);
     }
 
-    public override int DetectState(){
+    public override int UpdateState(){
         int initialState = state;
 
-        if(DetectJumping()){
-            state = PlayerState.JUMPING;
-        }
-        else if(DetectFalling()){
-            state = PlayerState.FALLING;
-        }
-        else if(DetectSprinting()){
+        if(DetectSprinting()){
             state = PlayerState.SPRINTING;
         }
         else if(DetectWalking()){
diff --git a/Assets/Scripts/Core/Player/PlayerStats.cs b/Assets/Scripts/Core/Player/PlayerStats.cs
index 31a088cb..1c5305ba 100644
--- a/Assets/Scripts/Core/Player/PlayerStats.cs
+++ b/Assets/Scripts/Core/Player/PlayerStats.cs
@@ -3,10 +3,7 @@ using UnityEngine;
 public class PlayerStats {
     // Attributes
     private readonly Player player;
-    [SerializeField] public float walkSpeed = 10;
-    [SerializeField] public float sprintSpeed = 20;
-    [SerializeField] public float jumpForce = 600;
-    public float snapshotSpeed = 25;
+    public float sprintModifier = 1.5f;
     public float Health {
         get => player.Health;
         set => player.Health = value;
@@ -19,12 +16,9 @@ public class PlayerStats {
         get => player.BaseDamage;
         set => player.BaseDamage = value;
     }
-
     public float MaxSpeed => player.stateController.state switch{
-        PlayerState.WALKING => walkSpeed,
-        PlayerState.SPRINTING => sprintSpeed,
-        PlayerState.JUMPING => snapshotSpeed,
-        PlayerState.FALLING => snapshotSpeed,
+        PlayerState.WALKING => player.BaseSpeed,
+        PlayerState.SPRINTING => player.BaseSpeed * sprintModifier,
         _ => 0
     };
 
@@ -32,9 +26,4 @@ public class PlayerStats {
     public PlayerStats(Player player){
         this.player = player;
     }
-
-    // Functions
-    public void SaveStats(){
-        GameData.instance.Save(this);
-    }
 }
diff --git a/Assets/Scripts/Library/BaseClasses/AccompaniableCombatant.cs b/Assets/Scripts/Library/BaseClasses/AccompaniableCombatant.cs
new file mode 100644
index 00000000..17aed23a
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses/AccompaniableCombatant.cs
@@ -0,0 +1,7 @@
+using System.Collections.Generic;
+
+public class AccompaniableCombatant : Combatant, IAccompaniable{
+    // Attributes
+    private readonly List<Companions> companionList = new();    
+    public List<Companions> Companions => companionList;
+}
diff --git a/Assets/Scripts/Library/BaseClasses/AccompaniableCombatant.cs.meta b/Assets/Scripts/Library/BaseClasses/AccompaniableCombatant.cs.meta
new file mode 100644
index 00000000..b084917a
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses/AccompaniableCombatant.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 70ede02eebb60bf4f9f966141d3e789e
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/BaseClasses/AttackHitbox.cs b/Assets/Scripts/Library/BaseClasses/AttackHitbox.cs
index 51c85788..00b9bca2 100644
--- a/Assets/Scripts/Library/BaseClasses/AttackHitbox.cs
+++ b/Assets/Scripts/Library/BaseClasses/AttackHitbox.cs
@@ -2,8 +2,9 @@ using System;
 using UnityEngine;
 
 public class AttackHitbox : AttackObject{
+    // Functions
     void OnTriggerStay(Collider otherCollider){
         Debug.Log(string.Format("Collision in hitbox of {0} by {1}", transform.name, otherCollider.transform.name));
         Hit(otherCollider);
     }
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/BaseClasses/Combatant.cs b/Assets/Scripts/Library/BaseClasses/Combatant.cs
index d0d8786a..2e6e1785 100644
--- a/Assets/Scripts/Library/BaseClasses/Combatant.cs
+++ b/Assets/Scripts/Library/BaseClasses/Combatant.cs
@@ -2,6 +2,7 @@ using System;
 using UnityEngine;
 
 public class Combatant : DamageableEntity, IArmed{
+    // Attributes
     [SerializeField] private float baseDamage;
     private WeaponObject weapon;
     public float BaseDamage { 
@@ -10,6 +11,11 @@ public class Combatant : DamageableEntity, IArmed{
     }
     public WeaponObject Weapon { 
         get => weapon; 
-        set => Weapon = value;
+        set => weapon = value;
     }
-}
\ No newline at end of file
+
+    // TODO: Test then decide whether to destroy/disable previous weapon
+    public void SwapWeapon(WeaponObject newWeapon){
+        Weapon = newWeapon;
+    }
+}
diff --git a/Assets/Scripts/Library/BaseClasses/Companions.cs b/Assets/Scripts/Library/BaseClasses/Companions.cs
new file mode 100644
index 00000000..5cb61306
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses/Companions.cs
@@ -0,0 +1,7 @@
+using System;
+using UnityEngine;
+
+public abstract class Companions : DamageableEntity {
+    // Functions
+    public virtual void Act(){}
+}
diff --git a/Assets/Scripts/Library/BaseClasses/Companions.cs.meta b/Assets/Scripts/Library/BaseClasses/Companions.cs.meta
new file mode 100644
index 00000000..ea89e63d
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses/Companions.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b9d58cb51e6bf6d47a044752686fe646
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackEntity.cs b/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackEntity.cs
index 59c33cd1..a0d413b9 100644
--- a/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackEntity.cs
+++ b/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackEntity.cs
@@ -14,7 +14,7 @@ public class AttackEntity : RigidEntity, IDamaging, IKnockback{
         set => damage = value; 
     }
     public Vector3 KnockbackOrigin{get; set;}
-    public event Action OnDamage;
+    public event Action OnDamageEvent;
 
     // Functions
     public void Knockback(IRigid rigidObject){
@@ -29,7 +29,7 @@ public class AttackEntity : RigidEntity, IDamaging, IKnockback{
 
         if(damageableObject.Damageable){
             damageableObject.InflictDamage(Damage);
-            OnDamage?.Invoke();
+            OnDamageEvent?.Invoke();
 
             otherCollider.TryGetComponent<IRigid>(out var rigidObject);
             if(rigidObject != null) Knockback(rigidObject);
diff --git a/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackObject.cs b/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackObject.cs
index 9d849033..ae4645b8 100644
--- a/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackObject.cs
+++ b/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackObject.cs
@@ -14,7 +14,7 @@ public class AttackObject : MonoBehaviour, IDamaging, IKnockback{
         set => damage = value; 
     }
     public Vector3 KnockbackOrigin{get; set;}
-    public event Action OnDamage;
+    public event Action OnDamageEvent;
 
     // Functions
     public void Knockback(IRigid rigidObject){
@@ -29,10 +29,10 @@ public class AttackObject : MonoBehaviour, IDamaging, IKnockback{
 
         if(damageableObject.Damageable){
             damageableObject.InflictDamage(Damage);
-            OnDamage?.Invoke();
+            OnDamageEvent?.Invoke();
 
             otherCollider.TryGetComponent<IRigid>(out var rigidObject);
             if(rigidObject != null) Knockback(rigidObject);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/BaseClasses/Entity-Object/DamageableEntity.cs b/Assets/Scripts/Library/BaseClasses/Entity-Object/DamageableEntity.cs
index c46bd2e5..56f1d388 100644
--- a/Assets/Scripts/Library/BaseClasses/Entity-Object/DamageableEntity.cs
+++ b/Assets/Scripts/Library/BaseClasses/Entity-Object/DamageableEntity.cs
@@ -17,22 +17,22 @@ public class DamageableEntity : RigidEntity, IDamageable{
 
     public bool Damageable => !Dead;
     public bool Dead => health <= 0;
-    public event Action OnDeath;
-    public event Action OnDamaged;
-    public event Action OnHeal;
+    public event Action OnDeathEvent;
+    public event Action OnDamagedEvent;
+    public event Action OnHealEvent;
 
     // Functions
     public float InflictDamage(float damage){
         Health -= damage;
-        OnDamaged?.Invoke();
-        if(Dead) OnDeath?.Invoke();
+        OnDamagedEvent?.Invoke();
+        if(Dead) OnDeathEvent?.Invoke();
 
         return Health;
     }
 
     public float InflictHeal(float heal){
         Health += heal;
-        OnHeal?.Invoke();
+        OnHealEvent?.Invoke();
 
         return Health;
     }
@@ -48,4 +48,4 @@ public class DamageableEntity : RigidEntity, IDamageable{
     protected new void FixedUpdate(){
         base.FixedUpdate();
     }
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/BaseClasses/Entity-Object/DamageableObject.cs b/Assets/Scripts/Library/BaseClasses/Entity-Object/DamageableObject.cs
index 06229a54..9593c504 100644
--- a/Assets/Scripts/Library/BaseClasses/Entity-Object/DamageableObject.cs
+++ b/Assets/Scripts/Library/BaseClasses/Entity-Object/DamageableObject.cs
@@ -17,23 +17,23 @@ public class DamageableObject : MonoBehaviour, IDamageable{
 
     public bool Damageable => !Dead;
     public bool Dead => health <= 0;
-    public event Action OnDeath;
-    public event Action OnDamaged;
-    public event Action OnHeal;
+    public event Action OnDeathEvent;
+    public event Action OnDamagedEvent;
+    public event Action OnHealEvent;
 
     // Functions
     public float InflictDamage(float damage){
         Health -= damage;
-        OnDamaged?.Invoke();
-        if(Dead) OnDeath?.Invoke();
+        OnDamagedEvent?.Invoke();
+        if(Dead) OnDeathEvent?.Invoke();
 
         return Health;
     }
 
     public float InflictHeal(float heal){
         Health += heal;
-        OnHeal?.Invoke();
+        OnHealEvent?.Invoke();
 
         return Health;
     }
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/BaseClasses/Entity-Object/RigidEntity.cs b/Assets/Scripts/Library/BaseClasses/Entity-Object/RigidEntity.cs
index 54dbbd59..2b27abc8 100644
--- a/Assets/Scripts/Library/BaseClasses/Entity-Object/RigidEntity.cs
+++ b/Assets/Scripts/Library/BaseClasses/Entity-Object/RigidEntity.cs
@@ -3,25 +3,24 @@ using UnityEngine;
 public class RigidEntity : MonoBehaviour, IRigid {
     // Attributes
     [SerializeField] private float knockbackResistance;
-
-    // Readonly by others
+    [SerializeField] private float baseSpeed;
     private new Rigidbody rigidbody;
     private new Collider collider;
-
-    //TODO: grounded automatic detection
-    private bool grounded = true;
-
-
+    
     public Rigidbody Rigidbody => rigidbody;
     public Collider Collider => collider;
     public Vector3 Position => transform.position;
-    public bool Grounded => grounded;
     public float KnockbackResistance {
         get => knockbackResistance <= 0? 1 : knockbackResistance;
         set => knockbackResistance = value;
     }
+    public float BaseSpeed { 
+        get => baseSpeed; 
+        set => baseSpeed = value < 0? 0 : value; 
+    }
 
     // Constructor
+
     protected void Start(){
         rigidbody = GetComponent<Rigidbody>();
         collider = GetComponent<Collider>();
diff --git a/Assets/Scripts/Library/BaseClasses/EntityStateController.meta b/Assets/Scripts/Library/BaseClasses/EntityStateController.meta
new file mode 100644
index 00000000..21bc9243
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses/EntityStateController.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e003128a05a8b1c46aaa1f39942aef7b
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/BaseClasses/EntityStateController/DamageableEntityStateController.cs b/Assets/Scripts/Library/BaseClasses/EntityStateController/DamageableEntityStateController.cs
new file mode 100644
index 00000000..cccba9fe
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses/EntityStateController/DamageableEntityStateController.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public abstract class DamageableEntityStateController : EntityStateController {
+    // Attributes
+    private readonly DamageableEntity Entity;
+    private float damagedDelay;
+    protected bool damaged = false;
+    public bool Damaged => damaged;
+    public float DamagedDelay {
+        get => damagedDelay;
+        set => damagedDelay = value <= 0? GameConfig.DAMAGED_DELAY_DURATION : value;
+    }
+    public event Action OnDamageDelayOverEvent;
+
+    // Constructor
+    public DamageableEntityStateController(DamageableEntity entity, float delay = 0){
+        Entity = entity;
+        DamagedDelay =  delay;
+
+        OnDamageDelayOverEvent += OnDamageDelayOver;
+        entity.OnDamagedEvent += OnDamaged;
+    }
+
+    // Functions
+    private IEnumerator WaitDamagedDelay(){
+        if (!Entity.Dead){
+            yield return new WaitForSeconds(DamagedDelay);
+            damaged = false;
+            InvokeDamageDelayOver();
+        }
+    }
+
+    private void InvokeDamageDelayOver(){
+        OnDamageDelayOverEvent?.Invoke();
+    }
+
+    private void OnDamaged(){
+        damaged = true;
+        InvokeOnStateChanged();
+        Entity.StartCoroutine(WaitDamagedDelay());
+    }
+    private void OnDamageDelayOver(){
+        damaged = false;
+        InvokeOnStateChanged();
+    }
+}
diff --git a/Assets/Scripts/Library/BaseClasses/EntityStateController/DamageableEntityStateController.cs.meta b/Assets/Scripts/Library/BaseClasses/EntityStateController/DamageableEntityStateController.cs.meta
new file mode 100644
index 00000000..9020185e
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses/EntityStateController/DamageableEntityStateController.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0e4de83b38eceeb428f0a0e1d1b346a4
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/BaseClasses/EntityStateController/EntityStateController.cs b/Assets/Scripts/Library/BaseClasses/EntityStateController/EntityStateController.cs
new file mode 100644
index 00000000..6af8f29a
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses/EntityStateController/EntityStateController.cs
@@ -0,0 +1,14 @@
+using System;
+
+public abstract class EntityStateController{
+    // Attributes
+    public int state;
+    public event Action OnStateChangeEvent;
+
+    // Functions
+    protected void InvokeOnStateChanged(){
+        OnStateChangeEvent?.Invoke();
+    }
+
+    public abstract int UpdateState();
+}
diff --git a/Assets/Scripts/Library/BaseClasses/StateController.cs.meta b/Assets/Scripts/Library/BaseClasses/EntityStateController/EntityStateController.cs.meta
similarity index 100%
rename from Assets/Scripts/Library/BaseClasses/StateController.cs.meta
rename to Assets/Scripts/Library/BaseClasses/EntityStateController/EntityStateController.cs.meta
diff --git a/Assets/Scripts/Library/BaseClasses/StateController.cs b/Assets/Scripts/Library/BaseClasses/StateController.cs
deleted file mode 100644
index 224c2306..00000000
--- a/Assets/Scripts/Library/BaseClasses/StateController.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-
-public abstract class StateController{
-    // Attributes
-    public int state;
-    public event Action OnStateChange;
-
-    // Functions
-    protected void InvokeOnStateChanged(){
-        OnStateChange?.Invoke();
-    }
-
-    public abstract int DetectState();
-}
\ No newline at end of file
diff --git a/Assets/Scripts/Library/BaseClasses/WeaponObject.cs b/Assets/Scripts/Library/BaseClasses/WeaponObject.cs
index 8fd24421..44ea16ac 100644
--- a/Assets/Scripts/Library/BaseClasses/WeaponObject.cs
+++ b/Assets/Scripts/Library/BaseClasses/WeaponObject.cs
@@ -1,6 +1,14 @@
 using System;
 using UnityEngine;
 
-public abstract class WeaponObject : AttackObject{
-    public virtual void Attack(){}
-}
\ No newline at end of file
+public abstract class WeaponObject : MonoBehaviour {
+    // Attributes
+    [SerializeField] private float baseDamage;
+    public float BaseDamage { 
+        get => baseDamage;
+        set => baseDamage = value;
+    }
+
+    // Functions
+    public abstract void Attack();
+}
diff --git a/Assets/Scripts/Library/CameraBehaviour/CameraBehaviour.cs b/Assets/Scripts/Library/CameraBehaviour/CameraBehaviour.cs
index 44266adb..be1ead9e 100644
--- a/Assets/Scripts/Library/CameraBehaviour/CameraBehaviour.cs
+++ b/Assets/Scripts/Library/CameraBehaviour/CameraBehaviour.cs
@@ -1,3 +1,3 @@
 using UnityEngine;
 
-public abstract class CameraBehaviour : MonoBehaviour {}
\ No newline at end of file
+public abstract class CameraBehaviour : MonoBehaviour {}
diff --git a/Assets/Scripts/Library/CameraBehaviour/CameraFollowObject.cs b/Assets/Scripts/Library/CameraBehaviour/CameraFollowObject.cs
index 85c4660b..3ee12225 100644
--- a/Assets/Scripts/Library/CameraBehaviour/CameraFollowObject.cs
+++ b/Assets/Scripts/Library/CameraBehaviour/CameraFollowObject.cs
@@ -13,4 +13,4 @@ public class CameraFollowObject : CameraBehaviour {
         Vector3 newPosition = Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, followingTime);
         transform.position = newPosition;
     }
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/CameraBehaviour/CameraStatic.cs b/Assets/Scripts/Library/CameraBehaviour/CameraStatic.cs
index 7679352d..c88e88fa 100644
--- a/Assets/Scripts/Library/CameraBehaviour/CameraStatic.cs
+++ b/Assets/Scripts/Library/CameraBehaviour/CameraStatic.cs
@@ -1,3 +1,3 @@
 using UnityEngine;
 
-public class CameraStatic : CameraBehaviour {}
\ No newline at end of file
+public class CameraStatic : CameraBehaviour {}
diff --git a/Assets/Scripts/Library/DataTypes/DifficultyData.cs b/Assets/Scripts/Library/DataTypes/DifficultyData.cs
index 98f93776..a08615d6 100644
--- a/Assets/Scripts/Library/DataTypes/DifficultyData.cs
+++ b/Assets/Scripts/Library/DataTypes/DifficultyData.cs
@@ -3,4 +3,4 @@ public class DifficultyData{
     public float EnemyDamageMultiplier { get; set; }
     public float PlayerHealthMultiplier { get; set; }
     public float PlayerDamageMultiplier { get; set; }
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/Enum/CameraBehaviourType.cs b/Assets/Scripts/Library/Enum/CameraBehaviourType.cs
index ca9c21f9..f8c1d945 100644
--- a/Assets/Scripts/Library/Enum/CameraBehaviourType.cs
+++ b/Assets/Scripts/Library/Enum/CameraBehaviourType.cs
@@ -2,4 +2,4 @@ public enum CameraBehaviourType{
     NULL,
     STATIC,
     FOLLOW
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/Enum/DifficultyType.cs b/Assets/Scripts/Library/Enum/DifficultyType.cs
index b6759584..fe61e48f 100644
--- a/Assets/Scripts/Library/Enum/DifficultyType.cs
+++ b/Assets/Scripts/Library/Enum/DifficultyType.cs
@@ -2,4 +2,4 @@ public enum DifficultyType{
     EASY,
     NORMAL,
     HARD
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/Enum/EntityState.cs b/Assets/Scripts/Library/Enum/EntityState.cs
index fca3022c..bb503d33 100644
--- a/Assets/Scripts/Library/Enum/EntityState.cs
+++ b/Assets/Scripts/Library/Enum/EntityState.cs
@@ -3,7 +3,4 @@ public class EntityState {
     public const int IDLE = 1;
     public const int WALKING = 2;
     public const int SPRINTING = 4;
-    public const int JUMPING = 8;
-    public const int FALLING = 16;
 }
-
diff --git a/Assets/Scripts/Library/Enum/GameEventType.cs b/Assets/Scripts/Library/Enum/GameEventType.cs
index 0252b7bb..3c20968a 100644
--- a/Assets/Scripts/Library/Enum/GameEventType.cs
+++ b/Assets/Scripts/Library/Enum/GameEventType.cs
@@ -1,3 +1,3 @@
 public enum GameEventType{
     CHEAT
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/Enum/GameState.cs b/Assets/Scripts/Library/Enum/GameState.cs
index 0914c54b..c4de8375 100644
--- a/Assets/Scripts/Library/Enum/GameState.cs
+++ b/Assets/Scripts/Library/Enum/GameState.cs
@@ -5,4 +5,3 @@ public enum GameState {
     CUTSCENE,
     PAUSED
 }
-
diff --git a/Assets/Scripts/Library/Enum/StackChangeEventType.cs b/Assets/Scripts/Library/Enum/StackChangeEventType.cs
index 885d3c0b..97aa2a78 100644
--- a/Assets/Scripts/Library/Enum/StackChangeEventType.cs
+++ b/Assets/Scripts/Library/Enum/StackChangeEventType.cs
@@ -1,4 +1,4 @@
 public enum StackChangeEventType{
     PUSH,
     POP
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/Events/GameEvent.cs b/Assets/Scripts/Library/Events/GameEvent.cs
index 10086a83..18321f6c 100644
--- a/Assets/Scripts/Library/Events/GameEvent.cs
+++ b/Assets/Scripts/Library/Events/GameEvent.cs
@@ -7,4 +7,4 @@ public class GameEventArgs : EventArgs{
     }
 }
 
-public delegate void GameEvent(GameEventArgs e);
\ No newline at end of file
+public delegate void GameEvent(GameEventArgs e);
diff --git a/Assets/Scripts/Library/Events/GameStateChangeEvent.cs b/Assets/Scripts/Library/Events/GameStateChangeEvent.cs
index ead0a904..a485da40 100644
--- a/Assets/Scripts/Library/Events/GameStateChangeEvent.cs
+++ b/Assets/Scripts/Library/Events/GameStateChangeEvent.cs
@@ -1,5 +1,6 @@
 
 public class GameStateChangeArgs : StackChangeEventArgs<GameState>{
-    public GameStateChangeArgs(StackChangeEventType eventType, int index, GameState value) : base(eventType, index, value){}
+    public GameState NewGameState => Value;
+    public GameStateChangeArgs(StackChangeEventType eventType, int index, GameState NewGameState) : base(eventType, index, NewGameState){}
 }
-public delegate void GameStateChangeEvent(GameStateChangeArgs e);
\ No newline at end of file
+public delegate void GameStateChangeEvent(GameStateChangeArgs e);
diff --git a/Assets/Scripts/Library/Events/StackChangeEvent.cs b/Assets/Scripts/Library/Events/StackChangeEvent.cs
index acab9319..e0a968d6 100644
--- a/Assets/Scripts/Library/Events/StackChangeEvent.cs
+++ b/Assets/Scripts/Library/Events/StackChangeEvent.cs
@@ -12,4 +12,4 @@ public class StackChangeEventArgs<T> : EventArgs{
     }
 }
 
-public delegate void StackChangeEvent<T>(StackChangeEventArgs<T> e);
\ No newline at end of file
+public delegate void StackChangeEvent<T>(StackChangeEventArgs<T> e);
diff --git a/Assets/Scripts/Library/Interfaces/IAccompanied.cs b/Assets/Scripts/Library/Interfaces/IAccompanied.cs
new file mode 100644
index 00000000..826e6468
--- /dev/null
+++ b/Assets/Scripts/Library/Interfaces/IAccompanied.cs
@@ -0,0 +1,5 @@
+using System.Collections.Generic;
+
+public interface IAccompaniable{
+    public List<Companions> Companions { get; }
+}
diff --git a/Assets/Scripts/Library/Interfaces/IAccompanied.cs.meta b/Assets/Scripts/Library/Interfaces/IAccompanied.cs.meta
new file mode 100644
index 00000000..b4fc086e
--- /dev/null
+++ b/Assets/Scripts/Library/Interfaces/IAccompanied.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5cdf14b558c905544aa05b347efb17d1
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/Interfaces/IArmed.cs b/Assets/Scripts/Library/Interfaces/IArmed.cs
index 2c12e113..da5d4b8a 100644
--- a/Assets/Scripts/Library/Interfaces/IArmed.cs
+++ b/Assets/Scripts/Library/Interfaces/IArmed.cs
@@ -1,4 +1,4 @@
 public interface IArmed{
     public float BaseDamage { get; set; }
     public WeaponObject Weapon { get; set; }
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/Interfaces/ICutscene.cs b/Assets/Scripts/Library/Interfaces/ICutscene.cs
index f1d4b8d8..d6ee8703 100644
--- a/Assets/Scripts/Library/Interfaces/ICutscene.cs
+++ b/Assets/Scripts/Library/Interfaces/ICutscene.cs
@@ -1,3 +1,3 @@
 public interface ICutscene{
     public void Skip();
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/Interfaces/IDamageable.cs b/Assets/Scripts/Library/Interfaces/IDamageable.cs
index e1f07147..88d0696d 100644
--- a/Assets/Scripts/Library/Interfaces/IDamageable.cs
+++ b/Assets/Scripts/Library/Interfaces/IDamageable.cs
@@ -6,9 +6,9 @@ public interface IDamageable{
     bool Damageable {get;}
     bool Dead {get;}
 
-    event Action OnDeath;
-    event Action OnDamaged;
-    event Action OnHeal;
+    event Action OnDeathEvent;
+    event Action OnDamagedEvent;
+    event Action OnHealEvent;
 
     float InflictDamage(float damage);
     float InflictHeal(float heal);
diff --git a/Assets/Scripts/Library/Interfaces/IDamaging.cs b/Assets/Scripts/Library/Interfaces/IDamaging.cs
index 0ac5ec0b..5b11e94d 100644
--- a/Assets/Scripts/Library/Interfaces/IDamaging.cs
+++ b/Assets/Scripts/Library/Interfaces/IDamaging.cs
@@ -2,5 +2,5 @@ using System;
 
 public interface IDamaging{
     float Damage{get; set;}
-    event Action OnDamage;
+    event Action OnDamageEvent;
 }
diff --git a/Assets/Scripts/Library/Interfaces/IMenu.cs b/Assets/Scripts/Library/Interfaces/IMenu.cs
index 1ed68e7a..a03457e5 100644
--- a/Assets/Scripts/Library/Interfaces/IMenu.cs
+++ b/Assets/Scripts/Library/Interfaces/IMenu.cs
@@ -1,3 +1,3 @@
 public interface IMenu{
     public void Close();
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/Library/Interfaces/IRigid.cs b/Assets/Scripts/Library/Interfaces/IRigid.cs
index d06a4a07..7b092eb9 100644
--- a/Assets/Scripts/Library/Interfaces/IRigid.cs
+++ b/Assets/Scripts/Library/Interfaces/IRigid.cs
@@ -6,5 +6,6 @@ public interface IRigid{
     public Rigidbody Rigidbody {get;}
     public Collider Collider {get;}
     public Vector3 Position {get;}
+    public float BaseSpeed {get; set;}
     public float KnockbackResistance {get; set;}
 }
diff --git a/Assets/Scripts/Library/Util/MathUtil.cs b/Assets/Scripts/Library/Util/MathUtil.cs
index eaf1b1f5..ac69919f 100644
--- a/Assets/Scripts/Library/Util/MathUtil.cs
+++ b/Assets/Scripts/Library/Util/MathUtil.cs
@@ -5,4 +5,9 @@ public static class MathUtils{
         Vector3 direction = origin - target;
         return direction.normalized;
     }
-}
\ No newline at end of file
+
+    // TODO: Tweak, add an interesting equation, maybe?
+    public static float CalculateDamage(float characterDamageStat, float weaponDamageStat){
+        return characterDamageStat + weaponDamageStat;
+    }
+}
diff --git a/Assets/Scripts/Library/Util/ObjectFactory.cs b/Assets/Scripts/Library/Util/ObjectFactory.cs
index 6c8c5ff9..a1273336 100644
--- a/Assets/Scripts/Library/Util/ObjectFactory.cs
+++ b/Assets/Scripts/Library/Util/ObjectFactory.cs
@@ -1,3 +1,3 @@
 public static class ObjectFactory{
     
-}
\ No newline at end of file
+}
diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset
index 0c2d7425..01993968 100644
--- a/ProjectSettings/TagManager.asset
+++ b/ProjectSettings/TagManager.asset
@@ -4,8 +4,7 @@
 TagManager:
   serializedVersion: 2
   tags:
-  - Weapon
-  - Model
+  - Ground
   - Enemy
   - Collectibles
   layers:
-- 
GitLab