Bugfixes and review

This commit is contained in:
Oleg Petruny 2025-07-11 00:01:19 +02:00
parent 0774965cc8
commit eaff75b652
68 changed files with 257 additions and 149 deletions

View File

@ -1,3 +1,5 @@
All sounds are liecesed under [CC0](https://creativecommons.org/publicdomain/zero/1.0/) when was downloaded.
Click - https://freesound.org/people/ccr_fs/sounds/484719/ Click - https://freesound.org/people/ccr_fs/sounds/484719/
ElectricTransform - https://freesound.org/people/ShahruhAudio/sounds/336881/ ElectricTransform - https://freesound.org/people/ShahruhAudio/sounds/336881/
ElectricZap - https://freesound.org/people/egomassive/sounds/536741/ ElectricZap - https://freesound.org/people/egomassive/sounds/536741/

View File

@ -62,10 +62,13 @@ InternationalizationPreset=English
LocalizationTargetCatchAllChunkId=0 LocalizationTargetCatchAllChunkId=0
bCookAll=False bCookAll=False
bCookMapsOnly=False bCookMapsOnly=False
bTreatWarningsAsErrorsOnCook=False
bSkipEditorContent=True bSkipEditorContent=True
bSkipMovies=False bSkipMovies=False
-IniKeyDenylist=KeyStorePassword -IniKeyDenylist=KeyStorePassword
-IniKeyDenylist=KeyPassword -IniKeyDenylist=KeyPassword
-IniKeyDenylist=DebugKeyStorePassword
-IniKeyDenylist=DebugKeyPassword
-IniKeyDenylist=rsa.privateexp -IniKeyDenylist=rsa.privateexp
-IniKeyDenylist=rsa.modulus -IniKeyDenylist=rsa.modulus
-IniKeyDenylist=rsa.publicexp -IniKeyDenylist=rsa.publicexp
@ -81,6 +84,8 @@ bSkipMovies=False
-IniKeyDenylist=MobileProvision -IniKeyDenylist=MobileProvision
-IniKeyDenylist=IniKeyDenylist -IniKeyDenylist=IniKeyDenylist
-IniKeyDenylist=IniSectionDenylist -IniKeyDenylist=IniSectionDenylist
+IniKeyDenylist=DebugKeyStorePassword
+IniKeyDenylist=DebugKeyPassword
+IniKeyDenylist=KeyStorePassword +IniKeyDenylist=KeyStorePassword
+IniKeyDenylist=KeyPassword +IniKeyDenylist=KeyPassword
+IniKeyDenylist=rsa.privateexp +IniKeyDenylist=rsa.privateexp
@ -100,6 +105,8 @@ bSkipMovies=False
+IniKeyDenylist=IniSectionDenylist +IniKeyDenylist=IniSectionDenylist
-IniSectionDenylist=HordeStorageServers -IniSectionDenylist=HordeStorageServers
-IniSectionDenylist=StorageServers -IniSectionDenylist=StorageServers
-IniSectionDenylist=/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings
+IniSectionDenylist=/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings
+IniSectionDenylist=HordeStorageServers +IniSectionDenylist=HordeStorageServers
+IniSectionDenylist=StorageServers +IniSectionDenylist=StorageServers
+DirectoriesToAlwaysCook=(Path="/Game/Misc/Interactables") +DirectoriesToAlwaysCook=(Path="/Game/Misc/Interactables")
@ -115,6 +122,7 @@ bSkipMovies=False
+DirectoriesToAlwaysCook=(Path="/Game/Audio/FMOD/Reverbs") +DirectoriesToAlwaysCook=(Path="/Game/Audio/FMOD/Reverbs")
+DirectoriesToAlwaysCook=(Path="/Game/Audio/FMOD/Snapshots") +DirectoriesToAlwaysCook=(Path="/Game/Audio/FMOD/Snapshots")
+DirectoriesToAlwaysCook=(Path="/Game/Audio/FMOD/VCAs") +DirectoriesToAlwaysCook=(Path="/Game/Audio/FMOD/VCAs")
+DirectoriesToAlwaysCook=(Path="/NNEDenoiser")
+DirectoriesToAlwaysStageAsNonUFS=(Path="Audio/FMOD/Desktop") +DirectoriesToAlwaysStageAsNonUFS=(Path="Audio/FMOD/Desktop")
bRetainStagedDirectory=False bRetainStagedDirectory=False
CustomStageCopyHandler= CustomStageCopyHandler=

View File

@ -37,3 +37,5 @@ HDRDisplayOutputNits=1000
[/Script/Engine.GameUserSettings] [/Script/Engine.GameUserSettings]
bUseDesiredScreenHeight=False bUseDesiredScreenHeight=False
[ScalabilityGroups]
sg.ResolutionQuality=100

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -55,6 +55,17 @@ int32 UCommonFunctions::StringIndexInTextArray(const TArray<FText>& array, const
return -1; return -1;
} }
int32 UCommonFunctions::SubstringCount(const FString& in, const FString& substr)
{
int32 result = 0;
int32 i = -1;
while((i = in.Find(substr, ESearchCase::Type::CaseSensitive, ESearchDir::Type::FromStart, i + 1)) != INDEX_NONE)
++result;
return result;
}
void UCommonFunctions::DestroyActorRecursively(AActor* actor) void UCommonFunctions::DestroyActorRecursively(AActor* actor)
{ {
TArray<AActor*> childs; TArray<AActor*> childs;

View File

@ -53,6 +53,8 @@ public:
UFUNCTION(BlueprintPure) UFUNCTION(BlueprintPure)
static int32 StringIndexInTextArray(const TArray<FText>& array, const FString& value); static int32 StringIndexInTextArray(const TArray<FText>& array, const FString& value);
UFUNCTION(BlueprintPure)
static int32 SubstringCount(const FString& in, const FString& substr);
/** Recursively destroy actor and all its childs (the default Destroy doesn't have consistent behavior) */ /** Recursively destroy actor and all its childs (the default Destroy doesn't have consistent behavior) */
UFUNCTION(BlueprintCallable, Category = Actor) UFUNCTION(BlueprintCallable, Category = Actor)

View File

@ -130,21 +130,19 @@ void UCustomGameInstance::SaveGame(FName checkpointName)
if(!levelScript) if(!levelScript)
return; return;
auto player = APlayerBase::Get();
if(!player)
return;
saveData->level = GetWorld()->GetFName(); saveData->level = GetWorld()->GetFName();
saveData->state = levelScript->GetState(); saveData->state = levelScript->GetState();
saveData->checkpoint = checkpointName; saveData->checkpoint = checkpointName;
if(player->leftPocketItem)
auto player = APlayerBase::Get();
if(player && player->leftPocketItem)
saveData->playerLeftPocketItem = player->leftPocketItem->GetFName(); saveData->playerLeftPocketItem = player->leftPocketItem->GetFName();
else else
saveData->playerLeftPocketItem = FName(TEXT("")); saveData->playerLeftPocketItem = {};
if(player->rightPocketItem) if(player && player->rightPocketItem)
saveData->playerRightPocketItem = player->rightPocketItem->GetFName(); saveData->playerRightPocketItem = player->rightPocketItem->GetFName();
else else
saveData->playerRightPocketItem = FName(TEXT("")); saveData->playerRightPocketItem = {};
UGameplayStatics::SaveGameToSlot(saveData, saveName, saveIndex); UGameplayStatics::SaveGameToSlot(saveData, saveName, saveIndex);
} }

