From e6ed33440e1afadb3168673924910efd6750351c Mon Sep 17 00:00:00 2001
From: MuhamadAjiW <16521119@mahasiswa.itb.ac.id>
Date: Tue, 23 Apr 2024 01:18:39 +0700
Subject: [PATCH] feat: weapon switching, with a subpar structure but will do
 for now

---
 .../TestWeapon/TestWeaponData.asset           |   2 +-
 .../TestWeapon/TestWeaponProjectileData.asset |   6 +-
 .../Weapons/TestWeapon/TestWeaponModel.prefab |   2 +-
 .../PhysicsMaterial/Slippery.physicMaterial   |   8 +-
 .../Weapons/TestWeapon/TestWeapon.prefab      |   3 +-
 Assets/Scenes/SampleScene.unity               |  30 +++-
 ...ironmentConfig.cs => EnvironmentConfig.cs} |   6 +-
 ...nfig.cs.meta => EnvironmentConfig.cs.meta} |   0
 .../Scripts/Core/Entities/Mobs/EnemyEntity.cs |   6 +-
 .../Objects/Weapons/TestWeapon/TestWeapon.cs  |  13 +-
 .../Core/Objects/Weapons/WeaponObject.cs      |  20 +--
 Assets/Scripts/Core/Player/Player.cs          |   6 +-
 .../Core/Player/PlayerInputController.cs      |   6 +-
 .../Controller/AnimationController.cs         |   2 +-
 .../EntityObject/CombatantEntity.cs           |  33 ++++-
 .../BaseClasses/EntityObject/WorldEntity.cs   |   4 +-
 .../Scripts/Library/Enum/AttackObjectType.cs  |   6 -
 .../Library/Enum/AttackObjectType.cs.meta     |  11 --
 Assets/Scripts/Library/Interfaces/IArmed.cs   |   3 +
 Assets/Scripts/Library/Util/ObjectFactory.cs  | 130 ++++++++++--------
 20 files changed, 178 insertions(+), 119 deletions(-)
 rename Assets/Scripts/Config/{GameEnvironmentConfig.cs => EnvironmentConfig.cs} (82%)
 rename Assets/Scripts/Config/{GameEnvironmentConfig.cs.meta => EnvironmentConfig.cs.meta} (100%)
 delete mode 100644 Assets/Scripts/Library/Enum/AttackObjectType.cs
 delete mode 100644 Assets/Scripts/Library/Enum/AttackObjectType.cs.meta

diff --git a/Assets/Data/Weapon Data/TestWeapon/TestWeaponData.asset b/Assets/Data/Weapon Data/TestWeapon/TestWeaponData.asset
index 52188fd9..04df8115 100644
--- a/Assets/Data/Weapon Data/TestWeapon/TestWeaponData.asset	
+++ b/Assets/Data/Weapon Data/TestWeapon/TestWeaponData.asset	
@@ -14,6 +14,6 @@ MonoBehaviour:
   m_EditorClassIdentifier: 
   baseDamage: 10
   knockbackPower: 10
-  attackInterval: 0.5
+  attackInterval: 0.2
   alternateAttackInterval: 1
   model: {fileID: 6146631199650576833, guid: 50599534a77c7dd46b591a71fbb5feba, type: 3}
diff --git a/Assets/Data/Weapon Data/TestWeapon/TestWeaponProjectileData.asset b/Assets/Data/Weapon Data/TestWeapon/TestWeaponProjectileData.asset
index e67302fd..495ed41a 100644
--- a/Assets/Data/Weapon Data/TestWeapon/TestWeaponProjectileData.asset	
+++ b/Assets/Data/Weapon Data/TestWeapon/TestWeaponProjectileData.asset	
@@ -12,7 +12,7 @@ MonoBehaviour:
   m_Script: {fileID: 11500000, guid: 9eb73b2d49aa0a5439d5c9a15a3f49e0, type: 3}
   m_Name: TestWeaponProjectileData
   m_EditorClassIdentifier: 
-  speed: 0
-  travelDistance: 0
+  speed: 50
+  travelDistance: 10
   through: 0
