DEG-166-NPC-대사-추가 #54

Merged
Sehyeon merged 4 commits from DEG-166-NPC-대사-추가 into main 2025-05-14 05:53:43 +00:00
8 changed files with 204 additions and 59 deletions

View File

@ -16,10 +16,6 @@ public class DungeonLogic : MonoBehaviour
private PlayerController _player; private PlayerController _player;
private EnemyController _enemy; private EnemyController _enemy;
// 던전 결과 이벤트
public event Action OnDungeonSuccess;
public event Action OnDungeonFailure;
private void Awake() private void Awake()
{ {
SpawnBossForCurrentStage(); SpawnBossForCurrentStage();

View File

@ -50,6 +50,7 @@ public class PlayerStats : MonoBehaviour
private SpeechBubbleFollower _speechBubbleFollower; private SpeechBubbleFollower _speechBubbleFollower;
private bool _isActiveBubble; private bool _isActiveBubble;
private bool _hasShownBubbleToday; // 하루에 말풍선 하나만 표시하기 private bool _hasShownBubbleToday; // 하루에 말풍선 하나만 표시하기
private InteractionAnimationPanelController _interactionAnimation; // 상호작용 패널 Active 여부 확인
private int _mealCount; private int _mealCount;
public int MealCount => _mealCount; public int MealCount => _mealCount;
@ -143,7 +144,6 @@ public class PlayerStats : MonoBehaviour
} }
} }
private InteractionAnimationPanelController _interactionAnimation;
public void SetInteractionPanelController(InteractionAnimationPanelController panelController) public void SetInteractionPanelController(InteractionAnimationPanelController panelController)
{ {
_interactionAnimation = panelController; _interactionAnimation = panelController;
@ -151,7 +151,7 @@ public class PlayerStats : MonoBehaviour
public void ShowBubble() public void ShowBubble()
{ {
if (_interactionAnimation.IsPanelActive()) return; if (_interactionAnimation != null && _interactionAnimation.IsPanelActive()) return;
if(_isActiveBubble) if(_isActiveBubble)
_speechBubbleFollower.ShowMessage(); _speechBubbleFollower.ShowMessage();
@ -296,11 +296,6 @@ public class PlayerStats : MonoBehaviour
// 하루가 실제로 종료된 경우에만 이벤트 발생 // 하루가 실제로 종료된 경우에만 이벤트 발생
if (isDayEnded) if (isDayEnded)
{ {
// 결근 관련 변수 초기화
_hasWorkedToday = false;
_hasCheckedAbsenceToday = false;
_hasShownBubbleToday = false;
// 식사 횟수 초기화 // 식사 횟수 초기화
_mealCount = 0; _mealCount = 0;
@ -334,6 +329,13 @@ public class PlayerStats : MonoBehaviour
EndDay(time, actionType); EndDay(time, actionType);
} }
if (TimeStat >= 8.0f && TimeStat < 9.0f)
{
_hasWorkedToday = false;
_hasCheckedAbsenceToday = false;
_hasShownBubbleToday = false;
}
CheckBubble(); CheckBubble();
} }

View File

@ -28,7 +28,7 @@ public class InteractionController : MonoBehaviour
{ {
housingCanvasController.ShowNpcInteractionButton(() => housingCanvasController.ShowNpcInteractionButton(() =>
{ {
GameManager.Instance.StartNPCDialogue(GamePhase.Gameplay); GameManager.Instance.DirectStartDialogue();
}); });
} }

View File

@ -46,6 +46,97 @@
"id": "player_intro_3", "id": "player_intro_3",
"name": "주인공", "name": "주인공",
"text": "할 수 밖에 없잖아...!!", "text": "할 수 밖에 없잖아...!!",
"nextId": "fairy_intro_5",
"phase": "intro"
},
{
"id": "fairy_intro_5",
"name": "냉장고 요정",
"text": "아, 추가로 설명을 하자면!",
"nextId": "player_intro_4",
"phase": "intro"
},
{
"id": "player_intro_4",
"name": "냉장고 요정",
"text": "시간 아래의 바가 보이지? 상단은 너의 회사 평판, 하단은 체력 바야.",
"nextId": "fairy_intro_6",
"phase": "intro"
},
{
"id": "fairy_intro_6",
"name": "냉장고 요정",
"text": "던전은 냉장고를 통해 진입할 수 있어. 일주일 내에 스테이지 2개를 깨주기 바라!",
"nextId": "player_intro_5",
"phase": "intro"
},
{
"id": "player_intro_5",
"name": "주인공",
"text": "(앞으로 중고 거래를 안해야겠어.) 그래. 그런데 평판이나 체력이 0이 되면 뭐가... 돼?",
"nextId": "fairy_intro_7",
"phase": "intro"
},
{
"id": "fairy_intro_7",
"name": "냉장고 요정",
"text": "평판이 0이 되면 굉장한 일이 벌어지지...",
"nextId": "player_intro_6",
"phase": "intro"
},
{
"id": "player_intro_6",
"name": "주인공",
"text": "설마 용사로 전직-",
"nextId": "fairy_intro_8",
"phase": "intro"
},
{
"id": "fairy_intro_8",
"name": "냉장고 요정",
"text": "너가 회사에서 짤려.",
"nextId": "player_intro_7",
"phase": "intro"
},
{
"id": "player_intro_7",
"name": "주인공",
"text": "...........?",
"nextId": "fairy_intro_9",
"phase": "intro"
},
{
"id": "fairy_intro_9",
"name": "냉장고 요정",
"text": "그리고 체력 0이 되면 지쳐서 기절할 거야.",
"nextId": "player_intro_8",
"phase": "intro"
},
{
"id": "player_intro_8",
"name": "주인공",
"text": "...........................",
"nextId": "fairy_intro_10",
"phase": "intro"
},
{
"id": "fairy_intro_10",
"name": "냉장고 요정",
"text": "관리를 잘 하는 게 좋겠지?",
"nextId": "player_intro_9",
"phase": "intro"
},
{
"id": "player_intro_9",
"name": "주인공",
"text": "이래서 감자 온도가 -99도, 아니 알려줘서 참으로 고맙다.",
"nextId": "fairy_intro_11",
"phase": "intro"
},
{
"id": "fairy_intro_11",
"name": "냉장고 요정",
"text": "별 말씀을!",
"nextId": "", "nextId": "",
"phase": "intro" "phase": "intro"
}, },
@ -73,14 +164,14 @@
{ {
"id": "fairy_gameplay_3", "id": "fairy_gameplay_3",
"name": "냉장고 요정", "name": "냉장고 요정",
"text": "던전은 총 2스테이지까지 있으며 모두 클리어한다면...", "text": "같은 스테이지를 3번이나 시도하면... 굉장한 일이 벌어지지.",
"nextId": "player_gameplay_3", "nextId": "player_gameplay_3",
"phase": "gameplay" "phase": "gameplay"
}, },
{ {
"id": "player_gameplay_3", "id": "player_gameplay_3",
"name": "주인공", "name": "주인공",
"text": "한다면... 뭐지?", "text": "(안좋은 일이겠지)",
"nextId": "", "nextId": "",
"phase": "gameplay" "phase": "gameplay"
}, },
@ -195,6 +286,69 @@
"text": "그 날 서울시 어느 동네에서, 한 34세의 남성의 절규 소리가 울려퍼졌다.", "text": "그 날 서울시 어느 동네에서, 한 34세의 남성의 절규 소리가 울려퍼졌다.",
"nextId": "", "nextId": "",
"phase": "zero" "phase": "zero"
},
{
"id": "fairy_fail_1",
"name": "냉장고 요정",
"text": "...이야. \n같은 스테이지를 몇 번이나 도전하는 거야?",
"nextId": "player_fail_1",
"phase": "fail"
},
{
"id": "player_fail_1",
"name": "주인공",
"text": "못 할 수도 있지...",
"nextId": "fairy_fail_2",
"phase": "fail"
},
{
"id": "fairy_fail_2",
"name": "냉장고 요정",
"text": "음, 축하해!",
"nextId": "player_fail_2",
"phase": "fail"
},
{
"id": "player_fail_2",
"name": "주인공",
"text": "(불안하다...)",
"nextId": "fairy_fail_3",
"phase": "fail"
},
{
"id": "fairy_fail_3",
"name": "냉장고 요정",
"text": "던전이 제대로 잠재워지지 않아서 곧 세상은 멸망할 거야!",
"nextId": "player_fail_4",
"phase": "fail"
},
{
"id": "player_fail_4",
"name": "주인공",
"text": "뭐?????",
"nextId": "fairy_fail_4",
"phase": "fail"
},
{
"id": "fairy_fail_4",
"name": "냉장고 요정",
"text": "출근하기 싫다고 했지? 이제 안해도 돼!",
"nextId": "player_fail_5",
"phase": "fail"
},
{
"id": "player_fail_5",
"name": "주인공",
"text": "안돼!!!!!!",
"nextId": "fairy_fail_5",
"phase": "fail"
},
{
"id": "fairy_fail_5",
"name": " ",
"text": "그렇게 세상은 멸망했다. 끝.",
"nextId": "",
"phase": "fail"
} }
] ]
} }

