From 4abf5c79dba6606c649a5ea2fc956b0b57105913 Mon Sep 17 00:00:00 2001
From: MuhamadAjiW <16521119@mahasiswa.itb.ac.id>
Date: Thu, 18 Apr 2024 22:53:10 +0700
Subject: [PATCH] feat: object factory

---
 .../Scripts/Config/GameEnvironmentConfig.cs   | 14 +--
 .../BaseClasses/Entity-Object/AttackEntity.cs |  2 +-
 .../BaseClasses/Entity-Object/AttackObject.cs |  2 +-
 .../Library/BaseClasses/WeaponObject.cs       |  5 ++
 .../Scripts/Library/Enum/AttackObjectType.cs  |  4 +
 .../Library/Enum/AttackObjectType.cs.meta     | 11 +++
 Assets/Scripts/Library/Interfaces/IAttack.cs  |  1 +
 .../Library/Interfaces/IAttack.cs.meta        | 11 +++
 Assets/Scripts/Library/Util/ObjectFactory.cs  | 86 ++++++++++++++++++-
 9 files changed, 128 insertions(+), 8 deletions(-)
 create mode 100644 Assets/Scripts/Library/Enum/AttackObjectType.cs
 create mode 100644 Assets/Scripts/Library/Enum/AttackObjectType.cs.meta
 create mode 100644 Assets/Scripts/Library/Interfaces/IAttack.cs
 create mode 100644 Assets/Scripts/Library/Interfaces/IAttack.cs.meta

diff --git a/Assets/Scripts/Config/GameEnvironmentConfig.cs b/Assets/Scripts/Config/GameEnvironmentConfig.cs
index f7088ea7..301e610e 100644
--- a/Assets/Scripts/Config/GameEnvironmentConfig.cs
+++ b/Assets/Scripts/Config/GameEnvironmentConfig.cs
@@ -1,8 +1,12 @@
 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";
+    public static string TAG_UNTAGGED = "Untagged";
+    public static string TAG_PLAYER = "Player";
+    public static string TAG_ENEMY = "Enemy";
+    public static string TAG_COLLECTIBLES = "Collectibles";
+    public static string TAG_GROUND = "Ground";
+
+    // Layers
+    public static string LAYER_ENEMY_HITBOX = "EnemyHitbox";
+    public static string LAYER_PLAYER_HITBOX = "PlayerHitbox";
 }
\ No newline at end of file
diff --git a/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackEntity.cs b/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackEntity.cs
index a0d413b9..f7af7601 100644
--- a/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackEntity.cs
+++ b/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackEntity.cs
@@ -1,7 +1,7 @@
 using System;
 using UnityEngine;
 
