Payback 0.0.1
CK Graduation Project
로딩중...
검색중...
일치하는것 없음
USituationManagementSubsystem 클래스 참조

#include <SituationManagementSubsystem.h>

USituationManagementSubsystem에 대한 상속 다이어그램 :
Inheritance graph
USituationManagementSubsystem에 대한 협력 다이어그램:
Collaboration graph

Public 멤버 함수

virtual void OnWorldBeginPlay (UWorld &InWorld) override
 
virtual void Deinitialize () override
 
void EquipSituation (const FName &SituationID)
 
TArray< USituationBase * > GetEquippedSituations () const
 
TArray< USituationBase * > GetActiveSituations () const
 
void PushTimeFreeze ()
 
void PopTimeFreeze ()
 

Public 속성

FOnSituationEquipped OnSituationEquipped
 
FOnSituationBuffChanged OnSituationBuffApplied
 
FOnSituationBuffChanged OnSituationBuffRemoved
 

Protected 멤버 함수

void EnsurePlayerBinding ()
 
void HandleLevelUp (int32 NewLevel)
 
void TryOpenNextSelection ()
 
void OpenSelectPopup ()
 
void HandleSelectPopupClosed (UPopupWidgetBase *Popup, EPopupResult Result)
 
void HandleSituationTriggered (USituationBase *Situation)
 
void HandleBuffExpired (USituationBase *Situation)
 
void HandleWeaponChanged (const FGameplayTag &PreviousWeaponTag, const FGameplayTag &NewWeaponTag)
 
void EnsureWeaponBinding (APlayerController *PlayerController)
 
APlayerController * ResolvePlayerController ()
 
USituationBaseCreateSituation (UStageManifest *Manifest, const FDT_SituationTable &SituationRow)
 

Protected 속성

TArray< TObjectPtr< USituationBase > > EquippedSituations
 
TArray< TObjectPtr< USituationBase > > PendingChoices
 
int32 PendingSelectionCount = 0
 
int32 TimeFreezeCount = 0
 
TWeakObjectPtr< UCardSelectionWidgetActivePopup
 
TWeakObjectPtr< AMainPlayerStateBoundPlayerState
 
TWeakObjectPtr< APlayerController > CachedPlayerController
 
TWeakObjectPtr< UWeaponLoadoutComponent > BoundWeaponLoadout
 
FTimerHandle PlayerBindRetryTimerHandle
 

상세한 설명

플레이어가 고른 "상황"들을 들고 주기 발동을 굴리는 월드 서브시스템. 레벨업 시 선택지를 뽑아 UI 로 넘기고, 선택 결과를 장착한다.

버프는 성좌가 아니라 상황 카드가 소유한다. 발동 시 카드가 자기 GE 를 적용하고, 성좌 서브시스템에는 채팅 반응만 요청한다.

멤버 함수 문서화

◆ CreateSituation()

