From 8f3a913b7e79b82c326929b87461c4f16486d6e1 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Fri, 11 Jul 2025 23:57:57 +0200 Subject: [PATCH] Add Inventory system with Inventory, InventorySlot, and StatModifierItem classes; update character attributes to include level and experience --- .../Sirenix/GlobalSerializationConfig.asset | 2 +- Assets/Prefabs/Projectile.prefab | 202 --------------- Assets/Prefabs/Projectile.prefab.meta | 7 - Assets/Scenes/main.unity | 230 +++++------------- Assets/Scripts/Inventory.meta | 3 + Assets/Scripts/Inventory/Inventory.cs | 66 +++++ Assets/Scripts/Inventory/Inventory.cs.meta | 3 + Assets/Scripts/Inventory/InventorySlot.cs | 13 + .../Scripts/Inventory/InventorySlot.cs.meta | 3 + Assets/Scripts/Inventory/StatModifierItem.cs | 19 ++ .../Inventory/StatModifierItem.cs.meta | 3 + Assets/Scripts/Inventory/WeaponItem.cs | 14 ++ Assets/Scripts/Inventory/WeaponItem.cs.meta | 3 + .../Scripts/Modifiers/PercentStatModifier.cs | 16 +- .../Systems/CharacterModifierManager.cs | 3 +- .../Systems/CharacterWeaponsManager.cs | 54 ++++ Assets/Scripts/Systems/InventoryManager.cs | 86 +++++++ .../Scripts/Systems/InventoryManager.cs.meta | 3 + Assets/Scripts/Weapons/Weapon.cs | 2 +- 19 files changed, 344 insertions(+), 388 deletions(-) delete mode 100644 Assets/Prefabs/Projectile.prefab delete mode 100644 Assets/Prefabs/Projectile.prefab.meta create mode 100644 Assets/Scripts/Inventory.meta create mode 100644 Assets/Scripts/Inventory/Inventory.cs create mode 100644 Assets/Scripts/Inventory/Inventory.cs.meta create mode 100644 Assets/Scripts/Inventory/InventorySlot.cs create mode 100644 Assets/Scripts/Inventory/InventorySlot.cs.meta create mode 100644 Assets/Scripts/Inventory/StatModifierItem.cs create mode 100644 Assets/Scripts/Inventory/StatModifierItem.cs.meta create mode 100644 Assets/Scripts/Inventory/WeaponItem.cs create mode 100644 Assets/Scripts/Inventory/WeaponItem.cs.meta create mode 100644 Assets/Scripts/Systems/InventoryManager.cs create mode 100644 Assets/Scripts/Systems/InventoryManager.cs.meta diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Config/Resources/Sirenix/GlobalSerializationConfig.asset b/Assets/Plugins/Sirenix/Odin Inspector/Config/Resources/Sirenix/GlobalSerializationConfig.asset index 0e48b68..185befc 100644 --- a/Assets/Plugins/Sirenix/Odin Inspector/Config/Resources/Sirenix/GlobalSerializationConfig.asset +++ b/Assets/Plugins/Sirenix/Odin Inspector/Config/Resources/Sirenix/GlobalSerializationConfig.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 1549551891, guid: 74721b9f0af448f5ae2e91102a1a5edd, type: 3} m_Name: GlobalSerializationConfig m_EditorClassIdentifier: - HideSerializationCautionaryMessage: 0 + HideSerializationCautionaryMessage: 1 HidePrefabCautionaryMessage: 0 HideOdinSerializeAttributeWarningMessages: 0 HideNonSerializedShowInInspectorWarningMessages: 0 diff --git a/Assets/Prefabs/Projectile.prefab b/Assets/Prefabs/Projectile.prefab deleted file mode 100644 index 5fccfd8..0000000 --- a/Assets/Prefabs/Projectile.prefab +++ /dev/null @@ -1,202 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &616788743636109406 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2013319700553645954} - - component: {fileID: 3496656179941343539} - m_Layer: 0 - m_Name: Circle - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &2013319700553645954 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 616788743636109406} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0.5, y: 0.5, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 4409070236958952652} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!212 &3496656179941343539 -SpriteRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 616788743636109406} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 0 - m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 0 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_Sprite: {fileID: -2413806693520163455, guid: a86470a33a6bf42c4b3595704624658b, type: 3} - m_Color: {r: 0.48584908, g: 0.8317809, b: 1, a: 1} - m_FlipX: 0 - m_FlipY: 0 - m_DrawMode: 0 - m_Size: {x: 1, y: 1} - m_AdaptiveModeThreshold: 0.5 - m_SpriteTileMode: 0 - m_WasSpriteAssigned: 1 - m_MaskInteraction: 0 - m_SpriteSortPoint: 0 ---- !u!1 &4455660151786346708 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4409070236958952652} - - component: {fileID: 4544380185088036541} - - component: {fileID: 4369473182176468481} - - component: {fileID: 6312981442736341380} - m_Layer: 0 - m_Name: Projectile - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &4409070236958952652 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4455660151786346708} - 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: - - {fileID: 2013319700553645954} - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!50 &4544380185088036541 -Rigidbody2D: - serializedVersion: 5 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4455660151786346708} - m_BodyType: 1 - m_Simulated: 1 - m_UseFullKinematicContacts: 0 - m_UseAutoMass: 0 - m_Mass: 1 - m_LinearDamping: 0 - m_AngularDamping: 0.05 - m_GravityScale: 0 - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_Interpolate: 0 - m_SleepingMode: 1 - m_CollisionDetection: 1 - m_Constraints: 4 ---- !u!58 &4369473182176468481 -CircleCollider2D: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4455660151786346708} - m_Enabled: 1 - serializedVersion: 3 - m_Density: 1 - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_ForceSendLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_ForceReceiveLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_ContactCaptureLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_CallbackLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_IsTrigger: 1 - m_UsedByEffector: 0 - m_CompositeOperation: 0 - m_CompositeOrder: 0 - m_Offset: {x: 0, y: 0} - m_Radius: 0.25 ---- !u!114 &6312981442736341380 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4455660151786346708} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 2d5fcee922b049d1b9db7b49711ce562, type: 3} - m_Name: - m_EditorClassIdentifier: - rb: {fileID: 4544380185088036541} - speed: 10 - lifeTime: 5 diff --git a/Assets/Prefabs/Projectile.prefab.meta b/Assets/Prefabs/Projectile.prefab.meta deleted file mode 100644 index e313e0d..0000000 --- a/Assets/Prefabs/Projectile.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 5c8ef2a68bd248674af5c1f68f7fc012 -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scenes/main.unity b/Assets/Scenes/main.unity index f80eedc..d36b77d 100644 --- a/Assets/Scenes/main.unity +++ b/Assets/Scenes/main.unity @@ -343,37 +343,6 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &523621672 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 523621673} - m_Layer: 6 - m_Name: Fire point - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &523621673 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 523621672} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0.569, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 1370658699} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &541374773 GameObject: m_ObjectHideFlags: 0 @@ -649,6 +618,10 @@ GameObject: - component: {fileID: 1261447608} - component: {fileID: 1261447607} - component: {fileID: 1261447606} + - component: {fileID: 1261447612} + - component: {fileID: 1261447611} + - component: {fileID: 1261447610} + - component: {fileID: 1261447609} m_Layer: 6 m_Name: Player m_TagString: Player @@ -751,6 +724,8 @@ MonoBehaviour: moveSpeed: 5 luck: 0 armor: 0 + level: 1 + experience: 0 damage: 1 rangedDamage: 1 meleeDamage: 1 @@ -770,7 +745,6 @@ Transform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 869793959} - - {fileID: 1636516555} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &1261447605 @@ -827,94 +801,63 @@ MonoBehaviour: m_EditorClassIdentifier: character: {fileID: 1261447603} initialHealth: 100 ---- !u!1 &1370658698 -GameObject: +--- !u!114 &1261447609 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1370658699} - - component: {fileID: 1370658700} - m_Layer: 6 - m_Name: Triangle - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1370658699 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1370658698} - 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: - - {fileID: 523621673} - m_Father: {fileID: 1636516555} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!212 &1370658700 -SpriteRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1370658698} + m_GameObject: {fileID: 1261447599} m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 0 - m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 0 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_Sprite: {fileID: 7482667652216324306, guid: 75f5f34dc1b5347e0b8351032682f224, type: 3} - m_Color: {r: 1, g: 0, b: 0.74674034, a: 1} - m_FlipX: 0 - m_FlipY: 0 - m_DrawMode: 0 - m_Size: {x: 1, y: 1} - m_AdaptiveModeThreshold: 0.5 - m_SpriteTileMode: 0 - m_WasSpriteAssigned: 1 - m_MaskInteraction: 0 - m_SpriteSortPoint: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 57782f9b469d49ab9f4ad6c6e1ddf844, type: 3} + m_Name: + m_EditorClassIdentifier: + inventory: {fileID: 1261447610} + characterModifierManager: {fileID: 1261447611} + characterWeaponsManager: {fileID: 1261447612} +--- !u!114 &1261447610 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1261447599} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9810b6967ffd4c3589464d687e982ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + weaponSlots: + - item: {fileID: 11400000, guid: 53811578f5e9423a584055fe920fa137, type: 2} + quantity: 1 + itemSlots: [] +--- !u!114 &1261447611 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1261447599} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1c860b1e8855495097022a829e769fcc, type: 3} + m_Name: + m_EditorClassIdentifier: + character: {fileID: 1261447603} +--- !u!114 &1261447612 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1261447599} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 359935f34c694f0dbd7cc727404824e9, type: 3} + m_Name: + m_EditorClassIdentifier: + character: {fileID: 1261447603} --- !u!1 &1414795143 GameObject: m_ObjectHideFlags: 0 @@ -1047,68 +990,15 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: e4ff53f671604189b15fac28115b2b70, type: 3} m_Name: m_EditorClassIdentifier: - character: {fileID: 2062887717} weaponStats: damage: 2 attackSpeed: 1 range: 0.1 damageType: 0 + character: {fileID: 2062887717} targetMask: serializedVersion: 2 m_Bits: 64 ---- !u!1 &1636516554 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1636516555} - - component: {fileID: 1636516556} - m_Layer: 6 - m_Name: Weapon - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1636516555 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1636516554} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: -0.7071068, w: 0.7071068} - m_LocalPosition: {x: 0.593, y: -0.024, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1370658699} - m_Father: {fileID: 1261447604} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: -90} ---- !u!114 &1636516556 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1636516554} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fd9cdb55272f45ab9c60a948a56e01f5, type: 3} - m_Name: - m_EditorClassIdentifier: - character: {fileID: 1261447603} - weaponStats: - damage: 3 - attackSpeed: 2 - range: 0 - damageType: 1 - projectilePrefab: {fileID: 4455660151786346708, guid: 5c8ef2a68bd248674af5c1f68f7fc012, type: 3} - firePoint: {fileID: 523621673} --- !u!1 &2062887715 GameObject: m_ObjectHideFlags: 0 @@ -1164,6 +1054,8 @@ MonoBehaviour: moveSpeed: 5 luck: 0 armor: 0 + level: 1 + experience: 0 damage: 1 rangedDamage: 1 meleeDamage: 1 diff --git a/Assets/Scripts/Inventory.meta b/Assets/Scripts/Inventory.meta new file mode 100644 index 0000000..a89bb0a --- /dev/null +++ b/Assets/Scripts/Inventory.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 845fc46be00c4d5896b8794c59b19bfa +timeCreated: 1752268724 \ No newline at end of file diff --git a/Assets/Scripts/Inventory/Inventory.cs b/Assets/Scripts/Inventory/Inventory.cs new file mode 100644 index 0000000..c3e7658 --- /dev/null +++ b/Assets/Scripts/Inventory/Inventory.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using Sirenix.Serialization; +using UnityEngine; + +namespace Inventory +{ + public class Inventory : MonoBehaviour + { + [OdinSerialize, SerializeField] private List weaponSlots = new(); + [OdinSerialize, SerializeField] private List itemSlots = new(); + + public IReadOnlyList WeaponSlots => weaponSlots.AsReadOnly(); + public IReadOnlyList ItemSlots => itemSlots.AsReadOnly(); + + public void AddWeapon(WeaponItem weaponItem) + { + foreach (var slot in weaponSlots) + { + if (slot.item == weaponItem) return; + } + + weaponSlots.Add(new InventorySlot { item = weaponItem, quantity = 1 }); + } + + public void AddItem(ScriptableObject item) + { + foreach (var slot in itemSlots) + { + if (slot.item != item) continue; + + slot.quantity++; + return; + } + + itemSlots.Add(new InventorySlot { item = item, quantity = 1 }); + } + + public void RemoveWeapon(WeaponItem weaponItem) + { + for (var i = 0; i < weaponSlots.Count; i++) + { + if (weaponSlots[i].item != weaponItem) continue; + + if (--weaponSlots[i].quantity <= 0) + { + weaponSlots.RemoveAt(i); + } + return; + } + } + + public void RemoveItem(ScriptableObject item) + { + for (var i = 0; i < itemSlots.Count; i++) + { + if (itemSlots[i].item != item) continue; + + if (--itemSlots[i].quantity <= 0) + { + itemSlots.RemoveAt(i); + } + return; + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Inventory/Inventory.cs.meta b/Assets/Scripts/Inventory/Inventory.cs.meta new file mode 100644 index 0000000..3e14d29 --- /dev/null +++ b/Assets/Scripts/Inventory/Inventory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9810b6967ffd4c3589464d687e982ee6 +timeCreated: 1752268911 \ No newline at end of file diff --git a/Assets/Scripts/Inventory/InventorySlot.cs b/Assets/Scripts/Inventory/InventorySlot.cs new file mode 100644 index 0000000..ff41d65 --- /dev/null +++ b/Assets/Scripts/Inventory/InventorySlot.cs @@ -0,0 +1,13 @@ +using System; +using Sirenix.Serialization; +using UnityEngine; + +namespace Inventory +{ + [Serializable] + public class InventorySlot + { + [OdinSerialize] public ScriptableObject item; + [OdinSerialize] public int quantity; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Inventory/InventorySlot.cs.meta b/Assets/Scripts/Inventory/InventorySlot.cs.meta new file mode 100644 index 0000000..f4ec1b0 --- /dev/null +++ b/Assets/Scripts/Inventory/InventorySlot.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 88a6fde0304145ba9f9cdd1b2782e363 +timeCreated: 1752268731 \ No newline at end of file diff --git a/Assets/Scripts/Inventory/StatModifierItem.cs b/Assets/Scripts/Inventory/StatModifierItem.cs new file mode 100644 index 0000000..4693378 --- /dev/null +++ b/Assets/Scripts/Inventory/StatModifierItem.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using Interfaces; +using Sirenix.OdinInspector; +using Sirenix.Serialization; +using UnityEngine; + +namespace Inventory +{ + [CreateAssetMenu(menuName = "Game/Item/StatModifierItem")] + public class StatModifierItem : SerializedScriptableObject + { + public string itemName; + [TextArea] public string description; + public Sprite icon; + + public List cures = new(); + public List curses = new(); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Inventory/StatModifierItem.cs.meta b/Assets/Scripts/Inventory/StatModifierItem.cs.meta new file mode 100644 index 0000000..ced37e7 --- /dev/null +++ b/Assets/Scripts/Inventory/StatModifierItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c437a5565f39495281bf1dd14dd6ba40 +timeCreated: 1752268788 \ No newline at end of file diff --git a/Assets/Scripts/Inventory/WeaponItem.cs b/Assets/Scripts/Inventory/WeaponItem.cs new file mode 100644 index 0000000..eb95c37 --- /dev/null +++ b/Assets/Scripts/Inventory/WeaponItem.cs @@ -0,0 +1,14 @@ +using Sirenix.Serialization; +using UnityEngine; + +namespace Inventory +{ + [CreateAssetMenu(menuName = "Game/Item/WeaponItem")] + public class WeaponItem : ScriptableObject + { + [OdinSerialize] public string weaponName; + [OdinSerialize, TextArea] public string description; + [OdinSerialize] public GameObject prefab; + [OdinSerialize] public Sprite icon; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Inventory/WeaponItem.cs.meta b/Assets/Scripts/Inventory/WeaponItem.cs.meta new file mode 100644 index 0000000..fd7d050 --- /dev/null +++ b/Assets/Scripts/Inventory/WeaponItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: efa44a330e8343c08e3af638d466c118 +timeCreated: 1752268856 \ No newline at end of file diff --git a/Assets/Scripts/Modifiers/PercentStatModifier.cs b/Assets/Scripts/Modifiers/PercentStatModifier.cs index 981e012..d143935 100644 --- a/Assets/Scripts/Modifiers/PercentStatModifier.cs +++ b/Assets/Scripts/Modifiers/PercentStatModifier.cs @@ -1,25 +1,27 @@ +using System; using Data; using Interfaces; namespace Modifiers { + [Serializable] public class PercentStatModifier : IStatModifier { private float lastAppliedAmount; - public Stat Stat { get; set; } - public float Percent { get; set; } - public string Description => $"{Stat} +{Percent * 100}%"; + public Stat stat; + public float percent; + public string Description => $"{stat} +{percent * 100}%"; public void Apply(CharacterAttributes attributes) { var baseValue = GetBaseValue(attributes); - lastAppliedAmount = baseValue * Percent; + lastAppliedAmount = baseValue * percent; var flatModifier = new FlatStatModifier { value = lastAppliedAmount, - stat = Stat + stat = stat }; flatModifier.Apply(attributes); @@ -30,7 +32,7 @@ namespace Modifiers var flatModifier = new FlatStatModifier { value = -lastAppliedAmount, - stat = Stat + stat = stat }; flatModifier.Apply(attributes); @@ -38,7 +40,7 @@ namespace Modifiers private T GetBaseValue(CharacterAttributes attributes) { - return Stat switch + return stat switch { Stat.Health => (T)(object)attributes.Health, Stat.MaxHealth => (T)(object)attributes.MaxHealth, diff --git a/Assets/Scripts/Systems/CharacterModifierManager.cs b/Assets/Scripts/Systems/CharacterModifierManager.cs index e873714..da95218 100644 --- a/Assets/Scripts/Systems/CharacterModifierManager.cs +++ b/Assets/Scripts/Systems/CharacterModifierManager.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Data; using Interfaces; +using KBCore.Refs; using Sirenix.Serialization; using UnityEngine; @@ -10,7 +11,7 @@ namespace Systems { [OdinSerialize] private List activeModifiers = new(); - [SerializeField] private Character character; + [SerializeField, Self] private Character character; public void EquipItem(IStatModifier modifier) { diff --git a/Assets/Scripts/Systems/CharacterWeaponsManager.cs b/Assets/Scripts/Systems/CharacterWeaponsManager.cs index e7a395a..32d38ba 100644 --- a/Assets/Scripts/Systems/CharacterWeaponsManager.cs +++ b/Assets/Scripts/Systems/CharacterWeaponsManager.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using Data; +using KBCore.Refs; using Sirenix.Serialization; using UnityEngine; using Weapons; @@ -8,5 +10,57 @@ namespace Systems public class CharacterWeaponsManager : MonoBehaviour { [OdinSerialize] private List equippedWeapons = new(); + + [SerializeField] private IReadOnlyList EquippedWeapons => equippedWeapons.AsReadOnly(); + [SerializeField, Self] private Character character; + + public Weapon EquipWeapon(GameObject weaponPrefab) + { + var weaponObject = Instantiate(weaponPrefab, transform); + if (weaponObject.TryGetComponent(out Weapon weapon)) + { + weapon.character = character; + equippedWeapons.Add(weapon); + weapon.enabled = true; + return weapon; + } + + Destroy(weaponObject); + return null; + } + + public void UnequipWeapon(Weapon weapon, bool destroy = true) + { + if (!equippedWeapons.Remove(weapon)) return; + weapon.enabled = false; + + if (!destroy) return; + Destroy(weapon.gameObject); + } + + public void DisableAllWeapons() + { + foreach (var weapon in equippedWeapons) + { + weapon.enabled = false; + } + } + + public void EnableAllWeapons() + { + foreach (var weapon in equippedWeapons) + { + weapon.enabled = true; + } + } + + public void ClearWeapons() + { + foreach (var weapon in equippedWeapons) + { + Destroy(weapon.gameObject); + } + equippedWeapons.Clear(); + } } } \ No newline at end of file diff --git a/Assets/Scripts/Systems/InventoryManager.cs b/Assets/Scripts/Systems/InventoryManager.cs new file mode 100644 index 0000000..0d1c36b --- /dev/null +++ b/Assets/Scripts/Systems/InventoryManager.cs @@ -0,0 +1,86 @@ +using System; +using System.Linq; +using Inventory; +using KBCore.Refs; +using UnityEngine; +using Weapons; + +namespace Systems +{ + public class InventoryManager : MonoBehaviour + { + [SerializeField, Self] private Inventory.Inventory inventory; + [SerializeField, Self] private CharacterModifierManager characterModifierManager; + [SerializeField, Self] private CharacterWeaponsManager characterWeaponsManager; + + private void Start() + { + if (inventory == null) + { + Debug.LogError("Inventory is not assigned in InventoryManager."); + return; + } + + if (characterModifierManager == null) + { + Debug.LogError("CharacterModifierManager is not assigned in InventoryManager."); + return; + } + + if (characterWeaponsManager == null) + { + Debug.LogError("CharacterWeaponsManager is not assigned in InventoryManager."); + return; + } + + EquipAllItems(); + EquipAllWeapons(); + } + + public void EquipItem(StatModifierItem item) + { + inventory.AddItem(item); + foreach (var cure in item.cures) characterModifierManager.EquipItem(cure); + foreach (var curse in item.curses) characterModifierManager.EquipItem(curse); + } + + public void UnequipItem(StatModifierItem item) + { + if (inventory.ItemSlots.All(slot => slot.item != item)) return; + inventory.RemoveItem(item); + + foreach (var cure in item.cures) characterModifierManager.UnequipItem(cure); + foreach (var curse in item.curses) characterModifierManager.UnequipItem(curse); + } + + public void EquipWeapon(WeaponItem weaponItem) + { + inventory.AddWeapon(weaponItem); + characterWeaponsManager.EquipWeapon(weaponItem.prefab); + } + + public void UnequipWeapon(WeaponItem weaponItem) + { + if (inventory.WeaponSlots.All(slot => slot.item != weaponItem)) return; + inventory.RemoveWeapon(weaponItem); + weaponItem.prefab.TryGetComponent(out Weapon weapon); + characterWeaponsManager.UnequipWeapon(weapon); + } + + private void EquipAllWeapons() + { + foreach (var slot in inventory.WeaponSlots) + { + EquipWeapon(slot.item as WeaponItem); + } + } + + private void EquipAllItems() + { + foreach (var slot in inventory.ItemSlots) + { + EquipItem(slot.item as StatModifierItem); + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Systems/InventoryManager.cs.meta b/Assets/Scripts/Systems/InventoryManager.cs.meta new file mode 100644 index 0000000..76d0f1a --- /dev/null +++ b/Assets/Scripts/Systems/InventoryManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 57782f9b469d49ab9f4ad6c6e1ddf844 +timeCreated: 1752269055 \ No newline at end of file diff --git a/Assets/Scripts/Weapons/Weapon.cs b/Assets/Scripts/Weapons/Weapon.cs index 063d842..091b16c 100644 --- a/Assets/Scripts/Weapons/Weapon.cs +++ b/Assets/Scripts/Weapons/Weapon.cs @@ -11,8 +11,8 @@ namespace Weapons { private float timer; - [SerializeField] protected Character character; [OdinSerialize, InlineProperty] public WeaponStats weaponStats = new(); + public Character character; private void Update() {