View File

@ -116,11 +116,7 @@ void UGraphicsSettingsHelper::CenterWindowPosition(UCustomGameSettings* settings
return; return;
FIntPoint position; FIntPoint position;
if(GetDisplayMode(settings) == EDisplayMode::Fullscreen) if(GetDisplayMode(settings) == EDisplayMode::Windowed)
{
position = { 0, 0 };
}
else
{ {
auto monitors = GetAvailableMonitors(); auto monitors = GetAvailableMonitors();
int32 monitorId = GetMonitorId(settings); int32 monitorId = GetMonitorId(settings);
@ -132,6 +128,10 @@ void UGraphicsSettingsHelper::CenterWindowPosition(UCustomGameSettings* settings
FIntPoint window = GetResolution(settings); FIntPoint window = GetResolution(settings);
position = { offset + (monitor.X - window.X) / 2, (monitor.Y - window.Y) / 2 }; position = { offset + (monitor.X - window.X) / 2, (monitor.Y - window.Y) / 2 };
} }
else
{
position = { 0, 0 };
}
SetWindowPosition(settings, position); SetWindowPosition(settings, position);
} }
@ -361,8 +361,9 @@ FIntPoint UGraphicsSettingsHelper::FilterClosestResolution(const TArray<FIntPoin
for(int32 i = 1; i < resolutions.Num(); ++i) for(int32 i = 1; i < resolutions.Num(); ++i)
{ {
float c = resolutions[i].X / (float)target.X; float c = resolutions[i].X / (float)target.X;
if((coefficient > 1 && c < coefficient) if((coefficient > 1 && c < coefficient) // 1 < new result < old result
|| (coefficient < 1 && c > coefficient && c < 1)) || (c < 1 && c > coefficient) // old result < new result < 1
|| UCommonFunctions::FloatIsZero(c - 1)) // new result == Omega(1)
{ {
coefficient = c; coefficient = c;
resultId = i; resultId = i;

View File

@ -10,14 +10,18 @@
#include "Engine/SkyLight.h" #include "Engine/SkyLight.h"
#include "LevelSequencePlayer.h" #include "LevelSequencePlayer.h"
#include "CustomGameInstance.h"
#include "CutsceneManager.h" #include "CutsceneManager.h"
void ALevel1::BeginPlay() void ALevel1::BeginPlay()
{ {
ALevelBase::BeginPlay(); ALevelBase::BeginPlay();
TurnLight(false); //TurnLight(false);
TurnFog(false); //TurnFog(false);
if(auto GI = UCustomGameInstance::Get())
GI->SaveGame({});
CallNextState(); CallNextState();
} }

View File

@ -2,9 +2,14 @@
#include "Level2.h" #include "Level2.h"
#include "CustomGameInstance.h"
void ALevel2::BeginPlay() void ALevel2::BeginPlay()
{ {
ALevelBase::BeginPlay(); ALevelBase::BeginPlay();
if(auto GI = UCustomGameInstance::Get())
GI->SaveGame({});
CallNextState(); CallNextState();
} }

View File

@ -8,6 +8,7 @@
#include "Engine/SkyLight.h" #include "Engine/SkyLight.h"
#include "LevelSequencePlayer.h" #include "LevelSequencePlayer.h"
#include "CustomGameInstance.h"
#include "CutsceneManager.h" #include "CutsceneManager.h"
#include "MainGameModeBase.h" #include "MainGameModeBase.h"
@ -15,5 +16,8 @@ void ALevel3::BeginPlay()
{ {
ALevelBase::BeginPlay(); ALevelBase::BeginPlay();
CallNextState(); if(auto GI = UCustomGameInstance::Get())
GI->SaveGame({});
//CallNextState();
} }

View File

@ -89,32 +89,37 @@ void ALevelBase::ApplySaveData()
if(!player) if(!player)
return; return;
for(TActorIterator<ACheckpoint> it(GetWorld()); it; ++it) if(!GI->saveData->checkpoint.IsNone())
{ {
if(it->GetFName() == GI->saveData->checkpoint) for(TActorIterator<ACheckpoint> it(GetWorld()); it; ++it)
{ {
player->SetActorLocation(it->GetActorLocation(), false, nullptr, ETeleportType::ResetPhysics); if(it->GetFName() == GI->saveData->checkpoint)
player->Controller->SetControlRotation(it->GetActorRotation()); {
break; player->SetActorLocation(it->GetActorLocation(), false, nullptr, ETeleportType::ResetPhysics);
player->Controller->SetControlRotation(it->GetActorRotation());
break;
}
} }
} }
int pocketItems = 0; if(!GI->saveData->playerLeftPocketItem.IsNone() || !GI->saveData->playerRightPocketItem.IsNone())
for(TActorIterator<AInteractable> it(GetWorld()); it; ++it)
{ {
if(it->GetFName() == GI->saveData->playerLeftPocketItem) int pocketItems = 0;
for(TActorIterator<AInteractable> it(GetWorld()); it; ++it)
{ {
++pocketItems; if(pocketItems > 1)
player->TakeItemToLeftHand(*it); break;
}
else if(it->GetFName() == GI->saveData->playerRightPocketItem) if(it->GetFName() == GI->saveData->playerLeftPocketItem)
{ {
++pocketItems; ++pocketItems;
player->TakeItemToRightHand(*it); player->TakeItemToLeftHand(*it);
} }
if(pocketItems > 1) else if(it->GetFName() == GI->saveData->playerRightPocketItem)
{ {
break; ++pocketItems;
player->TakeItemToRightHand(*it);
}
} }
} }
} }

View File

@ -56,3 +56,11 @@ void AMinigame::Restart()
OnRestart_Internal(); OnRestart_Internal();
OnRestart(); OnRestart();
} }
void AMinigame::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
if(instance == this)
instance = nullptr;
Super::EndPlay(EndPlayReason);
}