USituationBase * USituationManagementSubsystem::CreateSituation ( UStageManifest Manifest,
const FDT_SituationTable SituationRow 
)
protected
311{
312 if (Manifest == nullptr)
313 {
314 return nullptr;
315 }
316
317 // 버프는 카드가 소유한다. Buff_Master 행을 스냅샷으로 만들어 넘긴다.
318 const FDT_BuffTable BuffRow = Manifest->GetBuffTable(SituationRow.Buff_ID);
319 FSituationBuffData BuffData;
320 BuffData.Buff_ID = BuffRow.Buff_ID;
321 BuffData.Interval = BuffRow.Interval;
322
323 // Buff_Master.Target 문자열을 스킬 태그로 해석한다. 'Default'/빈 값이면 EmptyTag.
324 if (BuffRow.Target.IsNone() || BuffRow.Target == TEXT("Default") || BuffRow.Target == FName("-"))
325 {
326 BuffData.TargetSkillTag = FGameplayTag::EmptyTag;
327 }
328 else
329 {
330 const FGameplayTag Tag = TAG_CHARACTER_STATE_COMBAT_SKILL.GetTag();
331 const FName FullTagName(*(Tag.ToString() + BuffRow.Target.ToString()));
332
333 // 등록되지 않은 태그면 경고만 남기고 전역 적용으로 흘린다.
334 BuffData.TargetSkillTag = UGameplayTagsManager::Get().RequestGameplayTag(FullTagName, false);
335
336 if (BuffData.TargetSkillTag.IsValid() == false)
337 {
338 LOG_WARNING(LogCKAbility, "Buff_Master 의 Target '%s'에 대응하는 스킬 태그가 없습니다: %s", *BuffRow.Target.ToString(), *FullTagName.ToString());
339 }
340 }
341
342 // 기획 데이터의 GE 경로는 블루프린트 에셋(UBlueprint) 경로로 적힌다.
343 // 클래스로 로드되려면 '_C' 가 붙은 오브젝트를 가리켜야 하므로 여기서 보정한다.
344 const FSoftObjectPath SourcePath = BuffRow.GE_Path.ToSoftObjectPath();
345
346 if (SourcePath.IsNull() == false)
347 {
348 const FString PackageName = SourcePath.GetLongPackageName();
349 FString AssetName = SourcePath.GetAssetName();
350
351 // 점 없이 패키지 경로만 적힌 경우 마지막 조각을 에셋 이름으로 쓴다.
352 if (AssetName.IsEmpty())
353 {
354 AssetName = FPackageName::GetShortName(PackageName);
355 }
356
357 // 블루프린트의 클래스 오브젝트는 '_C' 가 붙어 있다.
358 if (AssetName.EndsWith(TEXT("_C")) == false)
359 {
360 AssetName += TEXT("_C");
361 }
362
363 BuffData.EffectClass = TSoftClassPtr<UGameplayEffect>(FSoftObjectPath(PackageName + TEXT(".") + AssetName));
364 }
365
366 // GE 설정이 상황 버프 시스템의 전제와 맞는지 검사해 경고를 남긴다.
367 if (BuffData.EffectClass.IsNull())
368 {
369 LOG_ERROR(LogCKAbility, "버프 '%s'에 GE 경로가 비어 있습니다.", *BuffRow.Buff_ID.ToString());
370 USituationBase* Situation = NewObject<USituationBase>(this);
371 Situation->Initialize(SituationRow, BuffData);
372 return Situation;
373 }
374
375 const UClass* EffectClass = BuffData.EffectClass.LoadSynchronous();
376 const UGameplayEffect* EffectCDO = EffectClass ? EffectClass->GetDefaultObject<UGameplayEffect>() : nullptr;
377
378 if (EffectCDO == nullptr)
379 {
380 LOG_ERROR(LogCKAbility, "버프 '%s'의 GE 를 로드할 수 없습니다: %s", *BuffRow.Buff_ID.ToString(), *BuffData.EffectClass.ToString());
381 USituationBase* Situation = NewObject<USituationBase>(this);
382 Situation->Initialize(SituationRow, BuffData);
383 return Situation;
384 }
385
386 // 상황마다 자기 GE 핸들을 따로 추적하므로 스택 병합이 일어나면 안 된다.
387 // 병합되면 같은 버프를 쓰는 두 상황이 한 핸들을 공유해 서로의 버프를 지운다.
388 if (EffectCDO->GetStackingType() != EGameplayEffectStackingType::None)
389 {
390 LOG_WARNING(LogCKAbility, "버프 '%s'의 GE 가 StackingType=None 이 아닙니다. 같은 버프를 쓰는 상황끼리 핸들이 병합되어 버프가 서로 지워집니다.", *BuffRow.Buff_ID.ToString());
391 }
392
393 // Instant 는 Active 핸들이 남지 않아 회수가 불가능하다.
394 // 발동할 때마다 BaseValue 에 영구 누적되어 스탯이 무한정 오른다.
395 if (EffectCDO->DurationPolicy == EGameplayEffectDurationType::Instant)
396 {
397 LOG_ERROR(LogCKAbility, "버프 '%s'의 GE 가 Instant 입니다. 발동마다 수치가 영구 누적되고 만료/제거가 불가능하니 Has Duration 또는 Infinite 로 바꿔야 합니다.", *BuffRow.Buff_ID.ToString());
398 }
399
400 USituationBase* Situation = NewObject<USituationBase>(this);
401 Situation->Initialize(SituationRow, BuffData);
402 return Situation;
403}
#define LOG_ERROR(Category, Format,...)
Definition CK_UE.h:40
#define LOG_WARNING(Category, Format,...)
Definition CK_UE.h:39
Definition SituationBase.h:31
void Initialize(const FDT_SituationTable &InSituationData, const FSituationBuffData &InBuffData)
Definition SituationBase.cpp:21
virtual FDT_BuffTable GetBuffTable(const FName &RowID)
Definition StageManifest.cpp:627
Definition DT_BuffTable.h:15
float Interval
Definition DT_BuffTable.h:31
FName Buff_ID
Definition DT_BuffTable.h:27
TSoftClassPtr< UGameplayEffect > GE_Path
Definition DT_BuffTable.h:40
FName Target
Definition DT_BuffTable.h:36
FName Buff_ID
Definition DT_SituationTable.h:51
Definition SituationBuffData.h:15
float Interval
Definition SituationBuffData.h:24
TSoftClassPtr< UGameplayEffect > EffectClass
Definition SituationBuffData.h:33
FName Buff_ID
Definition SituationBuffData.h:20
FGameplayTag TargetSkillTag
Definition SituationBuffData.h:29
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Deinitialize()

