17#include "InputCoreTypes.h"
33#include "HairStrandsInterface.h"
45#include "Camera/CameraComponent.h"
46#include "Components/InputComponent.h"
47#include "Components/CapsuleComponent.h"
48#include "GameFramework/CharacterMovementComponent.h"
49#include "GameFramework/PlayerController.h"
50#include "Net/UnrealNetwork.h"
51#include "Blueprint/UserWidget.h"
52#include "Components/Image.h"
53#include "Components/StaticMeshComponent.h"
54#include "Engine/StaticMesh.h"
55#include "GameFramework/PlayerState.h"
56#include "Kismet/KismetMathLibrary.h"
59#define MAINWIDGET_PATH TEXT("/Game/CustomContents/UI/WBP_MainWidget.WBP_MainWidget_C")
60#define TOASTWIDGET_PATH TEXT("/Game/CustomContents/UI/WBP_ToastWidget.WBP_ToastWidget_C")
62#define HOOKMESHPATH_PATH TEXT("/Game/CustomContents/Character/Asset/MiniOwl/MiniOwlbot.MiniOwlbot")
66 PrimaryActorTick.bCanEverTick =
true;
68 GetCapsuleComponent()->InitCapsuleSize(45.f, 102.0f);
69 GetMesh()->SetRelativeLocationAndRotation(FVector(0, 0, -100), FRotator(0, -90, 0));
70 GetMesh()->SetRelativeScale3D(FVector(1.5));
73 bUseControllerRotationPitch =
false;
74 bUseControllerRotationYaw =
true;
75 bUseControllerRotationRoll =
false;
86 FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT(
"FollowCamera"));
89 FollowCamera->SetRelativeLocationAndRotation(FVector(0.235242,-14.285715,24.304751), FRotator(90, 90, 0));
92 GetCharacterMovement()->RotationRate = FRotator(0.0f, 500.0f, 0.0f);
93 GetCharacterMovement()->MaxWalkSpeed =
WalkSpeed;
94 GetCharacterMovement()->bOrientRotationToMovement =
false;
96 HoldPosition = CreateDefaultSubobject<USceneComponent>(TEXT(
"HoldPosition"));
98 HoldPosition->SetRelativeLocation(FVector(80.952382,0,-14.285714));
104 InteractionSystem = CreateDefaultSubobject<UInteractionSystem>(TEXT(
"InteractionSystem"));
105 HookSystem = CreateDefaultSubobject<UHookSystem>(TEXT(
"HookSystem"));
109 HookCable = CreateDefaultSubobject<UStaticMeshComponent>(TEXT(
"HookCable"));
112 HookCable->SetCollisionEnabled(ECollisionEnabled::NoCollision);
113 HookCable->SetMobility(EComponentMobility::Movable);
114 HookCable->SetUsingAbsoluteLocation(
true);
115 HookCable->SetUsingAbsoluteRotation(
true);
117 static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderMesh(TEXT(
"/Engine/BasicShapes/Cylinder.Cylinder"));
118 if (CylinderMesh.Succeeded())
119 HookCable->SetStaticMesh(CylinderMesh.Object);
120 HookCable->SetRelativeScale3D(FVector(0.05f, 0.05f, 1.0f));
122 HookProjectileMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT(
"HookProjectileMesh"));
127 static ConstructorHelpers::FObjectFinder<UStaticMesh> HookMesh(
HOOKMESHPATH_PATH);
128 if (HookMesh.Succeeded())
135 miniOwlBot = CreateDefaultSubobject<UChildActorComponent>(TEXT(
"miniOwlBot"));
136 miniOwlBot->SetupAttachment(GetRootComponent());
138 ConstructorHelpers::FClassFinder<AMiniOwlBot> miniOwlBotRef(TEXT(
"/Game/CustomContents/Blueprints/BP_MiniOwlBot.BP_MiniOwlBot_C"));
139 if (miniOwlBotRef.Succeeded())
141 miniOwlBot->SetChildActorClass(miniOwlBotRef.Class);
154 GetMesh()->SetOwnerNoSee(
true);
161 MoveComp = this->GetCharacterMovement();
167 if (
auto DM = UBroadcastManager::Get(GetWorld()))
194 FTimerHandle TimerHandle;
195 GetWorldTimerManager().SetTimer(TimerHandle, FTimerDelegate::CreateLambda([
this, GS]
197 GS->SetAllCompassVisibility(
false);
198 GS->SetCompassVisibilityByTag(
"ReadQuestStart",
true);
203 if (IsLocallyControlled())
213 PRINTLOG(TEXT(
"%s"), Cast<AMiniOwlBot>(
miniOwlBot->GetChildActor()) ==
nullptr ? TEXT(
"miniOwlBot is null") : TEXT(
"miniOwlBot is not null"));
214 if (
auto InChildActor = Cast<AMiniOwlBot>(
miniOwlBot->GetChildActor()))
216 if (IsLocallyControlled())
218 Cast<AMiniOwlBot>(InChildActor)->SetActorHiddenInGame(
false);
222 Cast<AMiniOwlBot>(InChildActor)->SetActorHiddenInGame(
true);
229 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
238 if (
UPopupManager* PopupMgr = UPopupManager::Get(GetWorld()))
240 if (PopupMgr->ShouldBlockPlayerControl())
250 FString MapName = GetWorld()->GetMapName();
251 MapName.RemoveFromStart(GetWorld()->StreamingLevelsPrefix);
253 if ( MapName.Contains(TEXT(
"Map1")) )
255 else if ( MapName.Contains(TEXT(
"Game")) )
257 else if ( MapName.Contains(TEXT(
"Person")) )
271 auto PC = Cast<APlayerControl>(GetController());
284 MainWidget->UpdateRoomWidget( GS->GetRoomLevel(), GS->GetRoomId());
286 MainWidget->CompassWidget->SetVisibility( ESlateVisibility::Visible );
287 MainWidget->VoiceRecording->SetVisibility( ESlateVisibility::Visible );
290 if (PC->HasUserInfo() )
292 MainWidget->UpdateStateWidget( PC->GetUserId(), PC->GetUserName());
298 FTimerHandle RetryTimer;
299 GetWorld()->GetTimerManager().SetTimer(RetryTimer, [
this, PC]()
301 if ( PC->GetUserId())
303 MainWidget->UpdateStateWidget( PC->GetUserId(), PC->GetUserName());
319 APlayerController* PC = Cast<APlayerController>(GetController());
330 Super::PossessedBy(NewController);
332 APlayerState* PS = GetPlayerState();
337 int32 PlayerIndex = -1;
338 if (AGameStateBase* GS = GetWorld()->GetGameState())
339 PlayerIndex = GS->PlayerArray.IndexOfByKey(PS);
349 Super::Tick(DeltaTime);
354 float CameraRotationZ =
FollowCamera->GetComponentRotation().Yaw;
361 if (
auto childOwlBot = Cast<AMiniOwlBot>(
miniOwlBot->GetChildActor()))
363 childOwlBot->UpdateLocation(DeltaTime);
369 Super::OnRep_Controller();
371 if (IsLocallyControlled())
378 PRINTLOG(TEXT(
"%s"), Cast<AMiniOwlBot>(
miniOwlBot->GetChildActor()) ==
nullptr ? TEXT(
"miniOwlBot is null") : TEXT(
"miniOwlBot is not null"));
379 if (
auto InChildActor = Cast<AMiniOwlBot>(
miniOwlBot->GetChildActor()))
381 if (IsLocallyControlled())
383 Cast<AMiniOwlBot>(InChildActor)->SetActorHiddenInGame(
false);
387 Cast<AMiniOwlBot>(InChildActor)->SetActorHiddenInGame(
true);
412 USkeletalMeshComponent* MeshComp = GetMesh();
417 for (int32 i = 0; i < MeshComp->GetNumMaterials(); ++i)
419 UMaterialInterface* Material = MeshComp->GetMaterial(i);
423 UMaterialInstanceDynamic* DynamicMaterial = Cast<UMaterialInstanceDynamic>(Material);
424 if (!DynamicMaterial)
425 DynamicMaterial = MeshComp->CreateAndSetMaterialInstanceDynamic(i);
428 DynamicMaterial->SetScalarParameterValue(FName(
"Another"),
AnotherValue);
432 auto PS = GetPlayerState<ALingoPlayerState>();
435 PS->RefreshQuestState();
441 if ( InMovementMode == MOVE_None)
444 auto Movement = this->GetCharacterMovement();
446 Movement->SetMovementMode( InMovementMode );
447 this->bUseControllerRotationYaw =
false;
448 this->bUseControllerRotationPitch =
false;
449 Movement->bOrientRotationToMovement =
true;
457void APlayerActor::Cmd_StopMove_Implementation()
462void APlayerActor::Cmd_Run_Implementation()
470void APlayerActor::Cmd_Move_Implementation(
const FVector2D& Axis)
481 const FRotator ControlRotation = Controller->GetControlRotation();
482 const EMovementMode CurrentMovementMode = GetCharacterMovement()->MovementMode;
484 if (CurrentMovementMode == MOVE_Walking || CurrentMovementMode == MOVE_Falling)
487 const FRotator YawRotation(0.0f, ControlRotation.Yaw, 0.0f);
490 const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
491 const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
493 AddMovementInput(ForwardDirection, Axis.Y);
494 AddMovementInput(RightDirection, Axis.X);
498void APlayerActor::Cmd_Look_Implementation(
const FVector2D& Axis)
503 AddControllerYawInput(Axis.X);
504 AddControllerPitchInput(Axis.Y);
507void APlayerActor::Cmd_Jump_Implementation()
515void APlayerActor::Cmd_RecordStart_Implementation()
523void APlayerActor::Cmd_RecordEnd_Implementation()
528void APlayerActor::Cmd_Info_Implementation()
535 auto PS = GetPlayerState<ALingoPlayerState>();
537 if ( PS->bReadQuestIng &&
538 !PS->bReadQuestCompleted )
540 if (
auto Popup = UPopupManager::ShowPopupAs<UPopup_ReadQuest>(GetWorld(), EPopupType::ReadQuest))
541 Popup->InitRead(GS->ReadScenarioData);
544 PS->bListenQuestIng &&
545 !PS->bListenQuestCompleted )
549 if ( QuestRole == EQuestRole::Both)
551 else if ( QuestRole == EQuestRole::OnlyQuestion1)
553 else if ( QuestRole == EQuestRole::OnlyQuestion2)
556 else if ( PS->bSpeakQuestIng &&
557 !PS->bSpeakQuestCompleted )
561 if ( SpeakStageActor->IsMyTurn(PS) )
571 return Cast<AMiniOwlBot>(
miniOwlBot->GetChildActor());
576 auto PS = GetPlayerState<ALingoPlayerState>();
579 if (PS->GetCurrentSpeakQuestion(StepIndex, CurrentSpeakQuestion))
599 if (
auto KLingoNetwork = UKLingoNetworkSystem::Get(GetWorld()))
603 KLingoNetwork->RequestListenAudio(
617 UDialogManager::Get(GetWorld())->ShowToast(*ResponseData.
audio_text);
627 if (
auto KLingoNetwork = UKLingoNetworkSystem::Get(GetWorld()))
631 KLingoNetwork->RequestListenAudio(
649void APlayerActor::ServerRPC_StopMove_Implementation()
654void APlayerActor::MulticastRPC_StopMove_Implementation()
657 GetCharacterMovement()->MaxWalkSpeed =
WalkSpeed;
660void APlayerActor::ServerRPC_DoJumpStart_Implementation()
665void APlayerActor::MulticastRPC_DoJumpStart_Implementation()
670void APlayerActor::ServerRPC_DoJump_Implementation()
675void APlayerActor::MulticastRPC_DoJump_Implementation()
681void APlayerActor::ServerRPC_DoRun_Implementation()
686void APlayerActor::MulticastRPC_DoRun_Implementation()
688 if (
bIsJumpStart || GetMovementComponent()->IsFalling())
return;
693 GetCharacterMovement()->MaxWalkSpeed =
WalkSpeed;
698 GetCharacterMovement()->MaxWalkSpeed =
RunSpeed;
713 ClientRPC_ShowGameMessage_Implementation(Message);
717void APlayerActor::ClientRPC_ShowGameMessage_Implementation(
const FString& Message)
720 if (
UDialogManager* DialogManager = UDialogManager::Get(GetWorld()))
722 DialogManager->ShowToast(Message);
732 if (!IsLocallyControlled())
735 PRINTLOG(TEXT(
"APlayerActor::OnTeleportAllPlayers - Start teleport to %s"), *TargetTransform.ToString());
743 PRINTLOG(TEXT(
"APlayerActor::OnTeleportAllPlayers - MainWidget is null"));
750 PRINTLOG(TEXT(
"APlayerActor::OnTeleportAllPlayers - FadeWidget is null"));
761void APlayerActor::ServerRPC_Teleport_Implementation(FTransform TargetTransform)
763 SetActorLocation(TargetTransform.GetLocation());
776 if (
auto PS = GetPlayerState<ALingoPlayerState>())
778 PS->AddSpeakJudes(Response);
785void APlayerActor::Server_NotifyConfirmSpeakJudes_Implementation()
791 if (
auto PS = GetPlayerState<ALingoPlayerState>())
795 SpeakStage->NotifyAnswerComplete(PS);
803 if (
auto Popup = UPopupManager::ShowPopupAs<UPopup_SpeakJudes>(GetWorld(), EPopupType::SpeakJudes))
806 FOnSpeakJudesConfirmDelegate OnConfirm;
807 OnConfirm.BindLambda([
this]()
812 Popup->InitPopup(Response, OnConfirm);
848 TArray<AActor*> TrackedActors;
850 TArray<AActor*> TempActors;
853 UGameplayStatics::GetAllActorsOfClass(GetWorld(), AContactTrigger::StaticClass(), TempActors);
854 TrackedActors.Append(TempActors);
857 UGameplayStatics::GetAllActorsOfClass(GetWorld(), ALuggageHolder::StaticClass(), TempActors);
858 TrackedActors.Append(TempActors);
861 UGameplayStatics::GetAllActorsOfClass(GetWorld(), AOrderKiosk::StaticClass(), TempActors);
862 TrackedActors.Append(TempActors);
865 UGameplayStatics::GetAllActorsOfClass(GetWorld(), AWheatly::StaticClass(), TempActors);
866 TrackedActors.Append(TempActors);
869 UGameplayStatics::GetAllActorsOfClass(GetWorld(), ATeleportTrigger::StaticClass(), TempActors);
870 TrackedActors.Append(TempActors);
873 UGameplayStatics::GetAllActorsOfClass(GetWorld(), AQuestionnaireKiosk::StaticClass(), TempActors);
874 TrackedActors.Append(TempActors);
877 UGameplayStatics::GetAllActorsOfClass(GetWorld(), AEvaluationTrigger::StaticClass(), TempActors);
878 TrackedActors.Append(TempActors);
881 UGameplayStatics::GetAllActorsOfClass(GetWorld(), APlayerActor::StaticClass(), TempActors);
882 for (AActor* OtherActor : TempActors)
884 if (OtherActor !=
this)
885 TrackedActors.Add(OtherActor);
889 for (AActor* TrackedActor : TrackedActors)
891 if (!TrackedActor)
continue;
895 if (!Target)
continue;
922 Marker->SetBrushFromTexture(NewTexture);
931 float TargetYaw = RelativeRotation.Yaw;
937 float Distance = FVector::Dist(GetActorLocation(), TrackedActor->GetActorLocation());
942 TArray<AActor*> ActorsToRemove;
945 if (!Pair.Key || !TrackedActors.Contains(Pair.Key))
951 ActorsToRemove.Add(Pair.Key);
955 for (AActor* Actor : ActorsToRemove)
964 FVector CapsuleLocation = GetCapsuleComponent()->GetComponentLocation();
967 FRotator CapsuleRotation = GetCapsuleComponent()->GetComponentRotation();
970 FVector TargetLocation = Target->GetActorLocation();
973 FRotator LookAtRotation = UKismetMathLibrary::FindLookAtRotation(
974 CapsuleLocation, TargetLocation);
977 FRotator RelativeRotation = UKismetMathLibrary::NormalizedDeltaRotator(
978 LookAtRotation,CapsuleRotation);
981 return RelativeRotation;
986 if (!IsLocallyControlled())
993 const int RoomLevel = GS->GetRoomLevel();
994 const int RoomId = NewRoomId;
996 MainWidget->UpdateRoomWidget(RoomLevel, RoomId);
1003 if (!IsLocallyControlled())
1010 const int RoomLevel = NewRoomLevel;
1011 const int RoomId = GS->GetRoomId();
1013 MainWidget->UpdateRoomWidget(RoomLevel, RoomId);
#define HOOKMESHPATH_PATH
Declares the player-controlled character actor.
APlayerControl 선언에 대한 Doxygen 주석을 제공합니다.
EQuestRole
Read 퀘스트에서 플레이어의 역할을 정의합니다.
FComponentHelper 구조체를 선언합니다.
YiSan 전반에서 사용하는 공용 인터페이스를 선언합니다.
#define PRINTLOG(fmt,...)
#define PRINT_STRING(fmt,...)
UDialogManager 클래스를 선언합니다.
KLingo API 요청을 담당하는 서브시스템을 선언합니다.
STT·GPT·TTS 파이프라인을 연결하는 음성 대화 컴포넌트를 선언합니다.
EQuestRole QuestRole
플레이어 역할 (싱글/멀티에서 문제1, 문제2 구분)
Main character driven directly by the player.
void ApplyAnotherValue()
Another 머티리얼 파라미터를 실제로 적용합니다 (서버/클라이언트 공통)
TObjectPtr< class UVoiceConversationSystem > VoiceConversationSystem
void OnGameMessage(const FString &Message)
게임 이벤트 메시지를 수신합니다.
TObjectPtr< class UHookSystem > HookSystem
bool IsControlEnabled() const
플레이어 조작이 가능한지 확인합니다
FTransform PendingTeleportTransform
텔레포트 목표 위치
void OnResponseSpeakAudio(FResponseListenAudio &ResponseData, bool bWasSuccessful)
void RequestSpeakAudio(const FString &AudioText)
TObjectPtr< class UMainWidget > MainWidget
메인 UI 위젯 인스턴스
TObjectPtr< class UChildActorComponent > miniOwlBot
virtual void PossessedBy(AController *NewController) override
TObjectPtr< class UCharacterMovementComponent > MoveComp
void MulticastRPC_DoRun()
void MulticastRPC_DoJumpStart()
void RecoveryMovementMode(const EMovementMode InMovementMode)
EQuestRole GetQuestRole()
virtual void OnRep_Controller() override
float AnotherValue
2P 구분을 위한 머티리얼 파라미터 (0=1P, 1=2P)
TObjectPtr< class UStaticMeshComponent > HookProjectileMesh
TMap< AActor *, class UImage * > CompassMarkerMap
virtual void Tick(float DeltaTime) override
TSubclassOf< class UToastWidget > ToastWidgetClass
void CreateMainWidget()
메인 위젯을 생성하고 뷰포트에 추가합니다.
TObjectPtr< class UInteractionSystem > InteractionSystem
void Server_NotifyConfirmSpeakJudes()
SpeakJudge 팝업 확인 버튼 클릭을 서버에 알립니다 (Server RPC)
TObjectPtr< class UStaticMeshComponent > HookCable
TSubclassOf< class UMainWidget > MainWidgetClass
메인 위젯 블루프린트 클래스
TObjectPtr< class UCameraComponent > FollowCamera
void Client_ShowSpeakJudesPopup(const struct FResponseSpeakingJudes &Response)
SpeakJudge 결과 팝업을 클라이언트에 표시합니다 (Client RPC)
void OnResponseListenAudio(FResponseListenAudio &ResponseData, bool bWasSuccessful)
virtual void GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > &OutLifetimeProps) const override
void ServerRPC_Teleport(FTransform TargetTransform)
void ClientRPC_ShowGameMessage(const FString &Message)
클라이언트에서 게임 메시지를 표시합니다.
void PlaySpeakInfo(int32 QuestStep)
void RequestListenAudio(const FString &AudioText)
void ServerRPC_DoJumpStart()
void MulticastRPC_DoJump()
void OnRoomIdUpdated(int64 NewRoomId)
void OnFadeOutCompleteForTeleport()
페이드 아웃 완료 후 텔레포트 실행
void OnTeleportAllPlayers(FTransform TargetTransform)
텔레포트 이벤트 핸들러
void UpdateCompassMarkers()
void OnRep_AnotherValue()
TObjectPtr< class USceneComponent > HoldPosition
FRotator FindRelativeRotationAtTarget(AActor *Target)
void ServerRPC_StopMove()
void PlayTTSAudio(const TArray< uint8 > &AudioData)
TTS 오디오를 재생합니다. VoiceConversationSystem으로 전달합니다.
class AMiniOwlBot * GetMiniOwlBot() const
TObjectPtr< class UToastWidget > ToastWidget
void MulticastRPC_StopMove()
virtual void BeginPlay() override
void OnRoomLevelUpdated(int32 NewRoomLevel)
virtual bool ShouldShowOnCompass() const
ECompassMarkerType GetCompassMarkerType()
ECompassMarkerType MarkerType
토스트 메시지와 같은 간단한 다이얼로그 위젯의 표시를 관리하는 LocalPlayer 서브시스템입니다.
static void HideMouseCursor(const UObject *WorldContextObject)
마우스 커서를 숨기고 게임 전용 입력 모드로 설정합니다.
static class ASpeakStageActor * GetSpeakStageActor(const UObject *WorldContextObject)
static class ALingoGameState * GetLingoGameState(const UObject *WorldContextObject)
static T * LoadAsset(const TCHAR *Path)
TArray< uint8 > audio_base64
Speaking Questions 응답 구조체입니다.
SpeakQuest 오디오 질문 데이터 구조체입니다.
FString GetQuestionMessage() const