diff --git a/Assets/Scripts/Core/Domain/Status.meta b/Assets/Scripts/Core/Domain/Status.meta new file mode 100644 index 0000000..e33519f --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: abcaa49aec2c42b49a76184f29afe8c5 +timeCreated: 1765574893 \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/Status/Effects.meta b/Assets/Scripts/Core/Domain/Status/Effects.meta new file mode 100644 index 0000000..bbbfc8a --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/Effects.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6787efe77d5b42eabca4db1f4e8f9601 +timeCreated: 1765575039 \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/Status/Effects/LightFootedEffect.cs b/Assets/Scripts/Core/Domain/Status/Effects/LightFootedEffect.cs new file mode 100644 index 0000000..ff47bee --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/Effects/LightFootedEffect.cs @@ -0,0 +1,33 @@ +namespace Core.Domain.Status.Effects +{ + public class LightFootedEffect : IStatusEffect + { + private float _duration; + + public bool IsExpired => _duration <= 0; + + public LightFootedEffect(float duration) + { + _duration = duration; + } + + public void Tick(float deltaTime) + { + _duration -= deltaTime; + } + + public void ModifyCapabilities(ref PlayerCapabilities caps) + { + caps.CanTriggerDecay = false; + caps.SpeedMultiplier = 1.2f; + } + + public void OnApply() + { + } + + public void OnRemove() + { + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/Status/Effects/LightFootedEffect.cs.meta b/Assets/Scripts/Core/Domain/Status/Effects/LightFootedEffect.cs.meta new file mode 100644 index 0000000..821e47a --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/Effects/LightFootedEffect.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3569c07e1bba489d8835de24488cfef8 +timeCreated: 1765575047 \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/Status/IStatusEffect.cs b/Assets/Scripts/Core/Domain/Status/IStatusEffect.cs new file mode 100644 index 0000000..3e46534 --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/IStatusEffect.cs @@ -0,0 +1,11 @@ +namespace Core.Domain.Status +{ + public interface IStatusEffect + { + bool IsExpired { get; } + void Tick(float deltaTime); + void ModifyCapabilities(ref PlayerCapabilities caps); + void OnApply(); + void OnRemove(); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/Status/IStatusEffect.cs.meta b/Assets/Scripts/Core/Domain/Status/IStatusEffect.cs.meta new file mode 100644 index 0000000..f323b9b --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/IStatusEffect.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 08db161381444423960b7deec94f48c1 +timeCreated: 1765574975 \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/Status/PlayerCapabilities.cs b/Assets/Scripts/Core/Domain/Status/PlayerCapabilities.cs new file mode 100644 index 0000000..fce3f09 --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/PlayerCapabilities.cs @@ -0,0 +1,14 @@ +namespace Core.Domain.Status +{ + public struct PlayerCapabilities + { + public bool CanTriggerDecay; + public float SpeedMultiplier; + + public static PlayerCapabilities Default => new PlayerCapabilities + { + CanTriggerDecay = true, + SpeedMultiplier = 1f + }; + } +} diff --git a/Assets/Scripts/Core/Domain/Status/PlayerCapabilities.cs.meta b/Assets/Scripts/Core/Domain/Status/PlayerCapabilities.cs.meta new file mode 100644 index 0000000..3fcef41 --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/PlayerCapabilities.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6c868f630ebc4cccad39e452e03e1025 +timeCreated: 1765574915 \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/Status/StatusManager.cs b/Assets/Scripts/Core/Domain/Status/StatusManager.cs new file mode 100644 index 0000000..6b1fb1e --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/StatusManager.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; + +namespace Core.Domain.Status +{ + public class StatusManager + { + private readonly List _activeEffects = new(); + + public PlayerCapabilities CurrentCapabilities { get; private set; } + + public StatusManager() + { + Recalculate(); + } + + public void AddEffect(IStatusEffect effect) + { + _activeEffects.Add(effect); + effect.OnApply(); + Recalculate(); + } + + public void Tick(float deltaTime) + { + for (var i = _activeEffects.Count - 1; i >= 0; i--) + { + var effect = _activeEffects[i]; + effect.Tick(deltaTime); + + if (!effect.IsExpired) continue; + + effect.OnRemove(); + _activeEffects.RemoveAt(i); + Recalculate(); + } + } + + private void Recalculate() + { + var caps = PlayerCapabilities.Default; + + foreach (var effect in _activeEffects) + { + effect.ModifyCapabilities(ref caps); + } + + CurrentCapabilities = caps; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/Status/StatusManager.cs.meta b/Assets/Scripts/Core/Domain/Status/StatusManager.cs.meta new file mode 100644 index 0000000..a7c8206 --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/StatusManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8e8580a304be4347a63e7dc0060fdc7b +timeCreated: 1765575109 \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/PlayerController.cs b/Assets/Scripts/Infrastructure/Unity/PlayerController.cs index e5cc52d..940d109 100644 --- a/Assets/Scripts/Infrastructure/Unity/PlayerController.cs +++ b/Assets/Scripts/Infrastructure/Unity/PlayerController.cs @@ -1,4 +1,5 @@ using System; +using Core.Domain.Status; using KBCore.Refs; using UnityEngine; using UnityEngine.InputSystem; @@ -24,6 +25,7 @@ namespace Infrastructure.Unity private Vector2 _moveInput; public Rigidbody Rigidbody => rb; + public StatusManager Status { get; private set; } private void OnEnable() { @@ -44,11 +46,17 @@ namespace Infrastructure.Unity private void Awake() { _actions = new InputSystem_Actions(); + Status = new StatusManager(); rb.freezeRotation = true; rb.useGravity = true; } + private void Update() + { + Status.Tick(Time.deltaTime); + } + private void FixedUpdate() { HandleMovement(); @@ -57,6 +65,8 @@ namespace Infrastructure.Unity private void HandleMovement() { + var currentSpeed = moveSpeed * Status.CurrentCapabilities.SpeedMultiplier; + var targetVelocity = Vector3.zero; var snapAxis = Vector3.zero; @@ -64,12 +74,12 @@ namespace Infrastructure.Unity { if (Mathf.Abs(_moveInput.x) > Mathf.Abs(_moveInput.y)) { - targetVelocity = new Vector3(_moveInput.x > 0 ? moveSpeed : -moveSpeed, 0, 0); + targetVelocity = new Vector3(_moveInput.x > 0 ? currentSpeed : -currentSpeed, 0, 0); snapAxis = Vector3.forward; } else { - targetVelocity = new Vector3(0, 0, _moveInput.y > 0 ? moveSpeed : -moveSpeed); + targetVelocity = new Vector3(0, 0, _moveInput.y > 0 ? currentSpeed : -currentSpeed); snapAxis = Vector3.right; } } @@ -107,6 +117,8 @@ namespace Infrastructure.Unity private void DetectGround() { + if (!Status.CurrentCapabilities.CanTriggerDecay) return; + if (Physics.Raycast(transform.position, Vector3.down, out var hit, groundCheckDistance, tileLayer)) { if (hit.collider.TryGetComponent(out var tileAdapter))