View File

@ -35,8 +35,9 @@ public enum GamePhase // 단계별로 출력되는 대화가 달라짐
{ {
Intro, // 인트로 설명문 Intro, // 인트로 설명문
Gameplay, // 게임 진행 팁? 등 Gameplay, // 게임 진행 팁? 등
End, // 엔딩 대화 End, // 회고 엔딩
ZeroEnd ZeroEnd, // 평판 0 엔딩
FailEnd // 같은 스테이지 3회 실패 엔딩
} }
public class ChatWindowController : MonoBehaviour, IPointerClickHandler public class ChatWindowController : MonoBehaviour, IPointerClickHandler

View File

@ -91,6 +91,10 @@ public class FairyDialogueManager
{ {
StartPhaseDialogue("zero"); StartPhaseDialogue("zero");
} }
else if (phase == GamePhase.FailEnd)
{
StartPhaseDialogue("fail");
}
} }
// 단계별 시작 대화 찾기 및 시작 // 단계별 시작 대화 찾기 및 시작

View File

@ -14,6 +14,9 @@ public partial class GameManager : Singleton<GameManager>
private int stageLevel = 1; // 스테이지 정보 private int stageLevel = 1; // 스테이지 정보
public int StageLevel => stageLevel; public int StageLevel => stageLevel;
private int tryStageCount = 0;
public int TryStageCount => tryStageCount;
// 날짜 변경 이벤트, 추후에 UI 상의 날짜를 변경할 때 사용 // 날짜 변경 이벤트, 추후에 UI 상의 날짜를 변경할 때 사용
public event Action<int> OnDayChanged; public event Action<int> OnDayChanged;
@ -40,15 +43,24 @@ public partial class GameManager : Singleton<GameManager>
public void StartNPCDialogue(GamePhase phase) // intro, gameplay, end 존재 public void StartNPCDialogue(GamePhase phase) // intro, gameplay, end 존재
{ {
if(chatWindowController == null) StartCoroutine(StartNPCDialogueCoroutine(phase));
SetChatWindowController(); }
private IEnumerator StartNPCDialogueCoroutine(GamePhase phase)
{
if (chatWindowController == null)
{
yield return new WaitForSeconds(0.5f); // 씬 전환 대기
chatWindowController = FindObjectOfType<ChatWindowController>();
}
chatWindowController.SetGamePhase(phase); chatWindowController.SetGamePhase(phase);
} }
private void SetChatWindowController() public void DirectStartDialogue()
{ {
chatWindowController = FindObjectOfType<ChatWindowController>(); if (chatWindowController == null) chatWindowController = FindObjectOfType<ChatWindowController>();
chatWindowController.SetGamePhase(GamePhase.Gameplay);
} }
#endregion #endregion
@ -79,6 +91,7 @@ public partial class GameManager : Singleton<GameManager>
public void ChangeToGameScene() public void ChangeToGameScene()
{ {
tryStageCount++; // 던전 시도 횟수 증가
SceneManager.LoadScene("ReDungeon"); // 던전 Scene SceneManager.LoadScene("ReDungeon"); // 던전 Scene
HandleSceneAudio("Dungeon"); HandleSceneAudio("Dungeon");
} }
@ -87,6 +100,8 @@ public partial class GameManager : Singleton<GameManager>
{ {
SceneManager.LoadScene("ReHousing"); // Home Scene SceneManager.LoadScene("ReHousing"); // Home Scene
HandleSceneAudio("Housing"); HandleSceneAudio("Housing");
if (tryStageCount >= 3) FailEnd(); // 엔딩
} }
// TODO: Open Setting Panel 등 Panel 처리 // TODO: Open Setting Panel 등 Panel 처리