-  model: {fileID: 0}
+  model: {fileID: 5003074370431539976, guid: 8c93d213036531f47a377ee7fd1e7877, type: 3}
diff --git a/Assets/Resources/Models/Weapons/TestWeapon/TestWeaponModel.prefab b/Assets/Resources/Models/Weapons/TestWeapon/TestWeaponModel.prefab
index 1f98c326..5a192af5 100644
--- a/Assets/Resources/Models/Weapons/TestWeapon/TestWeaponModel.prefab
+++ b/Assets/Resources/Models/Weapons/TestWeapon/TestWeaponModel.prefab
@@ -12,7 +12,7 @@ GameObject:
   - component: {fileID: 2791526420071666714}
   - component: {fileID: 1664417149787680797}
   - component: {fileID: 444274800546035912}
-  m_Layer: 8
+  m_Layer: 0
   m_Name: TestWeaponModel
   m_TagString: Untagged
   m_Icon: {fileID: 0}
diff --git a/Assets/Resources/PhysicsMaterial/Slippery.physicMaterial b/Assets/Resources/PhysicsMaterial/Slippery.physicMaterial
index e147072c..2b7c350f 100644
--- a/Assets/Resources/PhysicsMaterial/Slippery.physicMaterial
+++ b/Assets/Resources/PhysicsMaterial/Slippery.physicMaterial
@@ -7,8 +7,8 @@ PhysicMaterial:
   m_PrefabInstance: {fileID: 0}
   m_PrefabAsset: {fileID: 0}
   m_Name: Slippery
-  dynamicFriction: 0.6
-  staticFriction: 0.6
+  dynamicFriction: 0
+  staticFriction: 0
   bounciness: 0
-  frictionCombine: 0
-  bounceCombine: 0
+  frictionCombine: 1
+  bounceCombine: 1
diff --git a/Assets/Resources/Prefabs/Weapons/TestWeapon/TestWeapon.prefab b/Assets/Resources/Prefabs/Weapons/TestWeapon/TestWeapon.prefab
index 6e2b78e1..c7d6d573 100644
--- a/Assets/Resources/Prefabs/Weapons/TestWeapon/TestWeapon.prefab
+++ b/Assets/Resources/Prefabs/Weapons/TestWeapon/TestWeapon.prefab
@@ -10,7 +10,7 @@ GameObject:
   m_Component:
   - component: {fileID: 1050311400148833009}
   - component: {fileID: 5029868015402955001}
-  m_Layer: 8
+  m_Layer: 0
   m_Name: TestWeapon
   m_TagString: Untagged
   m_Icon: {fileID: 0}
@@ -45,6 +45,7 @@ MonoBehaviour:
   m_Script: {fileID: 11500000, guid: 68705b8ed948aae4d98ef6e87b6f6961, type: 3}
   m_Name: 
   m_EditorClassIdentifier: 
+  prefabPath: Prefabs/Weapons/TestWeapon/TestWeapon
   data: {fileID: 11400000, guid: 875c881f7a9ed2347a9d28ca2c18c4b5, type: 2}
   canAttack: 0
   fireRange: 10
diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity
index d4423856..fc666bc5 100644
--- a/Assets/Scenes/SampleScene.unity
+++ b/Assets/Scenes/SampleScene.unity
@@ -241,12 +241,18 @@ MonoBehaviour:
   m_Script: {fileID: 11500000, guid: bbd12f0cc12b22743998413b3f14b197, type: 3}
   m_Name: 
   m_EditorClassIdentifier: 
-  Id: 
+  id: 
   knockbackResistance: 1
   baseSpeed: 10
+  jumpForce: 5
+  groundLayers:
+    serializedVersion: 2
+    m_Bits: 1
   maxHealth: 100
   health: 100
+  damagedDelay: 1
   baseDamage: 10
+  weaponList: []
 --- !u!1 &239523005
 GameObject:
   m_ObjectHideFlags: 0
@@ -276,7 +282,7 @@ MonoBehaviour:
   m_Script: {fileID: 11500000, guid: 354f6ba1c1428a04da1f256d1da9f51e, type: 3}
   m_Name: 
   m_EditorClassIdentifier: 
