#include "Core/DescentGameMode.h" #include "Core/DescentGameClasses.h" #include "Debug/DescentDebugSubsystem.h" #include "TheDescent.h" #include "Engine/World.h" #include "GameFramework/GameStateBase.h" #include "GameFramework/HUD.h" #include "GameFramework/PlayerController.h" #include "GameFramework/PlayerState.h" #include "GameFramework/Pawn.h" namespace { /** The registered class for a slot if it derives from Base, otherwise the engine default already in Current. */ template TSubclassOf ResolveSlot(EDescentGameClassSlot Slot, TSubclassOf Current) { UClass* Registered = FDescentGameClassRegistry::Get().Resolve(Slot); if (!Registered) { return Current; } if (!Registered->IsChildOf(TBase::StaticClass())) { UE_LOG(LogDescent, Error, TEXT("GameClasses: %s registered for slot %d does not derive from %s; ignored"), *Registered->GetName(), static_cast(Slot), *TBase::StaticClass()->GetName()); return Current; } return Registered; } } ADescentGameMode::ADescentGameMode() { // Which pawn, controller, HUD, game state and player state the game uses is decided by registration // (Core/DescentGameClasses.h), so adding the real character or controller never edits this file. DefaultPawnClass = ResolveSlot(EDescentGameClassSlot::Pawn, DefaultPawnClass); PlayerControllerClass = ResolveSlot(EDescentGameClassSlot::PlayerController, PlayerControllerClass); HUDClass = ResolveSlot(EDescentGameClassSlot::HUD, HUDClass); GameStateClass = ResolveSlot(EDescentGameClassSlot::GameState, GameStateClass); PlayerStateClass = ResolveSlot(EDescentGameClassSlot::PlayerState, PlayerStateClass); } void ADescentGameMode::StartPlay() { // Super first: the world is marked as begun and existing actors get BeginPlay, so every actor a boot step // spawns afterwards is begun at once and the next step can rely on it. Super::StartPlay(); FDescentBootContext Context; Context.World = GetWorld(); Context.GameMode = this; const UDescentDebugSubsystem* Debug = UDescentDebugSubsystem::Get(Context.World); const FDescentScenarioRunner* Runner = Debug ? Debug->GetRunner() : nullptr; Context.bScenarioRunning = Runner && !Runner->IsFinished(); BootReport = FDescentBootRegistry::Get().Run(Context); UE_LOG(LogDescent, Display, TEXT("Boot: %d step(s) ran, %s"), BootReport.Ran.Num(), BootReport.bOk ? TEXT("all ok") : TEXT("AT LEAST ONE FAILED")); }