View File

@ -47,6 +47,8 @@ public:
TSoftObjectPtr<class UInputMappingContext> GetInputMappings() { return context; } TSoftObjectPtr<class UInputMappingContext> GetInputMappings() { return context; }
protected: protected:
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
virtual void OnStart_Internal() {} virtual void OnStart_Internal() {}
UFUNCTION(BlueprintImplementableEvent) UFUNCTION(BlueprintImplementableEvent)
void OnStart(); void OnStart();

View File

@ -348,30 +348,7 @@ void APlayerBase::ShowJournal()
void APlayerBase::ShowMenu() void APlayerBase::ShowMenu()
{ {
if(auto WM = AMainGameModeBase::GetWidgetsManager()) if(auto WM = AMainGameModeBase::GetWidgetsManager())
{ WM->MenuCall();
if(GetWorld()->IsPaused())
{
WM->HideMainMenu();
if(auto PC = ACustomPlayerController::Get())
{
PC->SetShowMouseCursor(false);
PC->SetInputMode(FInputModeGameOnly{});
}
UnlockPlayer(FPlayerLock::All());
UGameplayStatics::SetGamePaused(GetWorld(), false);
}
else
{
WM->ShowMainMenu();
if(auto PC = ACustomPlayerController::Get())
{
PC->SetShowMouseCursor(true);
PC->SetInputMode(FInputModeGameAndUI{});
}
LockPlayer(FPlayerLock::All());
UGameplayStatics::SetGamePaused(GetWorld(), true);
}
}
} }
FPlayerLock FPlayerLock::All() FPlayerLock FPlayerLock::All()