void USituationManagementSubsystem::Deinitialize ( )
overridevirtual
45{
46 UWorld* World = GetWorld();
47
48 if (World)
49 {
50 World->GetTimerManager().ClearTimer(PlayerBindRetryTimerHandle);
51 }
52
53 APlayerController* PlayerController = CachedPlayerController.Get();
54
55 for (USituationBase* Situation : EquippedSituations)
56 {
57 if (Situation)
58 {
59 Situation->OnSituationTriggered.RemoveAll(this);
60 Situation->OnBuffExpired.RemoveAll(this);
61 Situation->StopTicking(World);
62 Situation->RemoveBuff(PlayerController);
63 }
64 }
65
66 if (AMainPlayerState* PlayerState = BoundPlayerState.Get())
67 {
68 PlayerState->OnLevelUp.RemoveAll(this);
69 }
70
71 if (UWeaponLoadoutComponent* WeaponLoadout = BoundWeaponLoadout.Get())
72 {
73 WeaponLoadout->OnWeaponChanged.RemoveAll(this);
74 }
75
76 // 선택창이 뜬 채로 월드가 정리되면 시간이 멈춘 상태로 남는다.
78
79 if (UTimeManagementSubsystem* TimeSubsystem = World ? World->GetSubsystem<UTimeManagementSubsystem>() : nullptr)
80 {
81 TimeSubsystem->ResetTimeScale();
82 }
83
84 EquippedSituations.Empty();
85 PendingChoices.Empty();
86
87 Super::Deinitialize();
88}
Definition MainPlayerState.h:23
int32 TimeFreezeCount
Definition SituationManagementSubsystem.h:112
TWeakObjectPtr< AMainPlayerState > BoundPlayerState
Definition SituationManagementSubsystem.h:116
TWeakObjectPtr< APlayerController > CachedPlayerController
Definition SituationManagementSubsystem.h:118
TArray< TObjectPtr< USituationBase > > PendingChoices
Definition SituationManagementSubsystem.h:106
TWeakObjectPtr< UWeaponLoadoutComponent > BoundWeaponLoadout
Definition SituationManagementSubsystem.h:120
FTimerHandle PlayerBindRetryTimerHandle
Definition SituationManagementSubsystem.h:123
TArray< TObjectPtr< USituationBase > > EquippedSituations
Definition SituationManagementSubsystem.h:101
Definition TimeManagementSubsystem.h:27

◆ EnsurePlayerBinding()