-  player: {fileID: 0}
+  player: {fileID: 117855958}
   data: {fileID: 0}
 --- !u!4 &239523007
 Transform:
@@ -287,7 +293,7 @@ Transform:
   m_GameObject: {fileID: 239523005}
   serializedVersion: 2
   m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
-  m_LocalPosition: {x: -0.1930373, y: 0.8700184, z: -0.31220782}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
   m_LocalScale: {x: 1, y: 1, z: 1}
   m_ConstrainProportionsScale: 0
   m_Children:
@@ -435,7 +441,7 @@ BoxCollider:
   m_PrefabInstance: {fileID: 0}
   m_PrefabAsset: {fileID: 0}
   m_GameObject: {fileID: 576314395}
-  m_Material: {fileID: 0}
+  m_Material: {fileID: 13400000, guid: 6b36fb2e3a8a80643988a623d515cbcc, type: 2}
   m_IncludeLayers:
     serializedVersion: 2
     m_Bits: 0
@@ -1175,6 +1181,14 @@ PrefabInstance:
       propertyPath: m_LocalEulerAnglesHint.z
       value: 0
       objectReference: {fileID: 0}
+    - target: {fileID: 5029868015402955001, guid: 1a7698227caac3d429dceb8aa5056502, type: 3}
+      propertyPath: model
+      value: 
+      objectReference: {fileID: 0}
+    - target: {fileID: 5029868015402955001, guid: 1a7698227caac3d429dceb8aa5056502, type: 3}
+      propertyPath: weaponData
+      value: 
+      objectReference: {fileID: 11400000, guid: 875c881f7a9ed2347a9d28ca2c18c4b5, type: 2}
     - target: {fileID: 5240801910879785525, guid: 1a7698227caac3d429dceb8aa5056502, type: 3}
       propertyPath: m_Name
       value: TestWeapon
@@ -1315,6 +1329,10 @@ PrefabInstance:
     serializedVersion: 3
     m_TransformParent: {fileID: 1098815287}
     m_Modifications:
+    - target: {fileID: 4603107572195619152, guid: c98b222ded23bb24690e674886e5741a, type: 3}
+      propertyPath: m_Material
+      value: 
+      objectReference: {fileID: 13400000, guid: 6b36fb2e3a8a80643988a623d515cbcc, type: 2}
     - target: {fileID: 6541102688641435260, guid: c98b222ded23bb24690e674886e5741a, type: 3}
       propertyPath: m_Name
       value: TestInteractable
@@ -1359,6 +1377,10 @@ PrefabInstance:
       propertyPath: m_LocalEulerAnglesHint.z
       value: 0
       objectReference: {fileID: 0}
+    - target: {fileID: 8869483112752652203, guid: c98b222ded23bb24690e674886e5741a, type: 3}
+      propertyPath: m_Material
+      value: 
+      objectReference: {fileID: 13400000, guid: 6b36fb2e3a8a80643988a623d515cbcc, type: 2}
     m_RemovedComponents: []
     m_RemovedGameObjects: []
     m_AddedGameObjects: []
diff --git a/Assets/Scripts/Config/GameEnvironmentConfig.cs b/Assets/Scripts/Config/EnvironmentConfig.cs
similarity index 82%
rename from Assets/Scripts/Config/GameEnvironmentConfig.cs
rename to Assets/Scripts/Config/EnvironmentConfig.cs
index f8f02178..2f093d4c 100644
--- a/Assets/Scripts/Config/GameEnvironmentConfig.cs
+++ b/Assets/Scripts/Config/EnvironmentConfig.cs
@@ -1,5 +1,5 @@
 // Configs should only contain constants and static readonly classes