View File

@ -9,6 +9,11 @@
#include "MainMenuButtonWidget.h" #include "MainMenuButtonWidget.h"
#include "Widgets/WidgetsManager.h" #include "Widgets/WidgetsManager.h"
namespace
{
constexpr float userCallDelaySeconds = 0.1f;
}
bool UMainMenuWidget::Initialize() bool UMainMenuWidget::Initialize()
{ {
//FWidgetAnimationDynamicEvent closeFinished; //FWidgetAnimationDynamicEvent closeFinished;
@ -18,6 +23,25 @@ bool UMainMenuWidget::Initialize()
return UUserWidget::Initialize(); return UUserWidget::Initialize();
} }
void UMainMenuWidget::UserCall()
{
float time = GetWorld()->GetRealTimeSeconds();
if(time - userCallTimeStamp < userCallDelaySeconds)
return;
userCallTimeStamp = time;
if(Visibility == ESlateVisibility::Hidden)
{
if(auto GM = AMainGameModeBase::Get())
if(auto WM = GM->GetWidgetsManager())
WM->ShowMainMenu(true);
}
else
{
OnUserCall();
}
}
void UMainMenuWidget::Show(bool fast) void UMainMenuWidget::Show(bool fast)
{ {
SetVisibility(ESlateVisibility::Visible); SetVisibility(ESlateVisibility::Visible);

View File

@ -18,6 +18,9 @@ class UMainMenuWidget : public UUserWidget
public: public:
virtual bool Initialize() override; virtual bool Initialize() override;
void UserCall();
UFUNCTION(BlueprintImplementableEvent)
void OnUserCall();
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
void Show(bool fast = true); void Show(bool fast = true);
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
@ -38,4 +41,7 @@ public:
protected: protected:
UFUNCTION() UFUNCTION()
void Closed(); void Closed();
private:
float userCallTimeStamp = 0;
}; };