void USituationManagementSubsystem::EnsurePlayerBinding ( )
protected
92{
93 if (BoundPlayerState.IsValid())
94 {
95 return;
96 }
97
98 APlayerController* PlayerController = ResolvePlayerController();
99
100 if (PlayerController == nullptr)
101 {
102 return;
103 }
104
105 AMainPlayerState* PlayerState = PlayerController->GetPlayerState<AMainPlayerState>();
106
107 if (PlayerState == nullptr)
108 {
109 return;
110 }
111
112 PlayerState->OnLevelUp.AddUObject(this, &USituationManagementSubsystem::HandleLevelUp);
113 BoundPlayerState = PlayerState;
114
115 EnsureWeaponBinding(PlayerController);
116
117 // 붙었으면 재시도를 멈춘다.
118 if (UWorld* World = GetWorld())
119 {
120 World->GetTimerManager().ClearTimer(PlayerBindRetryTimerHandle);
121 }
122}
FOnLevelUp OnLevelUp
Definition MainPlayerState.h:46
void HandleLevelUp(int32 NewLevel)
Definition SituationManagementSubsystem.cpp:125
APlayerController * ResolvePlayerController()
Definition SituationManagementSubsystem.cpp:552
void EnsureWeaponBinding(APlayerController *PlayerController)
Definition SituationManagementSubsystem.cpp:526
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EnsureWeaponBinding()

void USituationManagementSubsystem::EnsureWeaponBinding ( APlayerController *  PlayerController)
protected
527{
528 if (PlayerController == nullptr || BoundWeaponLoadout.IsValid())
529 {
530 return;
531 }
532
533 AMainPlayerCharacter* PlayerCharacter = Cast<AMainPlayerCharacter>(PlayerController->GetPawn());
534
535 if (PlayerCharacter == nullptr)
536 {
537 return;
538 }
539
540 UWeaponLoadoutComponent* WeaponLoadout = PlayerCharacter->GetWeaponLoadoutComponent();
541
542 if (WeaponLoadout == nullptr)
543 {
544 return;
545 }
546
547 WeaponLoadout->OnWeaponChanged.AddUObject(this, &USituationManagementSubsystem::HandleWeaponChanged);
548 BoundWeaponLoadout = WeaponLoadout;
549}
Definition MainPlayerCharacter.h:39
FORCEINLINE UWeaponLoadoutComponent * GetWeaponLoadoutComponent() const
Definition MainPlayerCharacter.h:94
void HandleWeaponChanged(const FGameplayTag &PreviousWeaponTag, const FGameplayTag &NewWeaponTag)
Definition SituationManagementSubsystem.cpp:506
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EquipSituation()

void USituationManagementSubsystem::EquipSituation ( const FName &  SituationID)
407{
408 UWorld* World = GetWorld();
409
410 if (World == nullptr || SituationID.IsNone())
411 {
412 return;
413 }
414
415 // 제시한 선택지 안에서만 고를 수 있다.
416 auto MatchesID = [&SituationID](const TObjectPtr<USituationBase>& Choice)
417 {
418 return Choice && Choice->GetSituationID() == SituationID;
419 };
420
421 // 후보 시점에 이미 만들어 둔 인스턴스를 그대로 가져다 쓴다.
422 TObjectPtr<USituationBase>* ChosenPtr = PendingChoices.FindByPredicate(MatchesID);
423
424 if (ChosenPtr == nullptr)
425 {
426 LOG_WARNING(LogCKPlayer, "상황 '%s'는 현재 선택지에 없습니다.", *SituationID.ToString());
427 return;
428 }
429
430 USituationBase* Situation = *ChosenPtr;
431
432 TWeakObjectPtr<USituationManagementSubsystem> WeakThis = this;
433 TWeakObjectPtr<USituationBase> WeakSituation = Situation;
434
435 auto OnTriggered = [WeakThis, WeakSituation]()
436 {
437 if (WeakThis.IsValid() == false || WeakSituation.IsValid() == false)
438 {
439 return;
440 }
441
442 WeakThis->HandleSituationTriggered(WeakSituation.Get());
443 };
444
445 auto OnExpired = [WeakThis, WeakSituation]()
446 {
447 if (WeakThis.IsValid() == false || WeakSituation.IsValid() == false)
448 {
449 return;
450 }
451
452 WeakThis->HandleBuffExpired(WeakSituation.Get());
453 };
454
455 Situation->OnSituationTriggered.AddWeakLambda(this, OnTriggered);
456 Situation->OnBuffExpired.AddWeakLambda(this, OnExpired);
457 Situation->StartTicking(World);
458
459 // 카드를 고른 지금에서야 후원 성좌가 시청자 목록에 합류한다.
460 // 고르지 않은 카드의 성좌는 등록되지 않고 그대로 버려진다.
461 if (UStreamingSubsystem* StreamingSubsystem = World->GetSubsystem<UStreamingSubsystem>())
462 {
463 StreamingSubsystem->RegisterConstellation(Situation->GetConstellation());
464
465 // 합류가 끝난 뒤에 반응 태그를 갈아끼운다. 후원 성좌도 첫 태그 채팅 후보에 들어가야 한다.
466 StreamingSubsystem->HandleSituationSelected(Situation);
467 }
468
469 EquippedSituations.Add(Situation);
470
472
473 // 선택지는 한 번 쓰면 사라진다. 대기분 소모와 다음 선택창은 팝업이 닫힐 때 처리한다.
474 PendingChoices.Empty();
475
476 OnSituationEquipped.Broadcast(Situation);
477}
FSimpleMulticastDelegate OnBuffExpired
Definition SituationBase.h:124
void StartTicking(UWorld *World)
Definition SituationBase.cpp:28
FSimpleMulticastDelegate OnSituationTriggered
Definition SituationBase.h:121
UConstellationBase * GetConstellation() const
Definition SituationBase.cpp:413
FOnSituationEquipped OnSituationEquipped
Definition SituationManagementSubsystem.h:63
Definition StreamingSubsystem.h:73
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetActiveSituations()

