KLingo Project Documentation 1.0.0
Unreal Engine 5.6 C++ Project Documentation
로딩중...
검색중...
일치하는것 없음
FoodCourtManager.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
4#include "FoodCourtManager.h"
5
6#include "ADropper.h"
7#include "ALingoGameState.h"
8#include "Food.h"
9#include "ListenAnswer.h"
10#include "ULingoGameHelper.h"
11#include "Kismet/GameplayStatics.h"
12
14{
15 PrimaryActorTick.bCanEverTick = true;
16
17 ConstructorHelpers::FClassFinder<AFood> foodClass(TEXT("/Game/CustomContents/Blueprints/Interactables/BP_Food.BP_Food_C"));
18 if (foodClass.Succeeded())
19 {
20 FoodClass = foodClass.Class;
21 }
22}
23
25{
26 Super::BeginPlay();
27
29 {
30 GS->OnQuestScenarioDataUpdated.AddDynamic(this, &AFoodCourtManager::HandleQuestScenarioDataUpdated);
32 }
33}
34
35void AFoodCourtManager::EndPlay(const EEndPlayReason::Type EndPlayReason)
36{
37 Super::EndPlay(EndPlayReason);
38}
39
40// Called every frame
41void AFoodCourtManager::Tick(float DeltaTime)
42{
43 Super::Tick(DeltaTime);
44}
45
47{
48 ALingoGameState* GS = Cast<ALingoGameState>(GetWorld()->GetGameState());
49 if (GS)
50 {
51 // Food 스폰
52 AActor* FoundActor = UGameplayStatics::GetActorOfClass(GetWorld(), ADropper::StaticClass());
53 if (FoundActor)
54 {
55 Dropper = Cast<ADropper>(FoundActor);
56
59 }
60 }
61}
62
64{
65 // 서버에서만 실행
66 if (!HasAuthority()) return;
67
68 ALingoGameState* GS = Cast<ALingoGameState>(GetWorld()->GetGameState());
69 if (!GS) return;
70
71 const TArray<FScenarioTargetData>& ScenarioData = GS->GetListenScenarioData().target_data;
72
73 // 선택지 중복 안되도록 추리기
74 TSet<FWordInfo> FoodInfos;
75 TSet<FWordInfo> CityInfos;
76
77 for (int32 i=0; i<ScenarioData.Num(); i++)
78 {
79 auto SD = ScenarioData[i];
80
81 CityInfos.Add(SD.word1);
82 FoodInfos.Add(SD.word2);
83 }
84
85 // 음식 선택지 스폰 및 데이터 전달
86 int32 Index = 0;
87 for (const FWordInfo& FoodInfo : FoodInfos)
88 {
89 // 스폰하기
90 FVector SpawnLocation;
91 GetCurrentSpawnLocation(Index, FoodSpawnLocation, 0, SpawnLocation);
92
93 AListenAnswer* NewActor = GetWorld()->SpawnActor<AListenAnswer>(ListenAnswerClass, SpawnLocation, FRotator::ZeroRotator);
94 SpawnedListenAnswers.Add(NewActor);
95
96 // 데이터 전달
97 FTimerHandle TimerHandle;
98 GetWorldTimerManager().SetTimer(TimerHandle, FTimerDelegate::CreateLambda([this, NewActor, FoodInfo]
99 {
101 NewActor->AnswerData.word1 = FoodInfo;
102
103 // 로컬 위젯 업데이트
104 NewActor->UpdateMesh();
105 NewActor->UpdateNameWidget();
106
107 }), 1.f, false);
108
109 Index++;
110 }
111
112 Index = 0;
113 // 도시 이름 선택지 스폰 및 데이터 전달
114 for (const FWordInfo& CityInfo : CityInfos)
115 {
116 // 스폰하기
117 FVector SpawnLocation;
118 GetCurrentSpawnLocation(Index, CitySpawnLocation, 3, SpawnLocation);
119
120 AListenAnswer* NewActor = GetWorld()->SpawnActor<AListenAnswer>(ListenAnswerClass, SpawnLocation, FRotator::ZeroRotator);
121 SpawnedListenAnswers.Add(NewActor);
122
123 // 데이터 전달
124 FTimerHandle TimerHandle;
125 GetWorldTimerManager().SetTimer(TimerHandle, FTimerDelegate::CreateLambda([this, NewActor, CityInfo]
126 {
128 NewActor->AnswerData.word1 = CityInfo;
129
130 // 로컬 위젯 업데이트
131 NewActor->UpdateMesh();
132 NewActor->UpdateNameWidget();
133
134 }), 1.f, false);
135
136 Index++;
137 }
138}
139
140void AFoodCourtManager::GetCurrentSpawnLocation(int32 Index, FVector InitialLocation, int32 Dir, FVector& OutSpawnLocation)
141{
142 // 2열로 배치
143 int32 Row = Index / 2;
144 int32 Col = Index % 2;
145
146 // Dir 값에 따라 스폰 방향 변경
147 // 0: 전방-우측, 1: 전방-좌측, 2: 후방-우측, 3: 후방-좌측
148 FVector Offset;
149
150 switch (Dir)
151 {
152 case 0:
153 Offset = FVector(Row*SpawnDistance, Col*SpawnDistance, 0.0f);
154 break;
155 case 1:
156 Offset = FVector(-Col*SpawnDistance, Row*SpawnDistance, 0.0f);
157 break;
158 case 2:
159 Offset = FVector(-Row*SpawnDistance, -Col*SpawnDistance, 0.0f);
160 break;
161 case 3:
162 Offset = FVector(Col*SpawnDistance, -Row*SpawnDistance, 0.0f);
163 break;
164 default:
165 Offset = FVector(Row*SpawnDistance, Col*SpawnDistance, 0.0f);
166 break;
167 }
168
169 OutSpawnLocation = InitialLocation + Offset;
170}
171
173{
174 for (AActor* Actor : SpawnedListenAnswers)
175 {
176 if (AListenAnswer* Answer = Cast<AListenAnswer>(Actor))
177 {
178 Answer->AnswerData.word1.name = "";
179 Answer->UpdateNameWidget();
180 }
181 }
182}
183
185{
187 {
188 if (GS->GetCurrentQuestType() != EQuestType::Listen)
189 return;
190
192 }
193}
194
void SetSpawnClass(TSubclassOf< AActor > InClass)
스폰 전에 Dropper가 어떤 클래스를 스폰할지 등록
Definition ADropper.h:45
bool RequestSpawn()
스폰 요청 (서버에서만 동작)
Definition ADropper.cpp:49
virtual void Tick(float DeltaTime) override
TArray< AActor * > SpawnedListenAnswers
virtual void BeginPlay() override
TSubclassOf< AActor > FoodClass
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
void GetCurrentSpawnLocation(int32 Index, FVector InitialLocation, int32 Dir, FVector &OutSpawnLocation)
TSubclassOf< class AListenAnswer > ListenAnswerClass
class ADropper * Dropper
FORCEINLINE const FResponseListenScenario & GetListenScenarioData() const
void UpdateNameWidget()
FListenAnswerData AnswerData
static class ALingoGameState * GetLingoGameState(const UObject *WorldContextObject)
FWordInfo word1
시나리오 단어 정보
EAnswerType AnswerType
정답 타입
TArray< FScenarioTargetData > target_data
단어 정보 구조체