View File

@ -11,6 +11,7 @@
#include "CustomGameInstance.h" #include "CustomGameInstance.h"
#include "CustomGameSettings.h" #include "CustomGameSettings.h"
#include "CustomPlayerController.h"
#include "Interactable/Interactable.h" #include "Interactable/Interactable.h"
#include "Interactable/Modificators/InteractableModificator.h" #include "Interactable/Modificators/InteractableModificator.h"
#include "Interactable/Modificators/InventoryInteractableModificator.h" #include "Interactable/Modificators/InventoryInteractableModificator.h"
@ -165,8 +166,24 @@ void UWidgetsManager::RemoveOverlayWidget(UUserWidget* widget)
void UWidgetsManager::MenuCall()
{
mainMenuWidget->UserCall();
}
void UWidgetsManager::ShowMainMenu(bool pause) void UWidgetsManager::ShowMainMenu(bool pause)
{ {
if(auto PC = ACustomPlayerController::Get())
{
PC->SetShowMouseCursor(true);
PC->SetInputMode(FInputModeGameAndUI{});
}
if(auto p = APlayerBase::Get())
{
p->LockPlayer(FPlayerLock::All());
}
UGameplayStatics::SetGamePaused(GetWorld(), true);
mainMenuWidget->Show(pause); mainMenuWidget->Show(pause);
HideJournal(); HideJournal();
HideCheatMenu(); HideCheatMenu();
@ -174,6 +191,17 @@ void UWidgetsManager::ShowMainMenu(bool pause)
void UWidgetsManager::HideMainMenu() void UWidgetsManager::HideMainMenu()
{ {
if(auto PC = ACustomPlayerController::Get())
{
PC->SetShowMouseCursor(false);
PC->SetInputMode(FInputModeGameOnly{});
}
if(auto p = APlayerBase::Get())
{
p->UnlockPlayer(FPlayerLock::All());
}
UGameplayStatics::SetGamePaused(GetWorld(), false);
mainMenuWidget->Hide(); mainMenuWidget->Hide();
} }

View File

@ -32,7 +32,10 @@ public:
UFUNCTION(BlueprintCallable, Category = WidgetsManager) UFUNCTION(BlueprintCallable, Category = WidgetsManager)
void RemoveOverlayWidget(class UUserWidget* widget); void RemoveOverlayWidget(class UUserWidget* widget);
void MenuCall();
UFUNCTION(BlueprintCallable, Category = WidgetsManager)
void ShowMainMenu(bool pause = true); void ShowMainMenu(bool pause = true);
UFUNCTION(BlueprintCallable, Category = WidgetsManager)
void HideMainMenu(); void HideMainMenu();
UFUNCTION(BlueprintCallable, Category = WidgetsManager) UFUNCTION(BlueprintCallable, Category = WidgetsManager)