TArray< USituationBase * > USituationManagementSubsystem::GetActiveSituations ( ) const
584{
585 TArray<USituationBase*> Result;
586
587 for (USituationBase* Situation : EquippedSituations)
588 {
589 if (Situation && Situation->IsBuffActive())
590 {
591 Result.Add(Situation);
592 }
593 }
594
595 return Result;
596}
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetEquippedSituations()

TArray< USituationBase * > USituationManagementSubsystem::GetEquippedSituations ( ) const
567{
568 TArray<USituationBase*> Result;
569 Result.Reserve(EquippedSituations.Num());
570
571 for (USituationBase* Situation : EquippedSituations)
572 {
573 if (Situation)
574 {
575 Result.Add(Situation);
576 }
577 }
578
579 return Result;
580}
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ HandleBuffExpired()

void USituationManagementSubsystem::HandleBuffExpired ( USituationBase Situation)
protected
501{
502 OnSituationBuffRemoved.Broadcast(Situation);
503}
FOnSituationBuffChanged OnSituationBuffRemoved
Definition SituationManagementSubsystem.h:65

◆ HandleLevelUp()

void USituationManagementSubsystem::HandleLevelUp ( int32  NewLevel)
protected
126{
127 // 한 프레임에 여러 레벨이 올라도 선택창은 하나씩 순서대로 띄운다.
129
130 LOG_SCREEN_C(FColor::Black, "플레이어 레벨업! (LV: %d)", NewLevel);
131
133}
#define LOG_SCREEN_C(Color, Format,...)
Definition CK_UE.h:49
int32 PendingSelectionCount
Definition SituationManagementSubsystem.h:109
void TryOpenNextSelection()
Definition SituationManagementSubsystem.cpp:183
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ HandleSelectPopupClosed()

void USituationManagementSubsystem::HandleSelectPopupClosed ( UPopupWidgetBase Popup,
EPopupResult  Result 
)
protected
170{
171 ActivePopup.Reset();
172
173 // 고르지 않고 닫혀도(ESC 등) 한 번 띄운 몫은 소모한 것으로 본다.
174 // 여기서 줄이지 않으면 같은 대기분으로 팝업이 무한히 다시 열린다.
175 PendingSelectionCount = FMath::Max(PendingSelectionCount - 1, 0);
176
177 // 오른 레벨만큼 남아 있으면 곧바로 다음 선택창을 잇는다.
178 // 이 시점엔 TimeScale 이 0 이라 타이머로 미루면 영영 열리지 않는다.
180}
TWeakObjectPtr< UCardSelectionWidget > ActivePopup
Definition SituationManagementSubsystem.h:114
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ HandleSituationTriggered()

