KLingo Project Documentation 1.0.0
Unreal Engine 5.6 C++ Project Documentation
로딩중...
검색중...
일치하는것 없음
ALingoPlayerState.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 "ALingoPlayerState.h"
4
5#include "APlayerControl.h"
6#include "ASpeakStageActor.h"
7#include "EngineUtils.h"
8#include "UBroadcastManager.h"
9#include "Net/UnrealNetwork.h"
10#include "GameLogging.h"
11#include "UMainWidget.h"
12#include "Kismet/KismetSystemLibrary.h"
13
17
18void ALingoPlayerState::GetLifetimeReplicatedProps(TArray<class FLifetimeProperty>& OutLifetimeProps) const
19{
20 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
21
22 // Read Quest Data
23 DOREPLIFETIME(ALingoPlayerState, QuestRole);
24 DOREPLIFETIME(ALingoPlayerState, AttemptCount);
25
26 DOREPLIFETIME(ALingoPlayerState, SelectedWord1);
27 DOREPLIFETIME(ALingoPlayerState, SelectedWord2);
28 DOREPLIFETIME(ALingoPlayerState, bWrongWord1);
29 DOREPLIFETIME(ALingoPlayerState, bWrongWord2);
30
31 // Speak Quest Data
34
39}
40
42{
43 // TODO: GameMode, GameState, PlayerState 데이터를 참조하여 동적으로 생성
44 // 예시:
45 // - 현재 게임 상태 (메뉴, 인게임, 퀘스트 진행 등)
46 // - 플레이어 진행도 (레벨, 완료한 퀘스트 등)
47 // - 최근 대화 히스토리
48 // - NPC 정보 등
49
50 // 기본 Context 반환
51 return TEXT("You are a helpful assistant.");
52}
53
55{
56 // 각 퀘스트 상태 결정: 완료[V], 진행중[=], 미시작[X]
57 auto GetQuestStatus = [](bool bCompleted, bool bInProgress) -> const TCHAR*
58 {
59 if (bCompleted) return TEXT("V");
60 if (bInProgress) return TEXT("=");
61 return TEXT("X");
62 };
63
64 // R-L-S-W 퀘스트 상태 출력
65 FString StatusMsg = FString::Printf(TEXT("%s %s %s %s"),
66 GetQuestStatus(bReadQuestCompleted, bReadQuestIng),
68 GetQuestStatus(bSpeakQuestCompleted, bSpeakQuestIng),
69 GetQuestStatus(bWriteQuestCompleted, bWriteQuestIng));
70
71 // PRINT_STRING( TEXT("RLSW: %s"), *StatusMsg);
72
73 if (APlayerControl* PC = Cast<APlayerControl>(GetOwner()))
74 {
75 PC->UpdateQuestOrderWidget(StatusMsg);
76 }
77
78 // Host(서버)의 위젯 업데이트 (OnRep는 클라이언트에서만 호출됨)
79 if (HasAuthority())
80 {
81 if (APlayerControl* PC = Cast<APlayerControl>(GetOwner()))
82 {
83 PC->UpdateQuestInfoWidget();
84 }
85 }
86}
87
88//--------------------------------------------------------------//
89// Read Quest RPC Functions
90//--------------------------------------------------------------//
91
92void ALingoPlayerState::Server_SetSelectedWord1_Implementation(const FString& Word1)
93{
94 // Role 검증: OnlyQuestion2 역할은 심볼을 선택할 수 없음
95 if (QuestRole == EQuestRole::OnlyQuestion2)
96 {
97 PRINTLOG(TEXT("[PlayerState] ServerSetSelectedSymbol - Access denied for OnlyQuestion2 role"));
98 return;
99 }
100
101 SelectedWord1 = Word1;
102 bWrongWord1 = false; // 새로 선택하면 오답 플래그 초기화
103
104 PRINTLOG(TEXT("[PlayerState] Symbol selected: %s"), *Word1);
105}
106
107bool ALingoPlayerState::Server_SetSelectedWord1_Validate(const FString& Word1)
108{
109 // 빈 문자열도 허용 (선택 해제)
110 return true;
111}
112
113void ALingoPlayerState::Server_SetSelectedWord2_Implementation(const FString& Word2)
114{
115 // Role 검증: OnlyQuestion1 역할은 색상을 선택할 수 없음
116 if (QuestRole == EQuestRole::OnlyQuestion1)
117 {
118 PRINTLOG(TEXT("[PlayerState] ServerSetSelectedColor - Access denied for OnlyQuestion1 role"));
119 return;
120 }
121
122 SelectedWord2 = Word2;
123 bWrongWord2 = false; // 새로 선택하면 오답 플래그 초기화
124
125 PRINTLOG(TEXT("[PlayerState] Color selected: %s"), *Word2);
126}
127
128bool ALingoPlayerState::Server_SetSelectedWord2_Validate(const FString& Word2)
129{
130 // 빈 문자열도 허용 (선택 해제)
131 return true;
132}
133
135{
136 SpeakJudesResults.Add(EvaluationResult);
137
138 PRINTLOG(TEXT("[PlayerState] Evaluation result added - Total results: %d, Feedback: %s"),
139 SpeakJudesResults.Num(), *EvaluationResult.final_feedback);
140}
141
142void ALingoPlayerState::Server_NotifySpeakDataReady_Implementation()
143{
144 // 월드에서 SpeakStageActor를 찾습니다.
145 if (UWorld* World = GetWorld())
146 {
147 for (TActorIterator<ASpeakStageActor> It(World); It; ++It)
148 {
149 ASpeakStageActor* SpeakStage = *It;
150 if (SpeakStage)
151 {
152 // SpeakStage를 통해 퀘스트를 시작합니다.
153 SpeakStage->StartStageForPlayer(this);
154 PRINTLOG(TEXT("[ALingoPlayerState] Client is ready. Starting SpeakQuest for: %s"), *GetPlayerName());
155 return; // 첫 번째로 찾은 SpeakStage를 사용하고 종료
156 }
157 }
158 }
159
160 PRINTLOG(TEXT("[ALingoPlayerState] Server_NotifySpeakDataReady - ASpeakStageActor not found in world!"));
161}
162
163
164//--------------------------------------------------------------//
165// Read Quest OnRep Callbacks
166//--------------------------------------------------------------//
167
169{
170 PRINTLOG(TEXT("[PlayerState] OnRep_QuestRole: %s"), *ENUM_TO_NAME(EQuestRole, QuestRole));
171
172 // PC한테 콜을 날리고,
173 // PC가 판단해야해?
174 // 플레이어마다 QuestRole 정해져있음
175
176 APlayerControl* PC = Cast<APlayerControl>(GetOwner());
177 if (PC)
178 {
180 }
181}
182
184{
185 PRINTLOG(TEXT("[PlayerState] OnRep_SelectedSymbol: %s"), *SelectedWord1);
186}
187
189{
190 PRINTLOG(TEXT("[PlayerState] OnRep_SelectedColor: %s"), *SelectedWord2);
191}
192
194{
195 PRINTLOG(TEXT("[PlayerState] OnRep_SymbolWrong: %s"), bWrongWord1 ? TEXT("true") : TEXT("false"));
196}
197
199{
200 PRINTLOG(TEXT("[PlayerState] OnRep_ColorWrong: %s"), bWrongWord2 ? TEXT("true") : TEXT("false"));
201}
202
207
212
214{
215 if ( SpeakScenarioData.speak_quest_data.IsValidIndex(StepIndex))
216 {
217 Out = SpeakScenarioData.speak_quest_data[StepIndex];
218 return true;
219 }
220
221 return false;
222}
223
225{
226 if (!HasAuthority())
227 return;
228
231
233}
234
236{
237 if (!HasAuthority())
238 return;
239
240 bReadQuestCompleted = true;
242
244}
245
247{
248 if (!HasAuthority())
249 return;
250
253
255}
256
258{
259 if (!HasAuthority())
260 return;
261
264
266}
267
269{
270 if (!HasAuthority())
271 return;
272
273 bReadQuestIng = bInProgress;
274
276}
277
279{
280 if (!HasAuthority())
281 return;
282
283 bListenQuestIng = bInProgress;
284
286}
287
289{
290 if (!HasAuthority())
291 return;
292
293 bSpeakQuestIng = bInProgress;
294
296}
297
299{
300 if (!HasAuthority())
301 return;
302
303 bWriteQuestIng = bInProgress;
304
306}
307
309{
310 // 클라이언트에서 퀘스트 상태가 변경되었을 때 PlayerController의 위젯 업데이트 함수 호출
311 if (APlayerControl* PC = Cast<APlayerControl>(GetOwner()))
312 {
313 PC->UpdateQuestInfoWidget();
314
315 // 각 퀘스트 상태 결정: 완료[V], 진행중[=], 미시작[X]
316 auto GetQuestStatus = [](bool bCompleted, bool bInProgress) -> const TCHAR*
317 {
318 if (bCompleted) return TEXT("V");
319 if (bInProgress) return TEXT("=");
320 return TEXT("X");
321 };
322
323 // R-L-S-W 퀘스트 상태 출력
324 FString StatusMsg = FString::Printf(TEXT("%s %s %s %s"),
325 GetQuestStatus(bReadQuestCompleted, bReadQuestIng),
326 GetQuestStatus(bListenQuestCompleted, bListenQuestIng),
327 GetQuestStatus(bSpeakQuestCompleted, bSpeakQuestIng),
328 GetQuestStatus(bWriteQuestCompleted, bWriteQuestIng));
329
330 PC->UpdateQuestOrderWidget(StatusMsg);
331 }
332}
APlayerControl 선언에 대한 Doxygen 주석을 제공합니다.
EQuestRole
Read 퀘스트에서 플레이어의 역할을 정의합니다.
Definition EQuestRole.h:6
YiSan 전반에서 사용하는 공용 인터페이스를 선언합니다.
#define PRINTLOG(fmt,...)
Definition GameLogging.h:30
#define ENUM_TO_NAME(EnumType, Value)
Definition Macro.h:83
void AddSpeakJudes(const FResponseSpeakingJudes &EvaluationResult)
SpeakQuest 평가 결과를 저장합니다 (Server에서 호출됨)
FString SelectedWord2
선택한 색상 (문제2 답변)
bool GetCurrentSpeakQuestion(int32 StepIndex, FSpeakStageQuestion &Out) const
void SetListenQuestIng(bool bInProgress)
ListenQuest 진행 상태 설정 (서버에서만 호출)
bool bSpeakQuestIng
SpeakQuest 진행 여부 플래그
FString SelectedWord1
선택한 심볼 (문제1 답변)
void Server_NotifySpeakDataReady()
클라이언트가 SpeakScenarioData 수신 준비 완료를 서버에 알립니다.
void OnRep_SpeakScenarioData()
SpeakScenarioData 복제 알림 함수
void SetSpeakQuestCompleted()
SpeakQuest 완료 처리 (서버에서만 호출)
void SetWriteQuestIng(bool bInProgress)
WriteQuest 진행 상태 설정 (서버에서만 호출)
virtual void GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > &OutLifetimeProps) const override
void SetListenQuestCompleted()
ListenQuest 완료 처리 (서버에서만 호출)
bool bWriteQuestCompleted
WriteQuest 완료 여부 플래그
bool bSpeakQuestCompleted
SpeakQuest 완료 여부 플래그
TArray< struct FResponseSpeakingJudes > SpeakJudesResults
SpeakQuest 평가 결과 목록
void SetSpeakQuestIng(bool bInProgress)
SpeakQuest 진행 상태 설정 (서버에서만 호출)
bool bWriteQuestIng
WriteQuest 진행 여부 플래그
void SetReadQuestIng(bool bInProgress)
ReadQuest 진행 상태 설정 (서버에서만 호출)
FString GetChatContext() const
Chat AI의 Context를 반환합니다.
int32 AttemptCount
시도 횟수
bool bWrongWord1
심볼 오답 플래그
FResponseSpeakScenario SpeakScenarioData
void OnUpdateSpeakScenarioData()
SpeakScenarioData가 업데이트될 때 Host와 Client 모두에서 호출되는 공통 함수입니다.
void SetReadQuestCompleted()
ReadQuest 완료 처리 (서버에서만 호출)
bool bWrongWord2
색상 오답 플래그
void OnRep_SelectedWord2()
색상 선택 상태 복제 콜백
bool bReadQuestIng
ReadQuest 진행 여부 플래그
void OnRep_WrongWord2()
색상 오답 플래그 복제 콜백
EQuestRole QuestRole
플레이어 역할 (싱글/멀티에서 문제1, 문제2 구분)
void SetWriteQuestCompleted()
WriteQuest 완료 처리 (서버에서만 호출)
bool bListenQuestIng
ListenQuest 진행 여부 플래그
bool bListenQuestCompleted
ListenQuest 완료 여부 플래그
void OnRep_WrongWord1()
심볼 오답 플래그 복제 콜백
void OnRep_QuestState()
퀘스트 상태 변경 시 호출되는 복제 알림 함수
bool bReadQuestCompleted
ReadQuest 완료 여부 플래그
void OnRep_SelectedWord1()
심볼 선택 상태 복제 콜백
void UpdateQuestRole(EQuestRole QuestRole)
Speak Stage 시스템
void StartStageForPlayer(class ALingoPlayerState *Player)
특정 플레이어에 대해 Speak Stage를 시작합니다.
TArray< FSpeakStageQuestion > speak_quest_data
오디오 질문 목록
Speaking Questions 응답 구조체입니다.
SpeakQuest 오디오 질문 데이터 구조체입니다.