-public static class GameEnvironmentConfig{
+public static class EnvironmentConfig{
     // Tags
     public const string TAG_UNTAGGED = "Untagged";
     public const string TAG_PLAYER = "Player";
@@ -15,4 +15,8 @@ public static class GameEnvironmentConfig{
     public const string LAYER_ENEMY_ATTACK = "EnemyAttack";
     public const string LAYER_ENVIRONMENT_ATTACK = "EnvironmentAttack";
     public const string LAYER_COLLECTIBLE = "Collectible";
+
+    // Object Components
+    public const string OBJECT_WEAPON = "Weapon";
+    public const string OBJECT_MODEL = "Model";
 }
\ No newline at end of file
diff --git a/Assets/Scripts/Config/GameEnvironmentConfig.cs.meta b/Assets/Scripts/Config/EnvironmentConfig.cs.meta
similarity index 100%
rename from Assets/Scripts/Config/GameEnvironmentConfig.cs.meta
rename to Assets/Scripts/Config/EnvironmentConfig.cs.meta
diff --git a/Assets/Scripts/Core/Entities/Mobs/EnemyEntity.cs b/Assets/Scripts/Core/Entities/Mobs/EnemyEntity.cs
index 6008c0aa..9ffb4e15 100644
--- a/Assets/Scripts/Core/Entities/Mobs/EnemyEntity.cs
+++ b/Assets/Scripts/Core/Entities/Mobs/EnemyEntity.cs
@@ -1,11 +1,15 @@
 public abstract class EnemyEntity : CombatantEntity 
 {
+    // Set-Getters
+    public new string AttackLayerCode => EnvironmentConfig.LAYER_ENEMY_ATTACK;
+    public new float AttackMultiplier => GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].EnemyDamageMultiplier;
+
     // Functions
     new protected void Start()
     {
         base.Start();
         Health *= GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].EnemyHealthMultiplier;
         BaseDamage *= GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].EnemyDamageMultiplier;
-        tag = GameEnvironmentConfig.TAG_ENEMY;
+        tag = EnvironmentConfig.TAG_ENEMY;
     }
 }
