KLingo Project Documentation 1.0.0
Unreal Engine 5.6 C++ Project Documentation
로딩중...
검색중...
일치하는것 없음
ASpeakStageActor.cpp
이 파일의 문서화 페이지로 가기
1// Copyright (c) 2025 Doppleddiggong. All rights reserved. Unauthorized copying, modification, or distribution of this file, via any medium is strictly prohibited. Proprietary and confidential.
2
3#include "ASpeakStageActor.h"
4
5#include "ALingoPlayerState.h"
6#include "APlayerActor.h"
7#include "APlayerControl.h"
8#include "ULingoGameHelper.h"
9#include "GameLogging.h"
10#include "Net/UnrealNetwork.h"
11#include "GameFramework/PlayerState.h"
12#include "Engine/World.h"
13#include "UDialogManager.h"
14#include "UPopupManager.h"
15
17{
18 // Replication 설정
19 bReplicates = true;
20 bAlwaysRelevant = true; // 모든 클라이언트에 항상 복제
21
22 // Tick 비활성화 (이벤트 기반으로 동작)
23 PrimaryActorTick.bCanEverTick = false;
24
25 // 초기값 설정
26 CurrentSpeaker = nullptr;
28}
29
30void ASpeakStageActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
31{
32 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
33
34 DOREPLIFETIME(ASpeakStageActor, CurrentSpeaker);
35 DOREPLIFETIME(ASpeakStageActor, CurrentStepIndex);
36}
37
38//----------------------------------------------------------
39// RepNotify Functions
40//----------------------------------------------------------
41
46
47//----------------------------------------------------------
48// Public Interface
49//----------------------------------------------------------
50
52{
53 if (!HasAuthority() || !Player)
54 return;
55
56 // 이미 사용 중인 경우
57 if (CurrentSpeaker != nullptr)
58 return;
59
60 // 플레이어를 현재 발화자로 설정
61 CurrentSpeaker = Player;
63
64 // 서버 측 리스너에게 즉시 알림
66
67 // 모든 클라이언트에게 SpeakQuest 시작 알림 브로드캐스트
68 FString PlayerName = ULingoGameHelper::GetPlayerNameFromState(Player);
70
71 // 클라이언트에게 현재 단계 정보(Toast, TTS)를 전송하고 UI 업데이트를 요청합니다.
72 if (APlayerControl* PC = Cast<APlayerControl>(CurrentSpeaker->GetOwner()))
73 {
74 // 클라이언트에게 StepIndex를 전달하여 스스로 UI와 TTS를 처리하도록 합니다.
75 PC->Client_UpdateSpeakQuest(CurrentStepIndex);
76 PRINTLOG(TEXT("[SpeakStage] Sent StepIndex %d to client for update."), CurrentStepIndex);
77 }
78}
79
80void ASpeakStageActor::Multicast_NotifySpeakQuestStarted_Implementation(const FString& PlayerName)
81{
82 // // 모든 클라이언트에서 Toast 메시지 표시
83 // if (UDialogManager* DM = UDialogManager::Get(GetWorld()))
84 // {
85 // FString Message = FString::Printf(TEXT("[%s] has started the inspection quest with the officer."), *PlayerName);
86 // DM->ShowToast(Message);
87 // }
88}
89
91{
92 if (!HasAuthority() || !Player)
93 return;
94
95 // 현재 발화자가 아니면 무시
96 if (CurrentSpeaker != Player)
97 return;
98
99 // 다음 단계로 진행
100 AdvanceStep();
101}
102
104{
105 if (ALingoPlayerState* PS = Cast<ALingoPlayerState>(CurrentSpeaker))
106 {
107 return PS->SpeakScenarioData.speak_quest_data.Num();
108 }
109 return 0;
110}
111
113{
114 if (!CurrentSpeaker)
115 return TEXT("");
116
117 // PlayerState에서 데이터 가져오기
118 if (auto PS = Cast<ALingoPlayerState>(CurrentSpeaker))
119 {
120 if (PS->SpeakScenarioData.speak_quest_data.IsValidIndex(CurrentStepIndex))
121 return PS->SpeakScenarioData.speak_quest_data[CurrentStepIndex].GetQuestionMessage();
122 }
123
124 return TEXT("");
125}
126
128{
129 if (ALingoPlayerState* PS = Cast<ALingoPlayerState>(CurrentSpeaker))
130 return PS->SpeakScenarioData.speak_quest_data.Num();
131 return 0;
132}
133
135{
136 if (!HasAuthority())
137 {
138 return;
139 }
140
142
143 // 모든 질문 완료?
144 auto TotalQuestionsCount = GetTotalQuestionsCount();
145 if( CurrentStepIndex >= TotalQuestionsCount )
146 {
147 PRINTLOG(TEXT("[SpeakStage] All steps completed for: %s"), *ULingoGameHelper::GetPlayerNameFromState(CurrentSpeaker));
148 // 스테이지 종료
149 EndStage();
150 }
151 else
152 {
153 PRINTLOG(TEXT("[SpeakStage] Advanced to step: %d/%d"), CurrentStepIndex + 1, TotalQuestionsCount);
154
155 // 클라이언트에게 현재 단계 정보(Toast, TTS)를 전송하고 UI 업데이트를 요청합니다.
156 if (APlayerControl* PC = Cast<APlayerControl>(CurrentSpeaker->GetOwner()))
157 {
158 // 클라이언트에게 StepIndex를 전달하여 스스로 UI와 TTS를 처리하도록 합니다.
159 PC->Client_UpdateSpeakQuest(CurrentStepIndex);
160 PRINTLOG(TEXT("[SpeakStage] Sent StepIndex %d to client for update."), CurrentStepIndex);
161 }
162 }
163}
164
166{
167 if (!HasAuthority() || !CurrentSpeaker)
168 return;
169
170 // SpeakQuest 완료 처리 (PlayerState에 플래그 설정)
171 if (ALingoPlayerState* PS = Cast<ALingoPlayerState>(CurrentSpeaker))
172 {
173 PS->SetSpeakQuestCompleted();
174 }
175
176 // 클라이언트 측에서 완료 UI 처리 및 위젯 업데이트를 하도록 단일 RPC 호출
177 if (APlayerControl* PC = Cast<APlayerControl>(CurrentSpeaker->GetOwner()))
178 {
179 PC->Client_EndSpeakQuest();
180 PRINTLOG(TEXT("[SpeakStage] Sent FinalizeSpeakQuest to client: %s"), *ULingoGameHelper::GetPlayerNameFromState(CurrentSpeaker));
181 }
182
183 // 서버 상태 초기화
184 CurrentSpeaker = nullptr;
186
187 // 서버 측 리스너에게 알림
189}
190
192{
193 if ( PlayerState == nullptr)
194 return false;
195
196 if ( CurrentSpeaker == nullptr)
197 return false;
198
199 return CurrentSpeaker == PlayerState;
200}
Declares the player-controlled character actor.
APlayerControl 선언에 대한 Doxygen 주석을 제공합니다.
YiSan 전반에서 사용하는 공용 인터페이스를 선언합니다.
#define PRINTLOG(fmt,...)
Definition GameLogging.h:30
UDialogManager 클래스를 선언합니다.
Speak Stage 시스템
int32 GetTotalQuestions() const
bool IsMyTurn(class ALingoPlayerState *lingo_player_state)
void NotifyAnswerComplete(class ALingoPlayerState *Player)
플레이어 답변 완료 알림 (Server에서 호출됨)
int32 CurrentStepIndex
현재 진행 단계 (질문 인덱스)
virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty > &OutLifetimeProps) const override
Replication 설정
void Multicast_NotifySpeakQuestStarted(const FString &PlayerName)
모든 클라이언트에게 SpeakQuest 시작 알림 전송 (Multicast RPC)
void EndStage()
현재 플레이어의 스테이지를 강제로 종료합니다.
void AdvanceStep()
다음 질문으로 진행합니다.
FString GetCurrentQuestion() const
FOnSpeakerChangedDelegate OnSpeakerChanged
현재 발화자가 변경될 때 호출되는 이벤트입니다.
void OnRep_CurrentSpeaker()
currentSpeaker 복제 알림
void StartStageForPlayer(class ALingoPlayerState *Player)
특정 플레이어에 대해 Speak Stage를 시작합니다.
ASpeakStageActor()
생성자
TObjectPtr< class ALingoPlayerState > CurrentSpeaker
현재 발화 권한을 가진 플레이어. nullptr이면 스테이지가 비어있음을 의미.
static FString GetPlayerNameFromState(const class ALingoPlayerState *PlayerState)
PlayerState에서 PlayerControl을 통해 사용자 이름 가져오기