void USituationManagementSubsystem::HandleSituationTriggered ( USituationBase Situation)
protected
481{
482 if (Situation == nullptr)
483 {
484 return;
485 }
486
487 // 버프는 카드가 스스로 적용한다.
489
490 OnSituationBuffApplied.Broadcast(Situation);
491
492 // 성좌는 채팅으로만 반응한다.
493 if (UStreamingSubsystem* ConstellationSubsystem = GetWorld()->GetSubsystem<UStreamingSubsystem>())
494 {
495 ConstellationSubsystem->TriggerSituation(Situation);
496 }
497}
void ApplyBuff(APlayerController *TargetPC)
Definition SituationBase.cpp:62
FOnSituationBuffChanged OnSituationBuffApplied
Definition SituationManagementSubsystem.h:64
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ HandleWeaponChanged()

void USituationManagementSubsystem::HandleWeaponChanged ( const FGameplayTag &  PreviousWeaponTag,
const FGameplayTag &  NewWeaponTag 
)
protected
507{
508 APlayerController* PlayerController = CachedPlayerController.Get();
509
510 if (PlayerController == nullptr)
511 {
512 return;
513 }
514
515 // 걸려 있는 버프를 돌며 GE 를 다시 적용해, 무기별 수치가 새로 주입되게 한다.
516 for (USituationBase* Situation : EquippedSituations)
517 {
518 if (Situation)
519 {
520 Situation->RefreshForWeapon(PlayerController);
521 }
522 }
523}
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ OnWorldBeginPlay()

void USituationManagementSubsystem::OnWorldBeginPlay ( UWorld &  InWorld)
overridevirtual
29{
30 Super::OnWorldBeginPlay(InWorld);
31
33
34 if (BoundPlayerState.IsValid())
35 {
36 return;
37 }
38
39 // PlayerState 스폰이 늦는 경우가 있어 붙을 때까지 짧게 재시도한다.
40 InWorld.GetTimerManager().SetTimer(PlayerBindRetryTimerHandle, this, &USituationManagementSubsystem::EnsurePlayerBinding, 0.5f, true);
41}
void EnsurePlayerBinding()
Definition SituationManagementSubsystem.cpp:91
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ OpenSelectPopup()

void USituationManagementSubsystem::OpenSelectPopup ( )
protected
271{
272 FUIContext SelectPopupContext = GetDefault<USituationSettings>()->GetSelectPopupContext();
273
274 // 레이어는 고정이라 세팅에서 비워둬도 되게 여기서 채운다.
275 if (SelectPopupContext.LayerTag.IsValid() == false)
276 {
277 SelectPopupContext.LayerTag = TAG_UI_LAYER_POPUP;
278 }
279
280 if (SelectPopupContext.IsValid() == false)
281 {
282 LOG_WARNING(LogCKPlayer, "Project Settings > CK_UE > Situation Settings 의 SelectPopupContext.WidgetClass 가 비어 있어 선택 팝업을 띄울 수 없습니다.");
283 return;
284 }
285
287
288 if (UISubsystem == nullptr)
289 {
290 return;
291 }
292
293 UUILayer* OutLayer = nullptr;
294 UCardSelectionWidget* Popup = Cast<UCardSelectionWidget>(UISubsystem->PushPlayerWidget(SelectPopupContext, OutLayer));
295
296 if (Popup == nullptr)
297 {
298 LOG_ERROR(LogCKPlayer, "선택 팝업 위젯이 %s 가 아니라 선택지를 넘길 수 없습니다.", NAMEOF(UCardSelectionWidget));
299 return;
300 }
301
302 // 닫힘을 받아야 대기 중인 다음 선택창을 이어 띄울 수 있다.
304 ActivePopup = Popup;
305
307}
#define NAMEOF(Type)
Definition CK_UE.h:30
static UUIManagementSubsystem * GetUIManagementSubsystem(const UObject *WorldContextObject)
Definition CK_BPFunctionLibrary.cpp:138
Definition CardSelectionWidget.h:20
void SetupChoices(const TArray< TObjectPtr< USituationBase > > &Choices)
Definition CardSelectionWidget.cpp:18
FOnPopupClosed OnPopupClosed
Definition PopupWidgetBase.h:67
void HandleSelectPopupClosed(UPopupWidgetBase *Popup, EPopupResult Result)
Definition SituationManagementSubsystem.cpp:169
Definition UILayer.h:14
Definition UIManagementSubsystem.h:22
UUserWidgetBase * PushPlayerWidget(const FUIContext &Context, UUILayer *&OutLayer)
Definition UIManagementSubsystem.cpp:112
Definition UIContext.h:10
FGameplayTag LayerTag
Definition UIContext.h:21
bool IsValid() const
Definition UIContext.h:14
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PopTimeFreeze()