diff --git a/Assets/Scripts/Core/Objects/Weapons/TestWeapon/TestWeapon.cs b/Assets/Scripts/Core/Objects/Weapons/TestWeapon/TestWeapon.cs
index 4720285b..25364a3d 100644
--- a/Assets/Scripts/Core/Objects/Weapons/TestWeapon/TestWeapon.cs
+++ b/Assets/Scripts/Core/Objects/Weapons/TestWeapon/TestWeapon.cs
@@ -3,13 +3,14 @@ using UnityEngine;
 public class TestWeapon : WeaponObject
 {
     // Constants
+    private static readonly string weaponPrefab = "Prefabs/Weapons/TestWeapon/TestWeapon";
     private static readonly string hitboxPrefab = "Prefabs/Weapons/TestWeapon/WeaponHitbox";
     private static readonly string projectilePrefab = "Prefabs/Weapons/TestWeapon/TestProjectile";
     
     // Attribute
-    [SerializeField] private float fireRange = 100;
-    [SerializeField] private float projectileSpeed = 100; 
-    private TestWeaponAnimationController animationController;
+    public float fireRange = 100;
+    public float projectileSpeed = 100; 
+    public TestWeaponAnimationController animationController;
 
     // Constructor
     protected new void Start()
@@ -25,7 +26,8 @@ public class TestWeapon : WeaponObject
             prefabPath: projectilePrefab,
             damage: MathUtils.CalculateDamage(bearer.BaseDamage, data.baseDamage),
             knockbackPower: data.knockbackPower / 4,
-            type: bearerType,
+            attackLayerCode: bearer.AttackLayerCode,
+            damageModifier: bearer.AttackMultiplier,
             position: transform.position,
             rotation: bearer.Orientation.rotation,
             knockbackOrigin: transform.position - (bearer.Orientation.forward * projectileSpeed),
@@ -47,7 +49,8 @@ public class TestWeapon : WeaponObject
             prefabPath: hitboxPrefab,
             damage: MathUtils.CalculateDamage(bearer.BaseDamage, data.baseDamage),
             knockbackPower: data.knockbackPower,
-            type: bearerType,
+            attackLayerCode: bearer.AttackLayerCode,
+            damageModifier: bearer.AttackMultiplier,
             knockbackOrigin: transform.position,
             parent: animationController.model,
             objectName: "TestWeapon Hitbox"
diff --git a/Assets/Scripts/Core/Objects/Weapons/WeaponObject.cs b/Assets/Scripts/Core/Objects/Weapons/WeaponObject.cs
index b6294063..46562480 100644
--- a/Assets/Scripts/Core/Objects/Weapons/WeaponObject.cs
+++ b/Assets/Scripts/Core/Objects/Weapons/WeaponObject.cs
@@ -4,11 +4,12 @@ using UnityEngine;
 
 public abstract class WeaponObject : MonoBehaviour 
 {
+
     // Attributes
+    public string prefabPath;
     public WeaponData data;
-    protected AttackObjectType bearerType;
     protected IArmed bearer;
-    [SerializeField] private bool canAttack;
+    private bool canAttack = true;
 
     // Events
     public event Action OnAttackEvent;
@@ -18,21 +19,6 @@ public abstract class WeaponObject : MonoBehaviour
     protected void Start()
     {
         bearer = GetComponentInParent<IArmed>();
-        
-        // Switch requires a constant, so can't use that here
-        if(bearer is Player)
-        {
-            bearerType = AttackObjectType.PLAYER;
-        }
-        else if(bearer is EnemyEntity)
-        {
-            bearerType = AttackObjectType.ENEMY;
-        } 
-        else
-        {
-            bearerType = AttackObjectType.ENVIRONMENT;
-        } 
-
         canAttack = true;
         OnAttackEvent += OnAttack;
         OnAlternateAttackEvent += OnAlternateAttack;
diff --git a/Assets/Scripts/Core/Player/Player.cs b/Assets/Scripts/Core/Player/Player.cs
index b559a55e..89d543c1 100644
--- a/Assets/Scripts/Core/Player/Player.cs
+++ b/Assets/Scripts/Core/Player/Player.cs
@@ -15,6 +15,10 @@ public class Player : PlayerEntity
     public PlayerStateController stateController;
     public PlayerStats stats;
 
+    // Set-Getters
+    public new string AttackLayerCode => EnvironmentConfig.LAYER_PLAYER;
+    public new float AttackMultiplier => GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].PlayerDamageMultiplier;
+
     // Constructor
     new void Start()
     {
@@ -33,7 +37,7 @@ public class Player : PlayerEntity
         {
             WeaponList.Add(weapon);
         }
-        SetWeapon(0);
+        EquipWeapon(0);
 
         GameController.instance.player = this;
     }
diff --git a/Assets/Scripts/Core/Player/PlayerInputController.cs b/Assets/Scripts/Core/Player/PlayerInputController.cs
index ec2edea6..afe5b3b5 100644
--- a/Assets/Scripts/Core/Player/PlayerInputController.cs
+++ b/Assets/Scripts/Core/Player/PlayerInputController.cs
@@ -34,20 +34,24 @@ public class PlayerInputController
             Debug.Log("Player is Attacking");
             if(player.Weapon == null)
             {
+                Debug.Log("Player does not have a weapon");
                 return;
             }
+            Debug.Log("Attacking using Weapon");
 
             player.Weapon.Attack();
+            (player.Weapon as TestWeapon).AlternateAttack();
         }
         else if(Input.GetKeyDown(GameInput.instance.attackAlternateButton))
         {
             Debug.Log("Player is Attacking (alternate)");
             if(player.Weapon == null)
             {
+                Debug.Log("Player does not have a weapon");
                 return;
             }
 
-            player.Weapon.AlternateAttack();
+            (player.Weapon as TestWeapon).AlternateAttack();
         }
         else if(Input.GetKeyDown(GameInput.instance.interactButton))
         {
diff --git a/Assets/Scripts/Library/BaseClasses/Controller/AnimationController.cs b/Assets/Scripts/Library/BaseClasses/Controller/AnimationController.cs
index 411af95c..aa119af6 100644
--- a/Assets/Scripts/Library/BaseClasses/Controller/AnimationController.cs
+++ b/Assets/Scripts/Library/BaseClasses/Controller/AnimationController.cs
@@ -10,7 +10,7 @@ public abstract class AnimationController
     // Constructor
     public AnimationController(MonoBehaviour animable)
     {
-        model = animable.transform.Find("Model");
+        model = animable.transform.Find(EnvironmentConfig.OBJECT_MODEL);
         animator = model.GetComponent<Animator>();
         meshRenderer = model.GetComponent<MeshRenderer>();
 
diff --git a/Assets/Scripts/Library/BaseClasses/EntityObject/CombatantEntity.cs b/Assets/Scripts/Library/BaseClasses/EntityObject/CombatantEntity.cs
index 4b3eebc5..a837c75c 100644
--- a/Assets/Scripts/Library/BaseClasses/EntityObject/CombatantEntity.cs
+++ b/Assets/Scripts/Library/BaseClasses/EntityObject/CombatantEntity.cs
@@ -1,11 +1,13 @@
 using System;
 using System.Collections.Generic;
+using System.Reflection;
 using UnityEngine;
 
 public class CombatantEntity : DamageableEntity, IArmed
 {
     // Attributes
-    [SerializeField] private float baseDamage;
+    [SerializeField] protected float baseDamage;
+    [SerializeField] protected Vector3 weaponLocation;
     public List<WeaponObject> weaponList = new();
     private int weaponIndex;
     
@@ -13,6 +15,9 @@ public class CombatantEntity : DamageableEntity, IArmed
     public List<WeaponObject> WeaponList => weaponList;
     public WeaponObject Weapon => weaponList.Count > 0? weaponList[WeaponIndex] : null;
     public Transform Orientation => transform;
+    public Vector3 WeaponLocation => weaponLocation;
+    public string AttackLayerCode => EnvironmentConfig.LAYER_ENVIRONMENT_ATTACK;
+    public float AttackMultiplier => 1f;
     public float BaseDamage 
     {
         get => baseDamage;
@@ -31,14 +36,38 @@ public class CombatantEntity : DamageableEntity, IArmed
         } 
     }
 
+
     // Functions
-    public void SetWeapon(int index)
+    // TODO: Review, consider using prefabs instead?
+    // Prefabs are easier to implement but much less extendable
+    public void EquipWeapon(int index)
     {
         if(weaponList.Count == 0)
         {
             return;
         }
+        Debug.Log($"Equipping weapon {WeaponIndex}");
+
+        UnequipWeapon();
 
         WeaponIndex = index;
+
+        WeaponObject weaponObject = ObjectFactory.CreateObject<WeaponObject>(
+            prefabPath: Weapon.prefabPath,
+            parent: transform, 
+            position: WeaponLocation,
+            objectName: EnvironmentConfig.OBJECT_WEAPON
+        );
+        weaponObject.gameObject.layer = LayerMask.NameToLayer(AttackLayerCode);
+        WeaponList[weaponIndex] = weaponObject;
+
+        Debug.Log(Weapon == null);
+    }
+
+    public void UnequipWeapon(){
+        foreach (WeaponObject weapon in GetComponentsInChildren<WeaponObject>())
+        {
+            Destroy(weapon.gameObject);
+        }
     }
 }
diff --git a/Assets/Scripts/Library/BaseClasses/EntityObject/WorldEntity.cs b/Assets/Scripts/Library/BaseClasses/EntityObject/WorldEntity.cs
index c0ed5fb7..7f518119 100644
--- a/Assets/Scripts/Library/BaseClasses/EntityObject/WorldEntity.cs
+++ b/Assets/Scripts/Library/BaseClasses/EntityObject/WorldEntity.cs
@@ -6,8 +6,8 @@ public class WorldEntity : WorldObject, IRigid
     [SerializeField] private float knockbackResistance;
     [SerializeField] private float baseSpeed;
     [SerializeField] private float jumpForce;
-    protected Vector3 groundDetectionSize; 
     [SerializeField] protected LayerMask groundLayers;
+    protected Vector3 groundDetectionSize; 
     protected new Rigidbody rigidbody;
     private bool grounded = false;
 
@@ -40,7 +40,7 @@ public class WorldEntity : WorldObject, IRigid
         {
             Debug.LogWarning("Rigid entity " + name + " does not have a rigidbody"); 
         }
-        groundLayers = LayerMask.GetMask(GameEnvironmentConfig.LAYER_DEFAULT);
+        groundLayers = LayerMask.GetMask(EnvironmentConfig.LAYER_DEFAULT);
     }
 
     // Functions
diff --git a/Assets/Scripts/Library/Enum/AttackObjectType.cs b/Assets/Scripts/Library/Enum/AttackObjectType.cs
deleted file mode 100644
index 103641da..00000000
--- a/Assets/Scripts/Library/Enum/AttackObjectType.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-public enum AttackObjectType 
-{
-    PLAYER,
-    ENEMY,
-    ENVIRONMENT
-}
diff --git a/Assets/Scripts/Library/Enum/AttackObjectType.cs.meta b/Assets/Scripts/Library/Enum/AttackObjectType.cs.meta
deleted file mode 100644
index a494c18c..00000000
--- a/Assets/Scripts/Library/Enum/AttackObjectType.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 26aa78311840dbc4d80cd73c43fe9bcf
-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 7752880a..5282e6a7 100644
--- a/Assets/Scripts/Library/Interfaces/IArmed.cs
+++ b/Assets/Scripts/Library/Interfaces/IArmed.cs
@@ -5,6 +5,9 @@ public interface IArmed
 {
     // Set-Getters
     public float BaseDamage { get; set; }
+    public string AttackLayerCode { get; }
+    public float AttackMultiplier { get; }
+    public Vector3 WeaponLocation { get; }
     public WeaponObject Weapon { get; }
     public Transform Orientation { get; }
 }
diff --git a/Assets/Scripts/Library/Util/ObjectFactory.cs b/Assets/Scripts/Library/Util/ObjectFactory.cs
index 8cb2285c..8760e029 100644
--- a/Assets/Scripts/Library/Util/ObjectFactory.cs
+++ b/Assets/Scripts/Library/Util/ObjectFactory.cs
@@ -26,6 +26,41 @@ public static class ObjectFactory
         return CreateObject(prefabObject, parent, position, scale, rotation, renderingOrder, objectName);
     }
 
