diff --git a/.idea/.idea.exhaustion/.idea/indexLayout.xml b/.idea/.idea.exhaustion/.idea/indexLayout.xml
new file mode 100644
index 00000000..7b08163c
--- /dev/null
+++ b/.idea/.idea.exhaustion/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.exhaustion/.idea/workspace.xml b/.idea/.idea.exhaustion/.idea/workspace.xml
new file mode 100644
index 00000000..f8f4a5b5
--- /dev/null
+++ b/.idea/.idea.exhaustion/.idea/workspace.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Assets/JAY/Animation/CustomAttack01.anim b/Assets/JAY/Animation/CustomAttack01.anim
index 87ed2397..cdb44bb5 100644
--- a/Assets/JAY/Animation/CustomAttack01.anim
+++ b/Assets/JAY/Animation/CustomAttack01.anim
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:51c6f4c4d0aa53532545f61a997fbe42e2de2395443bbc0437546b93cb259037
-size 68742
+oid sha256:a78c0ae5bd17e84ad7484d6345f51126e0123d5d46864b537e9c5cc0e958ac48
+size 68398
diff --git a/Assets/JAY/Animation/CustomAttack02.anim b/Assets/JAY/Animation/CustomAttack02.anim
index db82e99a..32d86cfd 100644
--- a/Assets/JAY/Animation/CustomAttack02.anim
+++ b/Assets/JAY/Animation/CustomAttack02.anim
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6840d07e637f812131e19cdb5d3f853f96ce3a07cf94d648b4ccc7335ff31522
-size 64417
+oid sha256:56d4a41618cb3e9820775285a048b7fad66ad497b569e8846a2133d5eb971f9c
+size 64073
diff --git a/Assets/JAY/Scripts/AnimatorEventRelay.cs b/Assets/JAY/Scripts/AnimatorEventRelay.cs
index 8b2ffee9..005347e4 100644
--- a/Assets/JAY/Scripts/AnimatorEventRelay.cs
+++ b/Assets/JAY/Scripts/AnimatorEventRelay.cs
@@ -8,16 +8,6 @@ public class AnimatorEventRelay : MonoBehaviour
{
_playerController = GetComponentInParent();
}
-
- public void SetAttackComboTrue()
- {
- _playerController?.SetAttackComboTrue();
- }
-
- public void SetAttackComboFalse()
- {
- _playerController?.SetAttackComboFalse();
- }
public void PlayAttackEffect()
{
diff --git a/Assets/JAY/Scripts/PlayerAction/PlayerActionAttack.cs b/Assets/JAY/Scripts/PlayerAction/PlayerActionAttack.cs
index bd6a6662..154d9f60 100644
--- a/Assets/JAY/Scripts/PlayerAction/PlayerActionAttack.cs
+++ b/Assets/JAY/Scripts/PlayerAction/PlayerActionAttack.cs
@@ -2,72 +2,83 @@
public class PlayerActionAttack : IPlayerAction {
private static readonly int ComboStep = Animator.StringToHash("ComboStep");
+
private PlayerController player;
private int comboStep = 1;
private bool comboQueued = false;
private bool canReceiveCombo = false;
-
- public int CurrentComboStep => comboStep;
+ private float comboTimer = 0f;
+
+ [SerializeField] private float comboDuration = 0.7f;
+ private int maxComboStep = 4;
public bool IsActive { get; private set; }
+ public int CurrentComboStep => comboStep;
public void StartAction(PlayerController player) {
this.player = player;
IsActive = true;
+
comboStep = 1;
comboQueued = false;
- PlayComboAnimation(comboStep);
+ canReceiveCombo = true;
+ comboTimer = 0f;
+
player.SafeSetBool("Attack", true);
+ PlayComboAnimation(comboStep);
}
public void UpdateAction() {
- if (Input.GetKeyDown(KeyCode.X) && canReceiveCombo) {
+ comboTimer += Time.deltaTime;
+
+ if (canReceiveCombo && Input.GetKeyDown(KeyCode.X)) {
comboQueued = true;
}
+
+ if (comboTimer >= comboDuration) {
+ ProceedComboOrEnd();
+ }
+ }
+
+ private void ProceedComboOrEnd() {
+ canReceiveCombo = false;
+
+ if (comboQueued && comboStep < maxComboStep) {
+ comboStep++;
+ comboQueued = false;
+ comboTimer = 0f;
+ canReceiveCombo = true;
+ PlayComboAnimation(comboStep);
+ } else {
+ EndAction();
+ }
}
public void EndAction() {
+ if (player == null) return;
+
+ player.WeaponController.AttackEnd();
+
player.SafeSetBool("Attack", false);
IsActive = false;
- player.OnActionEnded(this); // player 에서도 action 초기화
+ player.OnActionEnded(this);
player = null;
}
- public void EnableCombo() {
- canReceiveCombo = true;
- }
+ private void PlayComboAnimation(int step) {
+ if (player?.PlayerAnimator == null) return;
- public void DisableCombo() {
- canReceiveCombo = false;
+ player.PlayerAnimator.SetInteger(ComboStep, step);
- if (comboQueued && comboStep < 4) {
- comboStep++;
- PlayComboAnimation(comboStep);
- comboQueued = false;
- } else {
- EndAction(); // 행동 종료
- }
- }
-
- private void PlayComboAnimation(int step)
- {
- if (player.PlayerAnimator == null) return;
-
- // 안전하게 파라미터 체크
- foreach (var param in player.PlayerAnimator.parameters)
- {
- if (param.nameHash == ComboStep && param.type == AnimatorControllerParameterType.Int)
- {
- player.PlayerAnimator.SetInteger(ComboStep, step);
- break;
- }
- }
-
- // 무기에 콤보 단계 전달
var weapon = player.GetComponentInChildren();
- if (weapon != null)
- {
- weapon.SetComboStep(step);
+ weapon?.SetComboStep(step);
+
+ player.WeaponController.AttackStart();
+ }
+
+ public void OnComboInput() {
+ if (canReceiveCombo) {
+ comboQueued = true;
}
}
-}
\ No newline at end of file
+}
diff --git a/Assets/JAY/Scripts/PlayerController.cs b/Assets/JAY/Scripts/PlayerController.cs
index 9742975c..b3720cfe 100644
--- a/Assets/JAY/Scripts/PlayerController.cs
+++ b/Assets/JAY/Scripts/PlayerController.cs
@@ -24,10 +24,8 @@ public class PlayerController : CharacterBase, IObserver
private bool _isBattle;
private GameObject weapon;
private WeaponController _weaponController;
- private float attackUpgradeLevel;
- private float moveSpeedUpgradeLevel;
- private float dashCooldownUpgradeLevel;
-
+ public WeaponController WeaponController => _weaponController;
+
private IPlayerState _currentStateClass { get; set; }
private IPlayerAction _currentAction;
public IPlayerAction CurrentAction => _currentAction;
@@ -51,13 +49,6 @@ public class PlayerController : CharacterBase, IObserver
public CharacterController CharacterController => _characterController;
public bool IsBattle => _isBattle;
public Transform DashEffectAnchor => dashEffectAnchor;
-
- // 대시 쿨타임 관련
- [SerializeField] private float dashCooldownDuration = 1.5f;
- private float dashCooldownTimer = 0f;
- public bool IsDashOnCooldown => dashCooldownTimer > 0f;
- public float DashCooldownRatio => dashCooldownTimer / dashCooldownDuration;
-
private void Awake()
{
@@ -81,15 +72,6 @@ public class PlayerController : CharacterBase, IObserver
hitEffectController = GetComponentInChildren();
PlayerInit();
-
- //강화 적용
- attackUpgradeLevel = 1 + (float)UpgradeManager.Instance.upgradeStat.CurrentUpgradeLevel(StatType.AttackPower)/2;
- moveSpeedUpgradeLevel = 1 + (float)UpgradeManager.Instance.upgradeStat.CurrentUpgradeLevel(StatType.MoveSpeed)/2;
- dashCooldownUpgradeLevel = (float)UpgradeManager.Instance.upgradeStat.CurrentUpgradeLevel(StatType.DashCoolDown)/4;
-
- attackPower *= attackUpgradeLevel;
- moveSpeed *= moveSpeedUpgradeLevel;
- dashCooldownDuration -= dashCooldownUpgradeLevel;
}
private void Update()
@@ -99,10 +81,6 @@ public class PlayerController : CharacterBase, IObserver
_playerStates[CurrentState].Update();
}
- // 대시 쿨타임 진행
- if (dashCooldownTimer > 0f)
- dashCooldownTimer -= Time.deltaTime;
-
// Hit 상태거나 게임 끝났을 땐 땐 입력 무시
if (CurrentState == PlayerState.Hit || CurrentState == PlayerState.Dead || CurrentState == PlayerState.Win)
return;
@@ -253,13 +231,6 @@ public class PlayerController : CharacterBase, IObserver
{
if (!_isBattle) return;
- // 쿨타임 중이면 무시
- if (IsDashOnCooldown)
- {
- Debug.Log("대시 쿨타임 중");
- return;
- }
-
// 만약 공격 중이면 강제로 공격 종료
if (_currentAction == _attackAction && _attackAction.IsActive)
{
@@ -273,9 +244,6 @@ public class PlayerController : CharacterBase, IObserver
_currentAction = _actionDash;
_actionDash.StartAction(this);
-
- // 쿨타임 시작
- dashCooldownTimer = dashCooldownDuration;
}
public void OnActionEnded(IPlayerAction action)
@@ -324,27 +292,7 @@ public class PlayerController : CharacterBase, IObserver
// 무기도 전투모드에만
weapon.SetActive(_isBattle);
}
-
- // Animation Event에서 호출될 메서드
- public void SetAttackComboTrue()
- {
- if (_weaponController.IsAttacking) return; // 이미 공격 중이면 실행 안함
- if (_currentAction == _attackAction) {
- _attackAction.EnableCombo();
- _weaponController.AttackStart();
- }
- }
-
- public void SetAttackComboFalse()
- {
- if (_currentAction == _attackAction) {
- // 이벤트 중복 호출? 공격 종료 시 SetAttackComboFalse가 아니라 ~True로 끝나서 오류 발생. (공격 안하는 상태여도 공격으로 판정됨)
- _attackAction.DisableCombo();
- _weaponController.AttackEnd(); // IsAttacking = false로 변경
- }
- }
-
public void PlayAttackEffect()
{
if (_attackAction == null) return;
@@ -383,6 +331,10 @@ public class PlayerController : CharacterBase, IObserver
GameManager.Instance.PlayPlayerAttackSound();
StartAttackAction();
}
+ else if (_currentAction is PlayerActionAttack attackAction)
+ {
+ attackAction.OnComboInput();
+ }
}
#endregion
diff --git a/Assets/JYY/Prefabs/Alien Big Blink.prefab b/Assets/JYY/Prefabs/Alien Big Blink.prefab
index abcf6a68..d0829083 100644
--- a/Assets/JYY/Prefabs/Alien Big Blink.prefab
+++ b/Assets/JYY/Prefabs/Alien Big Blink.prefab
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a1f8d0221468c75d2d3493c9338f253cb9b753dc860d56ddee853b4450ca6461
-size 77370
+oid sha256:957feb878cd80c20a3dc70cfb66c740204db8155c97835537e39de8730221fdc
+size 77283
diff --git a/Assets/JYY/Prefabs/Bullets/Magic Missaile.prefab b/Assets/JYY/Prefabs/Bullets/Magic Missaile.prefab
index a70f17b0..c7bbc27d 100644
--- a/Assets/JYY/Prefabs/Bullets/Magic Missaile.prefab
+++ b/Assets/JYY/Prefabs/Bullets/Magic Missaile.prefab
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3f001c75ff289549a3434a98114a11c041bcd61411bc2d892a0edd95c86652f5
-size 10837
+oid sha256:d51e7bbc994507d09d8e41c524596021b31347e399b76074317e2fa3b19fbbc2
+size 10895
diff --git a/Assets/JYY/Scenes/MonsterTest.unity b/Assets/JYY/Scenes/MonsterTest.unity
index 06210cab..1afc100f 100644
--- a/Assets/JYY/Scenes/MonsterTest.unity
+++ b/Assets/JYY/Scenes/MonsterTest.unity
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4ae36443f365ae3116a37980b936076ebed7b169ca2353d8836066de0ccff0fc
-size 23022
+oid sha256:1e8d721e4d0b53d0d1f036e49add6145b037d53c26f1d05c02f1526eca8923fd
+size 23594
diff --git a/Assets/KSH/PlayerStats.cs b/Assets/KSH/PlayerStats.cs
index d32ad5a6..760b6f9b 100644
--- a/Assets/KSH/PlayerStats.cs
+++ b/Assets/KSH/PlayerStats.cs
@@ -2,9 +2,10 @@ using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
+using UnityEngine.SceneManagement;
using Random = UnityEngine.Random;
-public class PlayerStats : MonoBehaviour, ISaveable
+public class PlayerStats : MonoBehaviour
{
public class StatsChangeData // 변경된 스탯 데이터
{
@@ -29,7 +30,7 @@ public class PlayerStats : MonoBehaviour, ISaveable
public event Action OnDayEnded;
public event Action Exhaustion; // 탈진
- public event Action Overslept; // 결근(늦잠)
+ public event Action Overslept; // 늦잠
public event Action ZeroReputation; // 평판 0 이벤트
public event Action OnStatsChanged; // 스탯 변경 이벤트
public event Action OnWorked; // 퇴근 이벤트 (출근 이후 집에 돌아올 시간에 발생)
@@ -37,6 +38,18 @@ public class PlayerStats : MonoBehaviour, ISaveable
private float previousAddHealth = 0f;
public static PlayerStats Instance;
+
+ // 결근 이벤트 관련 변수
+ private bool _hasWorkedToday = false;
+ private bool _hasCheckedAbsenceToday = false; // 결근 체크, 하루에 결근 여러 번 체크 안하기 위함
+ public event Action OnAbsent; // 결근
+
+ // 말풍선
+ private GameObject messagePanelInstance;
+ private SpeechBubbleFollower speechBubbleFollower;
+ private bool isActiveBubble;
+ private bool hasShownBubbleToday; // 하루에 말풍선 하나만 표시하기
+
private void Awake()
{
if (Instance == null)
@@ -59,7 +72,88 @@ public class PlayerStats : MonoBehaviour, ISaveable
{
_valueByAction = new ValueByAction();
_valueByAction.Initialize(); // 값 초기화
+
+ LoadMessagePanel();
+ CheckBubble();
+
+ SceneManager.sceneLoaded += OnSceneLoaded; // 씬 전환 이벤트
}
+
+ #region 말풍선(Bubble) 관련
+
+ private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
+ {
+ // 새 씬에서 메시지 패널 다시 로드
+ LoadMessagePanel();
+ CheckBubble();
+ }
+
+ // OnDestroy에서 이벤트 구독 해제
+ private void OnDestroy()
+ {
+ SceneManager.sceneLoaded -= OnSceneLoaded;
+ }
+
+ private void LoadMessagePanel()
+ {
+ if (messagePanelInstance != null) // 기존 패널 파괴
+ {
+ Destroy(messagePanelInstance);
+ messagePanelInstance = null;
+ }
+
+ GameObject messagePanelPrefab = Resources.Load("Prefabs/MessagePanel");
+
+ if (messagePanelPrefab != null)
+ {
+ Canvas canvas = FindObjectOfType