-public class AttackEntity : RigidEntity, IDamaging, IKnockback{
+public class AttackEntity : RigidEntity, IAttack{
     // Attributes
     [SerializeField] private float damage;
     [SerializeField] private float knockbackPower;
diff --git a/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackObject.cs b/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackObject.cs
index ae4645b8..769e801f 100644
--- a/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackObject.cs
+++ b/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackObject.cs
@@ -1,7 +1,7 @@
 using System;
 using UnityEngine;
 
-public class AttackObject : MonoBehaviour, IDamaging, IKnockback{
+public class AttackObject : MonoBehaviour, IAttack{
     // Attributes
     [SerializeField] private float damage;
     [SerializeField] private float knockbackPower;
diff --git a/Assets/Scripts/Library/BaseClasses/WeaponObject.cs b/Assets/Scripts/Library/BaseClasses/WeaponObject.cs
index 44ea16ac..93c2da98 100644
--- a/Assets/Scripts/Library/BaseClasses/WeaponObject.cs
+++ b/Assets/Scripts/Library/BaseClasses/WeaponObject.cs
@@ -4,10 +4,15 @@ using UnityEngine;
 public abstract class WeaponObject : MonoBehaviour {
     // Attributes
     [SerializeField] private float baseDamage;
+    [SerializeField] private float baseKnockbackPower;
     public float BaseDamage { 
         get => baseDamage;
         set => baseDamage = value;
     }
+    public float BaseKnockbackPower { 
+        get => baseKnockbackPower;
+        set => BaseKnockbackPower = value;
+    }
 
     // Functions
     public abstract void Attack();
diff --git a/Assets/Scripts/Library/Enum/AttackObjectType.cs b/Assets/Scripts/Library/Enum/AttackObjectType.cs
new file mode 100644
index 00000000..72282390
--- /dev/null
+++ b/Assets/Scripts/Library/Enum/AttackObjectType.cs
@@ -0,0 +1,4 @@
+public enum AttackObjectType {
+    PLAYER,
+    ENEMY,
+}
diff --git a/Assets/Scripts/Library/Enum/AttackObjectType.cs.meta b/Assets/Scripts/Library/Enum/AttackObjectType.cs.meta
new file mode 100644
index 00000000..a494c18c
--- /dev/null
+++ b/Assets/Scripts/Library/Enum/AttackObjectType.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 26aa78311840dbc4d80cd73c43fe9bcf
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/Interfaces/IAttack.cs b/Assets/Scripts/Library/Interfaces/IAttack.cs
new file mode 100644
index 00000000..3076aabb
--- /dev/null
+++ b/Assets/Scripts/Library/Interfaces/IAttack.cs
@@ -0,0 +1 @@
+public interface IAttack : IDamaging, IKnockback{}
\ No newline at end of file
diff --git a/Assets/Scripts/Library/Interfaces/IAttack.cs.meta b/Assets/Scripts/Library/Interfaces/IAttack.cs.meta
new file mode 100644
index 00000000..032c39d8
--- /dev/null
+++ b/Assets/Scripts/Library/Interfaces/IAttack.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6b2ca8f784afa944a8843724ccc1ea6b
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/Util/ObjectFactory.cs b/Assets/Scripts/Library/Util/ObjectFactory.cs
index a1273336..f63ec360 100644
--- a/Assets/Scripts/Library/Util/ObjectFactory.cs
+++ b/Assets/Scripts/Library/Util/ObjectFactory.cs
@@ -1,3 +1,87 @@
+using System.Collections;
+using UnityEditor.Experimental.GraphView;
+using UnityEngine;
+
 public static class ObjectFactory{
-    
+    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 returnObject = parent == null? GameObject.Instantiate(gameObject) : GameObject.Instantiate(gameObject, parent);
+        if(position != null) returnObject.transform.position = position.Value;
+        if(rotation != null) returnObject.transform.rotation = rotation.Value;
+        if(scale != null) returnObject.transform.localScale = Vector3.Scale(returnObject.transform.localScale, scale.Value);
+        if(returnObject.TryGetComponent<Renderer>(out var renderer)) renderer.sortingOrder = renderingOrder;
+        returnObject.name = objectName;
+
+        return returnObject;
+    }
+
+    public static GameObject CreateObject(
+        string prefabPath,
+        Transform parent = null,
+        Vector3? position = null,
+        Vector3? scale = null,
+        Quaternion? rotation = null,
+        int renderingOrder = 0,
+        string objectName = "Unnamed Object"
+    ){
+        GameObject prefabObject = Resources.Load<GameObject>(prefabPath);
+        if(prefabObject == null) Debug.LogError("Prefab not found: " + prefabPath);
+        return CreateObject(prefabObject, parent, position, scale, rotation, renderingOrder, objectName);
+    }
+
+    public static GameObject CreateAttackObject(
+        string prefabPath,
+        float damage,
+        float knockbackPower,
+        AttackObjectType type,
+        Transform parent = null,
+        Vector3? position = null,
+        Vector3? scale = null,
+        Quaternion? rotation = null,
+        int renderingOrder = 0,
+        string objectName = "Unnamed Object"
+    ){
+        GameObject prefabObject = Resources.Load<GameObject>(prefabPath);
+        if(prefabObject == null) Debug.LogError("Prefab not found: " + prefabPath);
+        if(!prefabObject.TryGetComponent<IAttack>(out var attackObject)) Debug.LogError("Loaded prefab is not an IAttack: " + prefabPath);
+
+        attackObject.Damage = damage;
+        attackObject.KnockbackPower = knockbackPower;
+
+        switch (type){
+            case AttackObjectType.PLAYER:
+                prefabObject.layer = LayerMask.NameToLayer(GameEnvironmentConfig.LAYER_PLAYER_HITBOX);
+                attackObject.Damage *= GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].PlayerDamageMultiplier;
+                break;
+            case AttackObjectType.ENEMY:
+                prefabObject.layer = LayerMask.NameToLayer(GameEnvironmentConfig.LAYER_ENEMY_HITBOX);
+                attackObject.Damage *= GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].EnemyDamageMultiplier;
+                break;
+            default:
+                Debug.LogError("Invalid AttackObjectType set, please refer to enum AttackObjectType for valid types");
+                break;
+        }
+
+        return CreateObject(prefabObject, parent, position, scale, rotation, renderingOrder, objectName);
+    }
+
+    public static void Destroy(GameObject gameObject, float delay = 0){
+        if(gameObject == null){
+            Debug.LogError("Tried to destroy a null gameObject");
+            return;
+        }
+        GameController.instance.StartCoroutine(DestroyWithDelay(gameObject, delay));
+    }
+
+    private static IEnumerator DestroyWithDelay(GameObject gameObject, float delay){
+        yield return new WaitForSeconds(delay);
+        GameObject.Destroy(gameObject);
+    }
 }
-- 
GitLab