10#include "GameFramework/Character.h"
14UTutorialComponent::UTutorialComponent()
18 PrimaryComponentTick.bCanEverTick =
true;
22 CurrentStep = ETutorialStep::Waiting;
23 OwnerController =
nullptr;
28void UTutorialComponent::BeginPlay()
33 OwnerController = Cast<APlayerController>(GetOwner());
36 UE_LOG(LogTemp, Error, TEXT(
"TutorialComponent: Owner is not a PlayerController!"));
40 LastControlRotation = OwnerController->GetControlRotation();
45void UTutorialComponent::TickComponent(
float DeltaTime, ELevelTick TickType,
46 FActorComponentTickFunction* ThisTickFunction)
48 Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
52 FRotator CurrentRotation = OwnerController->GetControlRotation();
55 if (CurrentStep != ETutorialStep::Completed && CurrentStep != ETutorialStep::Waiting)
57 CheckInputConditions();
60 LastControlRotation = CurrentRotation;
64void UTutorialComponent::StartTutorial()
66 SetStep(ETutorialStep::MouseLook);
69void UTutorialComponent::AdvanceToNextStep()
71 UE_LOG(LogTemp, Warning, TEXT(
"[AdvanceToNextStep] Called! CurrentStep: %d"), (int32)CurrentStep);
76 BM->SendHideTutorialMessage();
80 UE_LOG(LogTemp, Warning, TEXT(
"[AdvanceToNextStep] NextStep: %d"), (int32)NextStep);
86 CurrentStep = NewStep;
87 bInputConditionMet =
false;
90 bGrabbedLuggage =
false;
91 bPickedUpSomething =
false;
92 bInteractedWithSwitch =
false;
96 BM->SendTutorialStepChanged(OwnerController, NewStep);
98 FText TutorialMessage = GetTutorialMessage(NewStep);
99 if (NewStep == ETutorialStep::Completed)
101 BM->SendTutorMessage(TutorialMessage);
106 PC->OnTutorialCompleted();
111 BM->SendShowTutorialMessage(TutorialMessage);
115 UE_LOG(LogTemp, Log, TEXT(
"Tutorial Step Changed: %d"), (int32)NewStep);
118bool UTutorialComponent::IsTutorialCompleted()
const
120 return CurrentStep == ETutorialStep::Completed;
123void UTutorialComponent::CheckInputConditions()
125 if (!OwnerController || bInputConditionMet)
return;
127 bool bConditionMet =
false;
131 case ETutorialStep::MouseLook:
132 bConditionMet = CheckMouseLookInput();
134 case ETutorialStep::Movement:
135 bConditionMet = CheckMovementInput();
137 case ETutorialStep::Sprint:
138 bConditionMet = CheckSprintInput();
140 case ETutorialStep::Jump:
141 bConditionMet = CheckJumpInput();
143 case ETutorialStep::PickUp:
144 bConditionMet = CheckPickUpInput();
146 case ETutorialStep::GrabGun:
147 bConditionMet = CheckGrabGunInput();
149 case ETutorialStep::Interaction:
150 bConditionMet = CheckInteractionInput();
156 if (bConditionMet && !bInputConditionMet)
158 UE_LOG(LogTemp, Warning, TEXT(
"[CheckInputConditions] Condition met! Advancing to next step..."));
159 bInputConditionMet =
true;
160 OnInputConditionMet();
164void UTutorialComponent::OnInputConditionMet()
166 if (AdvanceDelayTimerHandle.IsValid())
168 GetWorld()->GetTimerManager().ClearTimer(AdvanceDelayTimerHandle);
171 GetWorld()->GetTimerManager().SetTimer(AdvanceDelayTimerHandle,
this,
172 &UTutorialComponent::AdvanceToNextStep, 1.5f,
false);
179 case ETutorialStep::Waiting:
return ETutorialStep::MouseLook;
180 case ETutorialStep::MouseLook:
return ETutorialStep::Movement;
181 case ETutorialStep::Movement:
return ETutorialStep::Sprint;
182 case ETutorialStep::Sprint:
return ETutorialStep::Jump;
183 case ETutorialStep::Jump:
return ETutorialStep::GrabGun;
184 case ETutorialStep::GrabGun:
return ETutorialStep::PickUp;
185 case ETutorialStep::PickUp:
return ETutorialStep::Interaction;
186 case ETutorialStep::Interaction:
return ETutorialStep::Completed;
187 default:
return ETutorialStep::Completed;
191bool UTutorialComponent::CheckMouseLookInput()
const
193 if (!OwnerController)
return false;
195 FRotator CurrentRotation = OwnerController->GetControlRotation();
196 FRotator DeltaRotation = CurrentRotation - LastControlRotation;
199 return FMath::Abs(DeltaRotation.Pitch) > 0.5f || FMath::Abs(DeltaRotation.Yaw) > 0.5f;
202bool UTutorialComponent::CheckMovementInput()
const
204 if (!OwnerController)
return false;
206 APawn* Pawn = OwnerController->GetPawn();
207 if (!Pawn)
return false;
210 FVector InputVector = Pawn->GetLastMovementInputVector();
211 return !InputVector.IsNearlyZero();
214bool UTutorialComponent::CheckSprintInput()
const
216 if (!OwnerController)
return false;
219 return OwnerController->IsInputKeyDown(EKeys::LeftShift);
222bool UTutorialComponent::CheckJumpInput()
const
224 if (!OwnerController)
return false;
226 return OwnerController->IsInputKeyDown(EKeys::SpaceBar);
229bool UTutorialComponent::CheckPickUpInput()
const
232 return bPickedUpSomething;
235bool UTutorialComponent::CheckGrabGunInput()
const
239 return bGrabbedLuggage;
242bool UTutorialComponent::CheckInteractionInput()
const
246 return bInteractedWithSwitch;
249FText UTutorialComponent::GetTutorialMessage(
ETutorialStep Step)
const
253 case ETutorialStep::MouseLook:
254 return FText::FromString(TEXT(
"Move mouse to look around"));
255 case ETutorialStep::Movement:
256 return FText::FromString(TEXT(
"Press W/A/S/D to walk"));
257 case ETutorialStep::Sprint:
258 return FText::FromString(TEXT(
"Press Shift to sprint"));
259 case ETutorialStep::Jump:
260 return FText::FromString(TEXT(
"Press Spacebar to jump"));
261 case ETutorialStep::PickUp:
262 return FText::FromString(TEXT(
"Left Click to pick up"));
263 case ETutorialStep::GrabGun:
264 return FText::FromString(TEXT(
"Right Click to grab things from far away"));
265 case ETutorialStep::Interaction:
266 return FText::FromString(TEXT(
"Press E to activate switch"));
267 case ETutorialStep::Completed:
268 return FText::FromString(TEXT(
"Tutorial finished!"));
270 return FText::GetEmpty();
274void UTutorialComponent::OnObjectGrabbed(AActor* GrabbedObject)
276 if (CurrentStep != ETutorialStep::GrabGun)
return;
278 if (GrabbedObject && GrabbedObject->IsA(Aluggage::StaticClass()))
280 bGrabbedLuggage =
true;
284void UTutorialComponent::OnObjectPickedUp(AActor* PickedObject)
286 if (CurrentStep != ETutorialStep::PickUp)
return;
288 if (PickedObject && PickedObject->IsA(Aluggage::StaticClass()))
290 bPickedUpSomething =
true;
294void UTutorialComponent::OnObjectInteracted(AActor* InteractedObject)
296 if (CurrentStep != ETutorialStep::Interaction)
return;
298 if (InteractedObject && InteractedObject->IsA(APedestalSwitch::StaticClass()))
300 bInteractedWithSwitch =
true;
APlayerControl 선언에 대한 Doxygen 주석을 제공합니다.
게임 내 전역 이벤트를 중계하는 중앙 이벤트 버스(Event Bus) 서브시스템입니다.