void USituationManagementSubsystem::PopTimeFreeze ( )
148{
149 if (TimeFreezeCount <= 0)
150 {
151 return;
152 }
153
155
156 // 다음 선택창이 이미 활성화됐다면 아직 풀면 안 된다.
157 if (TimeFreezeCount != 0)
158 {
159 return;
160 }
161
162 if (UTimeManagementSubsystem* TimeSubsystem = GetWorld()->GetSubsystem<UTimeManagementSubsystem>())
163 {
164 TimeSubsystem->ResetTimeScale();
165 }
166}
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ PushTimeFreeze()

void USituationManagementSubsystem::PushTimeFreeze ( )
137{
139
140 if (UTimeManagementSubsystem* TimeSubsystem = GetWorld()->GetSubsystem<UTimeManagementSubsystem>())
141 {
142 TimeSubsystem->ApplyTimeScale(0.0f);
143 }
144}
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ResolvePlayerController()

APlayerController * USituationManagementSubsystem::ResolvePlayerController ( )
protected
553{
554 if (CachedPlayerController.IsValid())
555 {
556 return CachedPlayerController.Get();
557 }
558
559 APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this, 0);
560 CachedPlayerController = PlayerController;
561
562 return PlayerController;
563}
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ TryOpenNextSelection()