View File

@ -16,51 +16,24 @@ public partial class GameManager
public void ClearStage() public void ClearStage()
{ {
tryStageCount = 0; // 시도 횟수 초기화
stageLevel++; stageLevel++;
} }
private void ZeroReputationEnd() private void ZeroReputationEnd() // 평판 0 엔딩
{ {
// npc와의 대화 출력, Phase = zero
StartNPCDialogue(GamePhase.ZeroEnd); StartNPCDialogue(GamePhase.ZeroEnd);
} }
// 엔딩 관련 메서드. 7일차에 실행 private void FailEnd() // 같은 스테이지 3회 도전 실패 엔딩
{
StartNPCDialogue(GamePhase.FailEnd);
}
// 회고 엔딩. 7일차에 실행
private void TriggerTimeEnding() private void TriggerTimeEnding()
{ {
// npc와의 마지막 대화 출력 // npc와의 마지막 대화 출력
StartNPCDialogue(GamePhase.End); StartNPCDialogue(GamePhase.End);
// 플레이어 상태에 따라 엔딩 판별
// EndingType endingType = DetermineEnding();
// 엔딩 타입에 따라 다른 씬이나 UI 표시
/*switch (endingType)
{
case EndingType.Normal:
Debug.Log("던전 공략 성공");
// TODO: 엔딩 관련 패널 띄우기
break;
case EndingType.Bad:
Debug.Log("던전 공략 실패");
break;
case EndingType.Happy:
Debug.Log("던전 공략 성공과 훌륭한 평판 작");
break;
}*/
}
// 던전 스테이지와 평판 수치로 엔딩 판별
private EndingType DetermineEnding()
{
if (stageLevel < GameConstants.maxStage) // 현재 스테이지 1 혹은 2
return EndingType.Bad;
if (PlayerStats.Instance.ReputationStat >= happyEndReputation) // 평판이 일정 수치 이상
return EndingType.Happy;
return EndingType.Normal;
} }
} }