+    public static GameObject CreateObject(
+        GameObject gameObject,
+        Transform parent = null,
+        Vector3? position = null,
+        Vector3? scale = null,
+        Quaternion? rotation = null,
+        int renderingOrder = 0,
+        string objectName = "Unnamed Object"
+    )
+    {
+        GameObject createdObject = parent == null?
+            GameObject.Instantiate(gameObject, ObjectManager.instance.transform) :
+            GameObject.Instantiate(gameObject, parent);
+
+        if(position != null)
+        {
+            createdObject.transform.position = position.Value;
+        }
+        if(rotation != null)
+        {
+            createdObject.transform.rotation *= rotation.Value;
+        }
+        if(scale != null)
+        {
+            createdObject.transform.localScale = Vector3.Scale(createdObject.transform.localScale, scale.Value);
+        }
+        if(createdObject.TryGetComponent<Renderer>(out var renderer))
+        {
+            renderer.sortingOrder = renderingOrder;
+        }
+        createdObject.name = objectName;
+
+        return createdObject;
+    }
+
     public static T CreateObject<T>(
         string prefabPath,
         Transform parent = null,
@@ -54,12 +89,41 @@ public static class ObjectFactory
         return UnityObject;
     }
 
+    public static T CreateObject<T>(
+        GameObject gameObject,
+        Transform parent = null,
+        Vector3? position = null,
+        Vector3? scale = null,
+        Quaternion? rotation = null,
+        int renderingOrder = 0,
+        string objectName = "Unnamed Object"
+    ) where T : MonoBehaviour 
+    {
+        GameObject prefabObject = CreateObject(
+            gameObject, 
+            parent == null? ObjectManager.instance.transform : parent, 
+            position, 
+            scale, 
+            rotation, 
+            renderingOrder, 
+            objectName
+        );
+
+        if(!prefabObject.TryGetComponent<T>(out var UnityObject))
+        {
+            Debug.LogError("Loaded gameobject is not a a valid type: " + gameObject.name);
+        }
+
+        return UnityObject;
+    }
+
     public static AttackObject CreateAttackObject(
         string prefabPath,
         float damage,
         float knockbackPower,
         Vector3 knockbackOrigin,
-        AttackObjectType type,
+        string attackLayerCode = EnvironmentConfig.LAYER_ENVIRONMENT_ATTACK,
+        float damageModifier = 0,
         Transform parent = null,
         Vector3? position = null,
         Vector3? scale = null,
@@ -81,24 +145,9 @@ public static class ObjectFactory
         attackObject.Damage = damage;
         attackObject.KnockbackPower = knockbackPower;
         attackObject.KnockbackOrigin = knockbackOrigin;
-
-        switch (type)
-        {
-            case AttackObjectType.PLAYER:
-                attackObject.gameObject.layer = LayerMask.NameToLayer(GameEnvironmentConfig.LAYER_PLAYER_ATTACK);
-                attackObject.Damage *= GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].PlayerDamageMultiplier;
-                break;
-            case AttackObjectType.ENEMY:
-                attackObject.gameObject.layer = LayerMask.NameToLayer(GameEnvironmentConfig.LAYER_ENEMY_ATTACK);
-                attackObject.Damage *= GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].EnemyDamageMultiplier;
-                break;
-            case AttackObjectType.ENVIRONMENT:
-                attackObject.gameObject.layer = LayerMask.NameToLayer(GameEnvironmentConfig.LAYER_ENVIRONMENT_ATTACK);
-                break;
-            default:
-                Debug.LogError("Invalid AttackObjectType set, please refer to enum AttackObjectType for valid types");
-                break;
-        }
+        attackObject.gameObject.layer = 
+        attackObject.gameObject.layer = LayerMask.NameToLayer(attackLayerCode);
+        attackObject.Damage *= damageModifier;
 
         return attackObject;
     }