void USituationManagementSubsystem::TryOpenNextSelection ( )
protected
184{
185 // 팝업이 떠 있는 동안에는 다음 선택지를 뽑지 않는다.
186 // 안 그러면 PendingChoices 가 덮여, 먼저 뜬 팝업의 카드가 목록에 없다고 거부당한다.
187 if (PendingSelectionCount <= 0 || ActivePopup.IsValid())
188 {
189 return;
190 }
191
192 UStageManifest* Manifest = UDataBundleRegistry::GetBundleAssetByTag<UStageManifest>(TAG_BUNDLE_INITIAL);
193
194 if (Manifest == nullptr)
195 {
196 return;
197 }
198
199 // 이미 장착한 상황은 선택지에서 빠지고, 동시에 선행 조건 판정의 기준이 된다.
200 TArray<FName> EquippedIDs;
201 EquippedIDs.Reserve(EquippedSituations.Num());
202
203 for (const USituationBase* Situation : EquippedSituations)
204 {
205 EquippedIDs.Add(Situation->GetSituationID());
206 }
207
208 const int32 PlayerLevel = BoundPlayerState.IsValid() ? BoundPlayerState->GetPlayerLevel() : 1;
209
210 const TArray<FDT_SituationTable> DrawnRows = Manifest->DrawSituationChoices(PlayerLevel, EquippedIDs, GetDefault<USituationSettings>()->GetChoiceCount());
211
212 // 카드 위젯이 버프 수치와 방송 태그를 직접 물어볼 수 있게 여기서 인스턴스까지 만든다.
213 // 고르지 않은 후보는 다음 추첨 때 참조가 끊겨 GC 가 정리한다.
214 PendingChoices.Reset(DrawnRows.Num());
215
216 UStreamingSubsystem* StreamingSubsystem = GetWorld() ? GetWorld()->GetSubsystem<UStreamingSubsystem>() : nullptr;
217
218 if (StreamingSubsystem == nullptr)
219 {
220 LOG_WARNING(LogCKPlayer, "%s 를 찾지 못해 카드에 성좌를 묶을 수 없습니다.", NAMEOF(UStreamingSubsystem));
221 }
222
223 // 같은 선택창의 카드끼리 같은 성좌를 물지 않게 뽑은 성좌를 모아 넘긴다.
224 TArray<FName> DrawnConstellationIDs;
225
226 for (const FDT_SituationTable& DrawnRow : DrawnRows)
227 {
228 USituationBase* Candidate = CreateSituation(Manifest, DrawnRow);
229
230 if (Candidate == nullptr)
231 {
232 continue;
233 }
234
235 // 카드가 뜨는 시점에 후원 성좌를 정해 둔다. 설명의 {{Alias}} / {{True_Name}} 이 이 성좌로 채워진다.
236 // 실제 시청자 합류는 카드를 골랐을 때 EquipSituation 이 처리한다.
237 UConstellationBase* Sponsor;
238
239 if (StreamingSubsystem)
240 {
241 Sponsor = StreamingSubsystem->DrawConstellationForTags(DrawnRow.ParsedTags, DrawnConstellationIDs);
242 }
243 else
244 {
245 Sponsor = nullptr;
246 }
247
248 Candidate->SetConstellation(Sponsor);
249
250 if (Sponsor)
251 {
252 DrawnConstellationIDs.Add(Sponsor->GetConstellationData().Constellation_ID);
253 }
254
255 PendingChoices.Add(Candidate);
256 }
257
258 if (PendingChoices.IsEmpty())
259 {
260 LOG_WARNING(LogCKPlayer, "레벨 %d 에서 제시할 상황이 없어 선택창을 띄우지 않습니다.", PlayerLevel);
261 PendingSelectionCount = 0; // 뽑을 게 없으면 남은 대기분도 의미가 없음.
262 }
263 else
264 {
266 }
267}
Definition ConstellationBase.h:35
FORCEINLINE const FConstellationData & GetConstellationData() const
Definition ConstellationBase.h:53
void SetConstellation(UConstellationBase *InConstellation)
Definition SituationBase.cpp:419
void OpenSelectPopup()
Definition SituationManagementSubsystem.cpp:270
USituationBase * CreateSituation(UStageManifest *Manifest, const FDT_SituationTable &SituationRow)
Definition SituationManagementSubsystem.cpp:310
Definition StageManifest.h:161
virtual TArray< FDT_SituationTable > DrawSituationChoices(int32 PlayerLevel, const TArray< FName > &EquippedIDs, int32 DrawCount=3)
Definition StageManifest.cpp:495
UConstellationBase * DrawConstellationForTags(ESituationTag BroadcastTags, const TArray< FName > &ExcludedIDs)
Definition StreamingSubsystem.cpp:152
FName Constellation_ID
Definition ConstellationData.h:21
Definition DT_SituationTable.h:20
이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

멤버 데이터 문서화

◆ ActivePopup

TWeakObjectPtr<UCardSelectionWidget> USituationManagementSubsystem::ActivePopup
protected

◆ BoundPlayerState

TWeakObjectPtr<AMainPlayerState> USituationManagementSubsystem::BoundPlayerState
protected

◆ BoundWeaponLoadout

TWeakObjectPtr<UWeaponLoadoutComponent> USituationManagementSubsystem::BoundWeaponLoadout
protected

◆ CachedPlayerController

TWeakObjectPtr<APlayerController> USituationManagementSubsystem::CachedPlayerController
protected

◆ EquippedSituations

TArray<TObjectPtr<USituationBase> > USituationManagementSubsystem::EquippedSituations
protected

◆ OnSituationBuffApplied

FOnSituationBuffChanged USituationManagementSubsystem::OnSituationBuffApplied

◆ OnSituationBuffRemoved

FOnSituationBuffChanged USituationManagementSubsystem::OnSituationBuffRemoved

◆ OnSituationEquipped

FOnSituationEquipped USituationManagementSubsystem::OnSituationEquipped

◆ PendingChoices

TArray<TObjectPtr<USituationBase> > USituationManagementSubsystem::PendingChoices
protected

◆ PendingSelectionCount

int32 USituationManagementSubsystem::PendingSelectionCount = 0
protected

◆ PlayerBindRetryTimerHandle

FTimerHandle USituationManagementSubsystem::PlayerBindRetryTimerHandle
protected

◆ TimeFreezeCount

int32 USituationManagementSubsystem::TimeFreezeCount = 0
protected

이 클래스에 대한 문서화 페이지는 다음의 파일들로부터 생성되었습니다.: