2020-12-13 15:01:13 +00:00
|
|
|
//=============================================================================
|
|
|
|
// KFGameEngine
|
|
|
|
//=============================================================================
|
|
|
|
// KF specific engine class needs
|
|
|
|
//=============================================================================
|
|
|
|
// Killing Floor 2
|
|
|
|
// Copyright (C) 2015 Tripwire Interactive LLC
|
|
|
|
// - Andrew "Strago" Ladenberger
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
class KFGameEngine extends GameEngine
|
|
|
|
config(Game)
|
|
|
|
native;
|
|
|
|
|
|
|
|
/** Supported platforms for KF2 */
|
|
|
|
enum SupportedPlatform
|
|
|
|
{
|
|
|
|
PLATFORM_PC_DX11,
|
|
|
|
PLATFORM_PC_DX10
|
|
|
|
};
|
|
|
|
|
|
|
|
//Pre-allocating seasonal events based on quarterly-ish patch cycle even if we aren't currently using them.
|
|
|
|
enum SeasonalEventIndex
|
|
|
|
{
|
|
|
|
SEI_None,
|
|
|
|
SEI_Spring,
|
|
|
|
SEI_Summer,
|
|
|
|
SEI_Fall,
|
|
|
|
SEI_Winter,
|
|
|
|
};
|
|
|
|
|
|
|
|
/** The game state we were in (paused, in game, etc.) when we lost focus */
|
|
|
|
var int LastFocusedGameStateID;
|
|
|
|
|
|
|
|
/** The font to use for drawing canvas text in KF */
|
|
|
|
var Font KFCanvasFont;
|
|
|
|
/** The universal scale for KFCanvasFont */
|
|
|
|
var float KFFontScale;
|
|
|
|
|
|
|
|
/** TRUE if we are actively logging into playfab */
|
|
|
|
var bool bReadingPlayfabStoreData;
|
|
|
|
|
|
|
|
/** Currently running event */
|
|
|
|
var private{private} const int SeasonalEventId;
|
|
|
|
var private const int LoadedSeasonalEventId;
|
|
|
|
|
|
|
|
/** Week index of the year - Used as index into weekly event */
|
|
|
|
var private int WeeklyEventIndex;
|
|
|
|
|
2020-12-13 15:09:05 +00:00
|
|
|
|
2020-12-13 15:01:13 +00:00
|
|
|
/************************************************************************************
|
|
|
|
* @name Content
|
|
|
|
***********************************************************************************/
|
|
|
|
/**
|
|
|
|
List of packages that were manually added to root for content precaching reasons.
|
|
|
|
These are removed from root during server travel in order to allow them to be
|
|
|
|
garbage collected while still maintaining a cached list in global space while a
|
|
|
|
level is running.
|
|
|
|
*/
|
|
|
|
var init array<Object> CachedRootPackages;
|
|
|
|
|
|
|
|
/************************************************************************************
|
|
|
|
* @name User Options
|
|
|
|
***********************************************************************************/
|
|
|
|
|
|
|
|
// @todo Find a way to reset a options section
|
|
|
|
var float DefaultGammaMult;
|
|
|
|
//@HSL_MOD_BEGIN - amiller 5/11/2016 - Adding support to save extra data into profile settings - Removing config flag
|
|
|
|
var float MusicVolumeMultiplier, SFxVolumeMultiplier, DialogVolumeMultiplier, MasterVolumeMultiplier, PadVolumeMultiplier, VoipVolumeMultiplier, VoipMicVolumeMultiplier;
|
|
|
|
var float GammaMultiplier; // a value between 0-1 that scales the gamma to a value between .5 and 3
|
|
|
|
|
|
|
|
var bool bMusicVocalsEnabled;
|
|
|
|
var bool bMinimalChatter;
|
|
|
|
var config float FOVOptionsPercentageValue;
|
|
|
|
//@HSL_MOD_END
|
|
|
|
var config bool bShowWelderInInv;
|
|
|
|
var config bool bUseAltAimOnDual;
|
|
|
|
var config bool bAntiMotionSickness;
|
|
|
|
|
|
|
|
var private config bool bShowCrossHair;
|
|
|
|
/** Crossair for console builds (default on). No config since it won't save */
|
|
|
|
var private bool bShowCrossHairConsole;
|
|
|
|
|
|
|
|
/** Whether to mute the game if focus is lost. */
|
|
|
|
var config bool bMuteOnLossOfFocus;
|
|
|
|
|
|
|
|
/** Whether to use native 4k resolution on Xbox One X (Scorpio) */
|
|
|
|
var config bool bEnableNative4k;
|
|
|
|
|
|
|
|
/** Cached stat rows used by XB1 only if there's ever a network interruption that won't allow a re-read of existing stats, We use this. */
|
|
|
|
var array<OnlineStatsRow> CachedStatRows;
|
|
|
|
|
|
|
|
/************************************************************************************
|
|
|
|
* @name Connection
|
|
|
|
***********************************************************************************/
|
|
|
|
|
|
|
|
// A callback for when a new connection handshake is complete
|
|
|
|
var transient delegate<HandshakeCompleteCallback> OnHandshakeComplete;
|
|
|
|
|
|
|
|
// Different connection errors that can occur during the join process
|
|
|
|
enum EConnectionError
|
|
|
|
{
|
|
|
|
CE_None, // Default value, represents no error
|
|
|
|
|
|
|
|
CE_Generic, // General unspecified connection error
|
|
|
|
|
|
|
|
// These will all occur BEFORE a travel, via the GameInfo and AccessControl PreLogin functions
|
|
|
|
CE_WrongPassword, // Connection denied because the password is incorrect
|
|
|
|
CE_NeedPassword, // Connection denied because no password was specified
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
/** The last error we got attempting to connect */
|
|
|
|
var EConnectionError LastConnectionError;
|
|
|
|
|
|
|
|
//@HSL_BEGIN - JRO - 3/21/2016 - PS4 Sessions
|
|
|
|
var string ConsoleGameSessionGuid;
|
|
|
|
//@HSL_END
|
|
|
|
|
|
|
|
/** The game settings for a pending invite. Used when an idle profile accepts an invite and we need to switch profiles for XB1 */
|
|
|
|
var OnlineGameSettings GameSettingsForPendingInvite;
|
|
|
|
|
|
|
|
/** Title and message for notification that should appear if user ever gets kicked back to IIS */
|
|
|
|
var string ReturnToIISConnectionErrorTitle;
|
|
|
|
var string ReturnToIISConnectionErrorMessage;
|
|
|
|
|
|
|
|
/** The login status for the one local user */
|
|
|
|
var ELoginStatus LocalLoginStatus;
|
|
|
|
|
|
|
|
/************************************************************************************
|
|
|
|
* @name Debugging
|
|
|
|
***********************************************************************************/
|
|
|
|
|
|
|
|
/** List of categories to filter */
|
|
|
|
var(Debug) config array<Name> AILogFilter;
|
|
|
|
|
|
|
|
/** A manager for drawing semi-persistent debug lines/spheres/text with optional owners, etc. */
|
|
|
|
var transient private KFDebugLines KFDebugLines;
|
|
|
|
/** Set to true to enable usage of KFDebugLines (see KFDebugLines.uc) */
|
|
|
|
var config bool bEnableAdvDebugLines;
|
|
|
|
|
|
|
|
cpptext
|
|
|
|
{
|
|
|
|
// static members
|
|
|
|
static FString GetSeasonalEventPrefix();
|
|
|
|
static FString GetSeasonalEventPackageName(INT EventId = -1, UMapInfo* MapInfo = NULL);
|
|
|
|
static FString GetSeasonalEventStatsClassPath();
|
|
|
|
|
|
|
|
// UEngine interface.
|
|
|
|
void Init();
|
|
|
|
void PreExit();
|
|
|
|
void FinishDestroy();
|
|
|
|
UBOOL Exec( const TCHAR* Cmd, FOutputDevice& Ar=*GLog );
|
|
|
|
virtual UBOOL LoadMap( const FURL& URL, class UPendingLevel* Pending, FString& Error );
|
|
|
|
virtual void SetProgress( EProgressMessageType MessageType, const FString& Title, const FString& Message );
|
|
|
|
virtual UBOOL Browse(FURL URL, FString& Error);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Pauses / unpauses the game-play when focus of the game's window gets lost / gained.
|
|
|
|
* @param EnablePause TRUE to pause; FALSE to unpause the game
|
|
|
|
*/
|
|
|
|
virtual void OnLostFocusPause( UBOOL EnablePause );
|
|
|
|
|
|
|
|
// One-time init
|
|
|
|
void LoadContentRootClass();
|
|
|
|
void LoadSeekFreePackages();
|
|
|
|
void LoadSeekFreeZedPackage();
|
|
|
|
void InitGfxSettings();
|
|
|
|
void DeallocatePlayfabServer();
|
|
|
|
void SyncInventoryProperties();
|
|
|
|
void SetSeasonalEventFromTitleData();
|
|
|
|
|
|
|
|
/** Initializes default resolution */
|
|
|
|
void InitializeResolution(INT CompatLevel);
|
|
|
|
|
|
|
|
virtual void PerformBetweenMapTasks();
|
|
|
|
|
|
|
|
#if __TW_INTERNET_TIME_
|
|
|
|
/** Trigger a network time lookup to update any time-based events (Weekly, Seasonal, etc) */
|
|
|
|
virtual void UpdateTimedGameEvents();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************************
|
|
|
|
* @name Content
|
|
|
|
***********************************************************************************/
|
|
|
|
native static function CacheToRoot(Object NewPackage);
|
|
|
|
native static function ClearCachedRootPackages();
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
|
|
* @name Debug
|
|
|
|
***********************************************************************************/
|
|
|
|
|
|
|
|
native static function bool CheckSkipLobby(); // If -skiplobby is added to the command line, return true
|
|
|
|
native static function bool CheckSkipGammaCheck(); // If -NoGammaStartup is added to the command line, return true
|
|
|
|
native static function bool CheckNoAutoStart(); // If -NoAutoStart is added to the command line, return true
|
|
|
|
native static function bool CheckNoMusic(); // If -NoMusic is added to the command line or PIE, return true
|
|
|
|
native static function bool CheckNoRandomStart(); // If -NoRandomStart is added to the command line or PIE, return true
|
|
|
|
|
|
|
|
/** Gets debug information for the number of loaded classes and their resource size*/
|
|
|
|
native static function GetClassCountAndSize(out int ClassCount, out float ClassSize, out float ResourceSize, class LoadedClass);
|
|
|
|
|
|
|
|
/** Returns the debug lines object, will create one if none exists */
|
|
|
|
native static function KFDebugLines GetDebugLines(); // Accessor for KFDebugLines, if enabled
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
|
|
* @name Platform / Online Backend
|
|
|
|
***********************************************************************************/
|
|
|
|
|
|
|
|
//Gets the game version for use on Steam
|
|
|
|
native static function int GetGameVersion();
|
|
|
|
/** Gets the current game version */
|
|
|
|
native static function int GetKFGameVersion();
|
|
|
|
/** Gets the current game Steam AppID */
|
|
|
|
native static function int GetAppID();
|
|
|
|
|
|
|
|
native static function SupportedPlatform GetPlatform();
|
|
|
|
native static function InitEventContent();
|
|
|
|
native static function RefreshEventContent();
|
|
|
|
|
|
|
|
// make sure our current tweak values are up-to-date with global
|
|
|
|
native static function RefreshOnlineGameData();
|
|
|
|
native static function ApplyTweaks(string MapName);
|
|
|
|
native static function bool IsLastRefreshTweakParamsSuccessful();
|
|
|
|
|
|
|
|
/** returns true if solo play should be disabled for this build */
|
|
|
|
native static function bool IsSoloPlayDisabled();
|
|
|
|
/** returns true if the free event has ended */
|
|
|
|
native static function bool IsFreeConsolePlayOver();
|
|
|
|
|
|
|
|
function ReadPFStoreData()
|
|
|
|
{
|
|
|
|
bReadingPlayfabStoreData = true;
|
|
|
|
// Read Playfab store data
|
|
|
|
GetPlayfabInterface().AddStoreDataReadCompleteDelegate(OnPlayfabStoreReadComplete);
|
|
|
|
GetPlayfabInterface().ReadStoreData();
|
|
|
|
}
|
|
|
|
|
|
|
|
function OnPlayfabStoreReadComplete(bool bSuccessful)
|
|
|
|
{
|
|
|
|
GetPlayfabInterface().ClearStoreDataReadCompleteDelegate(OnPlayfabStoreReadComplete);
|
|
|
|
|
|
|
|
if (bSuccessful)
|
|
|
|
{
|
|
|
|
if (class'WorldInfo'.static.IsConsoleBuild(CONSOLE_Durango))
|
|
|
|
{
|
|
|
|
OnlineSubsystem.MarketplaceInterface.ResetAvailableProducts(GamePlayers[0].ControllerId, MIT_GameContent);
|
|
|
|
OnlineSubsystem.MarketplaceInterface.ResetAvailableProducts(GamePlayers[0].ControllerId, MIT_GameConsumable);
|
|
|
|
OnlineSubsystem.MarketplaceInterface.AddReadAvailableProductsCompleteDelegate(GamePlayers[0].ControllerId, OnReadAvailableProductsComplete);
|
|
|
|
OnlineSubsystem.MarketplaceInterface.ReadAvailableProducts(GamePlayers[0].ControllerId, "", MIT_Game, MIT_GameContent);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Read PSN store data
|
|
|
|
OnlineSubsystem.PlayerInterfaceEx.AddStoreDataReadCompleteDelegate(OnStoreDataRead);
|
|
|
|
OnlineSubsystem.PlayerInterfaceEx.ReadStoreData();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function OnReadAvailableProductsComplete(EMediaItemType MediaType)
|
|
|
|
{
|
|
|
|
`log("Read products for store items of type"@MediaType);
|
|
|
|
|
|
|
|
// If this was the game content, kick off the consumable read request
|
|
|
|
if (MediaType == MIT_GameContent)
|
|
|
|
{
|
|
|
|
OnlineSubsystem.MarketplaceInterface.ReadAvailableProducts(GamePlayers[0].ControllerId, "", MIT_Game, MIT_GameConsumable);
|
|
|
|
}
|
|
|
|
// Reads all finished, next step is to read additional details for the products
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OnlineSubsystem.MarketplaceInterface.ClearReadAvailableProductsCompleteDelegate(GamePlayers[0].ControllerId, OnReadAvailableProductsComplete);
|
|
|
|
|
|
|
|
// Now read additional details for the products. We'll start with gamecontent again
|
|
|
|
OnlineSubsystem.MarketplaceInterface.AddReadAdditionalProductDetailsCompleteDelegate(GamePlayers[0].ControllerId, OnReadAdditionalProductDetailsComplete);
|
|
|
|
OnlineSubsystem.MarketplaceInterface.ReadAdditionalDetailsForProducts(GamePlayers[0].ControllerId, MIT_GameContent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function OnReadAdditionalProductDetailsComplete(EMediaItemType MediaType)
|
|
|
|
{
|
|
|
|
`log("Additional info for products read complete for type"@MediaType);
|
|
|
|
|
|
|
|
// If this was the game content, kick off the consumable read request
|
|
|
|
if (MediaType == MIT_GameContent)
|
|
|
|
{
|
|
|
|
OnlineSubsystem.MarketplaceInterface.ReadAdditionalDetailsForProducts(GamePlayers[0].ControllerId, MIT_GameConsumable);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OnlineSubsystem.MarketplaceInterface.ClearReadAdditionalProductDetailsCompleteDelegate(GamePlayers[0].ControllerId, OnReadAdditionalProductDetailsComplete);
|
|
|
|
|
|
|
|
// Now read inventory
|
|
|
|
OnlineSubsystem.MarketplaceInterface.AddReadInventoryItemsCompleteDelegate(GamePlayers[0].ControllerId, OnReadInventoryItemsComplete);
|
|
|
|
OnlineSubsystem.MarketplaceInterface.ResetInventoryItems(GamePlayers[0].ControllerId, MIT_All);
|
|
|
|
OnlineSubsystem.MarketplaceInterface.ReadInventoryItems(GamePlayers[0].ControllerId, MIT_All);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function OnReadInventoryItemsComplete(EMediaItemType MediaType)
|
|
|
|
{
|
|
|
|
`log("Inventory items read for"@MediaType);
|
|
|
|
OnlineSubsystem.MarketplaceInterface.ClearReadInventoryItemsCompleteDelegate(GamePlayers[0].ControllerId, OnReadInventoryItemsComplete);
|
|
|
|
OnStoreDataRead(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
function OnStoreDataRead(bool bSuccessful)
|
|
|
|
{
|
|
|
|
OnlineSubsystem.PlayerInterfaceEx.ClearStoreDataReadCompleteDelegate(OnStoreDataRead);
|
|
|
|
// Read playfab inventory
|
|
|
|
GetPlayfabInterface().AddInventoryReadCompleteDelegate(OnPlayfabInventoryReadComplete);
|
|
|
|
GetPlayfabInterface().ReadInventory();
|
|
|
|
}
|
|
|
|
|
|
|
|
function OnPlayfabInventoryReadComplete(bool bSuccessful)
|
|
|
|
{
|
|
|
|
bReadingPlayfabStoreData = false;
|
|
|
|
GetPlayfabInterface().ClearInventoryReadCompleteDelegate(OnPlayfabInventoryReadComplete);
|
|
|
|
OnlineSubsystem.ClearNewlyAdded();
|
|
|
|
}
|
|
|
|
|
|
|
|
function OnLinkStatusChange(bool bIsConnected)
|
|
|
|
{
|
|
|
|
OnConnectionStatusChanged(bIsConnected ? OSCS_Connected : OSCS_ConnectionDropped);
|
|
|
|
}
|
|
|
|
|
|
|
|
function OnConnectionStatusChanged(EOnlineServerConnectionStatus ConnectionStatus)
|
|
|
|
{
|
|
|
|
local KFGameViewportClient GVC;
|
|
|
|
|
|
|
|
// Let player controller handle state change
|
|
|
|
if (GamePlayers[0].Actor != none && KFPlayerController(GamePlayers[0].Actor) != none)
|
|
|
|
{
|
|
|
|
KFPlayerController(GamePlayers[0].Actor).HandleConnectionStatusChange(ConnectionStatus);
|
|
|
|
}
|
|
|
|
// Must be in a transition, kick back to main menu
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GetOnlineSubsystem().GameInterface.DestroyOnlineGame('Game');
|
|
|
|
GVC = KFGameViewportClient(class'GameEngine'.static.GetEngine().GameViewport);
|
|
|
|
GVC.bNeedDisconnectMessage = true;
|
|
|
|
GVC.ConsoleCommand("open KFMainMenu");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function OnLoginChange(byte LocalUserNum)
|
|
|
|
{
|
|
|
|
local OnlinePlayerInterface PlayerInterface;
|
|
|
|
|
|
|
|
PlayerInterface = GetOnlineSubsystem().PlayerInterface;
|
|
|
|
|
|
|
|
// Xbox kicks player back to IIS if active player signs out after an active user has been established
|
|
|
|
if( class'WorldInfo'.static.IsConsoleBuild(CONSOLE_Durango) &&
|
|
|
|
( KFGameViewportClient(GameViewport).bSeenIIS || (KFPlayerController(GamePlayers[0].Actor) != none && KFPlayerController(GamePlayers[0].Actor).HasActiveUserEstablished()) ) )
|
|
|
|
{
|
|
|
|
// Kick previously active player back to IIS with an error message.
|
|
|
|
if( LocalUserNum == GamePlayers[0].ControllerId && PlayerInterface.GetLoginStatus(LocalUserNum) != LS_LoggedIn )
|
|
|
|
{
|
|
|
|
KickBackToIIS("LoggedOutTitle", "LoggedOutMessage");
|
|
|
|
}
|
|
|
|
// Also kick back offline player if a user has signed in
|
|
|
|
else if( LocalLoginStatus == LS_UsingLocalProfile && PlayerInterface.GetLoginStatus(LocalUserNum) == LS_LoggedIn )
|
|
|
|
{
|
|
|
|
KickBackToIIS("LoggedInTitle", "LoggedOutMessage");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function OnLoginStatusChanged(ELoginStatus NewStatus, UniqueNetId NewId)
|
|
|
|
{
|
|
|
|
local KFGameViewportClient GVC;
|
|
|
|
local UniqueNetId ZeroId, LocalPlayerId;
|
|
|
|
|
|
|
|
LocalPlayerId = GamePlayers[0].GetUniqueNetId();
|
|
|
|
|
|
|
|
// Only bother with active user
|
|
|
|
if (LocalPlayerId == NewId && NewId != ZeroId)
|
|
|
|
{
|
|
|
|
// Let player controller handle state change
|
|
|
|
if (GamePlayers[0].Actor != none && KFPlayerController(GamePlayers[0].Actor) != none)
|
|
|
|
{
|
|
|
|
KFPlayerController(GamePlayers[0].Actor).HandleLoginStatusChange(NewStatus == LS_LoggedIn);
|
|
|
|
}
|
|
|
|
// Logged out
|
|
|
|
else if (NewStatus == LS_NotLoggedIn)
|
|
|
|
{
|
|
|
|
GetOnlineSubsystem().GameInterface.DestroyOnlineGame('Game');
|
|
|
|
GVC = KFGameViewportClient(GameViewport);
|
|
|
|
GVC.bNeedSignoutMessage = true;
|
|
|
|
GVC.ConsoleCommand("open KFMainMenu");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function KickBackToIIS(string ErrorTitleKey, string ErrorMessageKey)
|
|
|
|
{
|
|
|
|
// Set the cached errors
|
|
|
|
ReturnToIISConnectionErrorTitle = Localize("Notifications", ErrorTitleKey, "KFGameConsole");
|
|
|
|
ReturnToIISConnectionErrorMessage = Localize("Notifications", ErrorMessageKey, "KFGameConsole");;
|
|
|
|
|
|
|
|
// Now perform logout
|
|
|
|
PerformLogout();
|
|
|
|
}
|
|
|
|
|
|
|
|
function PerformLogout()
|
|
|
|
{
|
|
|
|
local UIDataStore_OnlinePlayerData PlayerDataDS;
|
|
|
|
|
|
|
|
OnlineSubsystem.PlayerInterface.Logout(GamePlayers[0].ControllerId);
|
|
|
|
if (PlayfabInterfaceInst != none)
|
|
|
|
{
|
|
|
|
PlayfabInterfaceInst.Logout();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Logout active player
|
|
|
|
OnlineSubsystem.PlayerInterface.Logout(GamePlayers[0].ControllerId);
|
|
|
|
|
|
|
|
// Reset the async state for the profile settings so a full read will complete
|
|
|
|
PlayerDataDS = UIDataStore_OnlinePlayerData(class'UIInteraction'.static.GetDataStoreClient().FindDataStore('OnlinePlayerData', GamePlayers[0]));
|
|
|
|
PlayerDataDS.ProfileProvider.Profile.AsyncState = OPAS_NotStarted;
|
|
|
|
|
|
|
|
// Clear seen IIS flag
|
|
|
|
KFGameViewportClient(GameViewport).bSeenIIS = false;
|
|
|
|
|
|
|
|
// Destroy active game session
|
|
|
|
OnlineSubsystem.GameInterface.DestroyOnlineGame('Game');
|
|
|
|
|
|
|
|
// If we have a player controller, let it handle the state
|
|
|
|
if (GamePlayers[0].Actor != none && KFPlayerController(GamePlayers[0].Actor) != none)
|
|
|
|
{
|
|
|
|
KFPlayerController(GamePlayers[0].Actor).PerformLogout();
|
|
|
|
}
|
|
|
|
// Must be in a transition. Kick back to the menu
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GameViewport.ConsoleCommand("open KFMainMenu");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function RegisterOnlineDelegates()
|
|
|
|
{
|
|
|
|
local int i;
|
|
|
|
|
|
|
|
OnlineSubsystem.SystemInterface.AddConnectionStatusChangeDelegate(OnConnectionStatusChanged);
|
|
|
|
|
|
|
|
for (i = 0; i < `MAX_NUM_PLAYERS; i++)
|
|
|
|
{
|
|
|
|
OnlineSubsystem.PlayerInterface.AddLoginStatusChangeDelegate(OnLoginStatusChanged, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
OnlineSubsystem.PlayerInterface.AddLoginChangeDelegate(OnLoginChange);
|
|
|
|
}
|
|
|
|
|
|
|
|
function ClearOnlineDelegates()
|
|
|
|
{
|
|
|
|
local int i;
|
|
|
|
|
|
|
|
OnlineSubsystem.SystemInterface.ClearConnectionStatusChangeDelegate(OnConnectionStatusChanged);
|
|
|
|
|
|
|
|
for (i = 0; i < `MAX_NUM_PLAYERS; i++)
|
|
|
|
{
|
|
|
|
OnlineSubsystem.PlayerInterface.ClearLoginStatusChangeDelegate(OnLoginStatusChanged, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
OnlineSubsystem.PlayerInterface.ClearLoginChangeDelegate(OnLoginChange);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Static because these are both called on default object */
|
|
|
|
native static function int GetSeasonalEventID();
|
|
|
|
native static function int GetWeeklyEventIndex();
|
2020-12-13 15:09:05 +00:00
|
|
|
native static function bool IsSalesEventActive();
|
|
|
|
native static function bool IsSalesEventChecked();
|
2020-12-13 15:01:13 +00:00
|
|
|
/***********************************************************************************
|
|
|
|
* @name Game Options
|
|
|
|
***********************************************************************************/
|
|
|
|
native static function InitAudioOptions();
|
|
|
|
native static function InitGamma();
|
|
|
|
|
|
|
|
native static function SetWWiseSFXVolume( float Volume );
|
|
|
|
native static function SetWWiseMusicVolume( float Volume );
|
|
|
|
native static function SetWWiseVoiceVolume( float Volume );
|
|
|
|
native static function SetWWiseMasterVolume( float Volume );
|
|
|
|
native static function SetWWisePADVolume( float Volume );
|
|
|
|
native static function SetVoIPRecieveVolume( float Volume );
|
|
|
|
native static function SetVoIPMicRecieveVolume( float Volume );
|
|
|
|
native static function GetVoIPVolumeRange(out float MinVol, out float MaxVol, out float CurrentVol);
|
|
|
|
native static function PlayFullScreenMovie(string MovieName);
|
|
|
|
native static function bool IsFullScreenMoviePlaying();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the current gamma value.
|
|
|
|
*
|
|
|
|
* @param New Gamma Value, must be between 0.0 and 1.0
|
|
|
|
*/
|
|
|
|
native static function SetGamma(float InGammaMultiplier);
|
|
|
|
native static function SetNative4k(bool InEnableNative4k);
|
|
|
|
native static function SwitchNative4k();
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
|
|
* @name Server takeover/reconfigure
|
|
|
|
***********************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper function that will return an enum value representative of the actual error that occurred
|
|
|
|
* We have to do this by comparing the localized connection error message to what we know exists in the localization files
|
|
|
|
*
|
|
|
|
* @param Message the localized connection error message
|
|
|
|
*
|
|
|
|
* @return The EConnectionError representing the actual error that occurred
|
|
|
|
*/
|
|
|
|
static function EConnectionError GetConnectionErrorForMessage(out string Message, out string Title)
|
|
|
|
{
|
|
|
|
if (Message == "<Strings:Engine.AccessControl.NeedPassword>") {
|
|
|
|
return CE_NeedPassword;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Message == "<Strings:Engine.AccessControl.WrongPassword>") {
|
|
|
|
return CE_WrongPassword;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CE_Generic;
|
|
|
|
}
|
|
|
|
|
|
|
|
function SetLastConnectionError(string Message, string Title)
|
|
|
|
{
|
|
|
|
if (LastConnectionError == CE_None) {
|
|
|
|
// Let's try to determine what exactly happened here ... and unfortunately we only have these localized strings to do it
|
|
|
|
LastConnectionError = GetConnectionErrorForMessage(Message, Title);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delegate bool HandshakeCompleteCallback(bool bSuccess, string Error, out int SuppressPasswordRetry);
|
|
|
|
|
|
|
|
event bool CheckHandshakeComplete(EProgressMessageType MessageType, string Title, out int SuppressPasswordRetry, out int Cleanup)
|
|
|
|
{
|
|
|
|
local bool SuppressPopup;
|
|
|
|
|
|
|
|
SuppressPopup = false;
|
|
|
|
Cleanup = 0;
|
|
|
|
|
|
|
|
if (OnHandshakeComplete != None)
|
|
|
|
{
|
|
|
|
switch (MessageType)
|
|
|
|
{
|
|
|
|
case PMT_ConnectionFailure:
|
|
|
|
case PMT_PeerConnectionFailure:
|
|
|
|
case PMT_PeerHostMigrationFailure:
|
|
|
|
case PMT_SocketFailure:
|
|
|
|
Cleanup = 1;
|
|
|
|
SuppressPopup = OnHandshakeComplete(false, Title, SuppressPasswordRetry);
|
|
|
|
break;
|
|
|
|
case PMT_Information:
|
|
|
|
if (Title == "HandshakeDone") //This string is set in UnPenLev.cpp UNetPendingLevel::NotifyControlMessage
|
|
|
|
{
|
|
|
|
SuppressPopup = OnHandshakeComplete(true, Title, SuppressPasswordRetry);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return SuppressPopup;
|
|
|
|
}
|
|
|
|
|
|
|
|
native static function CancelPendingLevel();
|
|
|
|
|
|
|
|
function bool IsLockedServer()
|
|
|
|
{
|
|
|
|
return bUsedForTakeover && !bAvailableForTakeover;
|
|
|
|
}
|
|
|
|
|
|
|
|
function UnlockServer()
|
|
|
|
{
|
|
|
|
local UniqueNetId NullId;
|
|
|
|
|
|
|
|
if (class'WorldInfo'.static.GetWorldInfo().NetMode == NM_DedicatedServer)
|
|
|
|
{
|
|
|
|
//`REMOVEMESOON_ServerTakeoverLog("KFGameEngine.UnlockServer - bUsedForTakeover: "$bUsedForTakeover);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bUsedForTakeover)
|
|
|
|
{
|
|
|
|
`log("***The server is now unlocked and available for takeover!");
|
|
|
|
ConsoleGameSessionGuid = "";
|
|
|
|
KFGameReplicationInfo(class'WorldInfo'.static.GetWorldInfo().GRI).ConsoleGameSessionHost = NullId;
|
|
|
|
bAvailableForTakeover = true;
|
|
|
|
bPrivateServer = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
native function KillPendingServerConnection();
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
|
|
* @name Misc Helpers
|
|
|
|
***********************************************************************************/
|
|
|
|
/**
|
|
|
|
* Wrapper for engine fast trace
|
|
|
|
* Very fast, uses RBCC_Visibility. Returns TRUE if did not hit world geometry. Does not use extents or complex collision.
|
|
|
|
* @NOTE: Will not hit KFDoorActors, KFDestructibleActors, KFFracturedMeshActors, or CanBecomeDynamic() actors
|
|
|
|
*/
|
|
|
|
native static function bool FastTrace_PhysX( vector TraceEnd, vector TraceStart );
|
|
|
|
|
|
|
|
/* TODO: Using LoadPackageAsync
|
|
|
|
|
|
|
|
* Calling "LoadPackageAsync" will load the entirety of a package (ex. all of KFGameContent), however all unused classes will be garbage collected shortly after
|
|
|
|
* Create separate arrays of loaded and pending load classes for weapons, characters and possibly zeds
|
|
|
|
* By storing a loaded class in an array, it will not get garbage collected and we will not need to reload a package for a class that we already have
|
|
|
|
* To access this class, search through the array and spawn it whereever it is needed
|
|
|
|
|
|
|
|
* Gears of War 3 uses LoadPackageAsync only when they are using SeekFreeLoading, otherwise classes will be DLO'd immediately
|
|
|
|
* Gears of War 3 uses a different cooking method to read from smaller cooked packages that can be loaded asynchronously without having to load something like "GearGame"
|
|
|
|
* Gears of War 3 has an object class that exists specifically for holding loaded classes of a certain package (ex. class GearMPCharacterStore)
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** Get the canvas font used for KF */
|
|
|
|
static function Font GetKFCanvasFont()
|
|
|
|
{
|
|
|
|
return default.KFCanvasFont;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Get the universal scalar for the KFCanvasFont */
|
|
|
|
static function float GetKFFontScale()
|
|
|
|
{
|
|
|
|
return default.KFFontScale;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Get value of crosshair option */
|
|
|
|
static function bool IsCrosshairEnabled()
|
|
|
|
{
|
|
|
|
return default.bShowCrossHair;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Set value of crosshair option */
|
|
|
|
static function SetCrosshairEnabled(bool bEnable)
|
|
|
|
{
|
|
|
|
default.bShowCrossHair = bEnable;
|
|
|
|
|
|
|
|
if ( !Class'WorldInfo'.Static.IsConsoleBuild() )
|
|
|
|
{
|
|
|
|
StaticSaveConfig();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DefaultProperties
|
|
|
|
{
|
|
|
|
DefaultGammaMult=.68
|
|
|
|
KFCanvasFont=Font'UI_Canvas_Fonts.Font_Main'
|
|
|
|
KFFontScale=0.65f
|
|
|
|
SeasonalEventId=-1
|
|
|
|
LoadedSeasonalEventId=-1
|
|
|
|
WeeklyEventIndex=-1
|
|
|
|
LocalLoginStatus=LS_LoggedIn
|
|
|
|
SafeFrameScale=1.0
|
|
|
|
|
|
|
|
MasterVolumeMultiplier=50.0
|
|
|
|
DialogVolumeMultiplier=50.0
|
|
|
|
MusicVolumeMultiplier=50.0
|
|
|
|
SFxVolumeMultiplier=50.0
|
|
|
|
|
|
|
|
// By default disable AILogging (see `define AILog)
|
|
|
|
// by command line: '-enableailogging'
|
|
|
|
// by cheat: 'ToggleAILogging'
|
|
|
|
bDisableAILogging=true
|
|
|
|
}
|