@@ -108,7 +157,8 @@ public static class ObjectFactory
         float damage,
         float knockbackPower,
         Vector3 knockbackOrigin,
-        AttackObjectType type,
+        string attackLayerCode = EnvironmentConfig.LAYER_ENVIRONMENT_ATTACK,
+        float damageModifier = 0,
         Transform parent = null,
         Vector3? position = null,
         Vector3? scale = null,
@@ -122,7 +172,8 @@ public static class ObjectFactory
             damage, 
             knockbackPower, 
             knockbackOrigin, 
-            type, 
+            attackLayerCode, 
+            damageModifier,
             parent, 
             position, 
             scale, 
@@ -158,7 +209,7 @@ public static class ObjectFactory
             objectName
         );
 
-        collectible.gameObject.layer = LayerMask.NameToLayer(GameEnvironmentConfig.LAYER_COLLECTIBLE);
+        collectible.gameObject.layer = LayerMask.NameToLayer(EnvironmentConfig.LAYER_COLLECTIBLE);
         
         return collectible;
     }
@@ -191,41 +242,6 @@ public static class ObjectFactory
     }
 
     // Internal functions
-    private static GameObject CreateObject(
-        GameObject gameObject,
-        Transform parent = null,
-        Vector3? position = null,
-        Vector3? scale = null,
-        Quaternion? rotation = null,
-        int renderingOrder = 0,
-        string objectName = "Unnamed Object"
-    )
-    {
-        GameObject createdObject = parent == null?
-            GameObject.Instantiate(gameObject, ObjectManager.instance.transform) :
-            GameObject.Instantiate(gameObject, parent);
-
-        if(position != null)
-        {
-            createdObject.transform.position = position.Value;
-        }
-        if(rotation != null)
-        {
-            createdObject.transform.rotation *= rotation.Value;
-        }
-        if(scale != null)
-        {
-            createdObject.transform.localScale = Vector3.Scale(createdObject.transform.localScale, scale.Value);
-        }
-        if(createdObject.TryGetComponent<Renderer>(out var renderer))
-        {
-            renderer.sortingOrder = renderingOrder;
-        }
-        createdObject.name = objectName;
-
-        return createdObject;
-    }
-    
     private static IEnumerator DestroyWithDelay(GameObject gameObject, float delay)
     {
         yield return new WaitForSeconds(delay);
-- 
GitLab