270 lines
10 KiB
Ucode
270 lines
10 KiB
Ucode
//=============================================================================
|
|
// SteamStatsAndAchievementsBase
|
|
//=============================================================================
|
|
// Interface between Steam Stats/Achievements and RO/Mods
|
|
//=============================================================================
|
|
// Red Orchestra Source
|
|
// Copyright (C) 2003-2009 Tripwire Interactive LLC
|
|
// Created by Dayle Flowers
|
|
//=============================================================================
|
|
|
|
class SteamStatsAndAchievementsBase extends Actor
|
|
native;
|
|
|
|
struct native export SteamStatInt
|
|
{
|
|
var const int Value; // Value of this Stat(can be set by calling SetStatInt)
|
|
};
|
|
|
|
struct native export SteamStatFloat
|
|
{
|
|
var const float Value; // Value of this Stat(can be set by calling SetStatFloat)
|
|
};
|
|
|
|
// Steam updates an Averaging stat by adding SessionNumerator to the existing Numerator in the Steam Database and SessionDenominator
|
|
// to the existing Denominator in the Steam Database(which only exists on the client). These stats are only able to be grabbed as
|
|
// floats from Steam, but when the client sends the new Session Values Averages to Steam, the Steam Database does a full Numerator
|
|
// over Denominator calculation with the new Session Data. In short, this is not a reliable system for checking Achievements on the
|
|
// Server in real-time, as you only get the resulting Float *after* the client sends the data to Steam and the Steam Database has
|
|
// time to recalculate the new average. The latest Float Value is only valid in OnStatsAndAchievementsReady and should not be
|
|
// considered reliable outside of that function.
|
|
struct native export SteamStatAverage
|
|
{
|
|
var const float NumeratorValue; // Numerator Value of this Stat during this Session
|
|
var const float DenominatorValue; // Denominator Value of this Stat during this Session
|
|
};
|
|
|
|
// Set to true once we've pulled Stats from the Database(prevents Steam screwing up and erasing Stats in Single Player)
|
|
var bool bInitialized;
|
|
|
|
// Owner of these Stats and Achievements
|
|
var PlayerController PCOwner;
|
|
|
|
// Set to true by the Timer function to allow us to completely control replication
|
|
var bool bFlushStatsToClient;
|
|
|
|
// Number of seconds between sending Stats to client
|
|
var float FlushStatsToClientDelay;
|
|
|
|
// Steam Names
|
|
var array<string> SteamNameStat;
|
|
var array<string> SteamNameAchievement;
|
|
|
|
// Used to track if God Mode, weapon cheats, summoning, and others have ever been used
|
|
var bool bUsedCheats;
|
|
|
|
// Debug
|
|
var globalconfig bool bResetStats;
|
|
var globalconfig bool bDebugStats;
|
|
|
|
// Delegate callback for Stats and Achievements data initialization completion
|
|
delegate OnDataInitialized();
|
|
|
|
// Gets the Server ready to handle Stats
|
|
native final function bool Initialize(PlayerController MyOwner);
|
|
|
|
// Requests the Owner's Stats and Achievements from Steam(calls OnStatsAndAchievementsReady when completed)
|
|
native final function GetStatsAndAchievements();
|
|
|
|
// Functions to grab individual Stats and Achievements from Steam by name(generally done from the OnStatsAndAchievementsReady callback)
|
|
native final function GetStatInt(SteamStatInt Stat, string SteamName);
|
|
native final function GetStatFloat(SteamStatFloat Stat, string SteamName);
|
|
native final function float GetStatAverage(string SteamName);
|
|
native final function bool GetAchievementCompleted(string SteamName);
|
|
|
|
// Used to natively Initialize the const Stat Variables(Server-side only)
|
|
native final function InitStatInt(SteamStatInt Stat, int NewValue);
|
|
native final function InitStatFloat(SteamStatFloat Stat, float NewValue);
|
|
|
|
// Used to natively Set the const Stat Variables(Server-side only)
|
|
native final function SetStatInt(SteamStatInt Stat, int NewValue);
|
|
native final function SetStatFloat(SteamStatFloat Stat, float NewValue);
|
|
native final function SetStatAverage(SteamStatAverage Stat, float NewNumerator, float NewDenominator);
|
|
|
|
// Called to set bNetDirty which forces replication to the owning client at a preset interval
|
|
native final function SetNetDirty();
|
|
|
|
// Send the specified Int/Float/Stat to the Local Steam Client, not the Steam Database(Client-Side only)
|
|
// NOTE: For Average stats, we send Stat.Numerator - SavedStat.Numerator and Stat.Denominator - SavedStat.Denominator,
|
|
// because Steam is keeping a running total behind the scenes.
|
|
native final function FlushStatToSteamInt(SteamStatInt Stat, string SteamName);
|
|
native final function FlushStatToSteamFloat(SteamStatFloat Stat, string SteamName);
|
|
native final function FlushStatToSteamAverage(SteamStatAverage Stat, SteamStatAverage SavedStat, string SteamName);
|
|
native final function SetAchievementCompleted(string SteamName);
|
|
|
|
// Call after all Stats have been changed on the Client to send changed stats from the local Steam Client to the Steam Database
|
|
native final function FlushStatsToSteamDatabase();
|
|
|
|
// Returns the displayable information set in the SteamWork's Database
|
|
native final function GetAchievementDescription(string SteamName, out string DisplayName, out string Description);
|
|
|
|
native simulated final function bool DoPotato();
|
|
|
|
// Returns an integer representation of Owned Weapon DLC Packs
|
|
native final function int GetOwnedWeaponDLC();
|
|
|
|
// Determines whether or not this player owns a particular Weapon DLC AppID
|
|
simulated function bool PlayerOwnsWeaponDLC(int AppID);
|
|
native final function bool OwnsWeaponDLC(int AppID, SteamStatInt OwnedWeaponDLCStat);
|
|
|
|
// Opens the Steam Store page for the specified AppID
|
|
native final function PurchaseWeaponDLC(int AppID);
|
|
|
|
// Fetches the name of the specified Weapons DLC Pack
|
|
function string GetWeaponDLCPackName(int AppID);
|
|
|
|
// Opens the Steam Overlay directly to the Game's Steam Workshop page
|
|
native final function ShowWorkshopContent();
|
|
|
|
// Fetches a user ID for the owning PC
|
|
native final function string GetSteamUserID();
|
|
|
|
cpptext
|
|
{
|
|
#include "SteamStatsAndAchievementsBase.h"
|
|
}
|
|
|
|
replication
|
|
{
|
|
reliable if ( Role == ROLE_Authority )
|
|
bUsedCheats;
|
|
}
|
|
|
|
// Called via Client to Server function in PlayerController to start the FlushStatsToClient timing
|
|
function ServerSteamStatsAndAchievementsInitialized()
|
|
{
|
|
if ( bDebugStats )
|
|
log("STEAMSTATS: ServerSteamStatsAndAchievementsInitialized called");
|
|
|
|
bInitialized = true;
|
|
SetTimer(FlushStatsToClientDelay, false);
|
|
}
|
|
|
|
event PostBeginPlay()
|
|
{
|
|
PlayerDied();
|
|
}
|
|
|
|
// Overridden to Grab the Stats and Achievements from Steam on the Client
|
|
simulated event PostNetBeginPlay()
|
|
{
|
|
if ( Level.NetMode == NM_Client )
|
|
{
|
|
if ( bDebugStats )
|
|
log("STEAMSTATS: PostNetBeginPlay grabbing Stats - StatsObject="$self);
|
|
|
|
GetStatsAndAchievements();
|
|
|
|
PCOwner = Level.GetLocalPlayerController();
|
|
}
|
|
}
|
|
|
|
// Overridden in subclasses to send the Stats/Achievements that have changed to Steam
|
|
//simulated event PostNetReceive();
|
|
|
|
// Called at set interval to push all Stats to Client, then called again to reset
|
|
// NETWORK: Server only
|
|
event Timer()
|
|
{
|
|
// We use bFlushStatsToClient to control when things are sent
|
|
if ( !bFlushStatsToClient )
|
|
{
|
|
FlushStatsToClient();
|
|
}
|
|
|
|
// Soon after FlushStatsToClientw is called above, Timer gets called again to clear bFlushStatsToClient
|
|
else
|
|
{
|
|
bFlushStatsToClient = false;
|
|
SetTimer(FlushStatsToClientDelay, false);
|
|
}
|
|
}
|
|
|
|
// Called on Server(via Timer) to push all Stats to Client
|
|
// NETWORK: Server only
|
|
function FlushStatsToClient()
|
|
{
|
|
// if it's a local player, just send stuff off to Steam from here
|
|
if ( Level.NetMode == NM_Standalone || (Level.NetMode == NM_ListenServer && PCOwner == Level.GetLocalPlayerController()) )
|
|
{
|
|
PostNetReceive();
|
|
SetTimer(FlushStatsToClientDelay, false);
|
|
}
|
|
else
|
|
{
|
|
if ( bDebugStats )
|
|
log("STEAMSTATS: Flushing Stats to Client");
|
|
|
|
// Force Stats to be sent to Client immediately
|
|
NetUpdateTime = Level.TimeSeconds - 1.0;
|
|
bFlushStatsToClient = true;
|
|
SetNetDirty();
|
|
|
|
// Clear bFlushStatsToClient once completed
|
|
SetTimer(0.1, false);
|
|
}
|
|
}
|
|
|
|
// Event Callback for GetStatsAndAchievements call(Call PCOwner.ServerSteamStatsAndAchievementsInitialized when done)
|
|
// NETWORK: Client only
|
|
simulated event OnStatsAndAchievementsReady()
|
|
{
|
|
if ( PCOwner != none && PCOwner.PlayerReplicationInfo != none )
|
|
{
|
|
PCOwner.PlayerReplicationInfo.SteamStatsAndAchievements = self;
|
|
}
|
|
|
|
bInitialized = true;
|
|
PCOwner.ServerSteamStatsAndAchievementsInitialized();
|
|
OnDataInitialized();
|
|
}
|
|
|
|
// Called on Server to initialize Stats from Client replication, because Servers can't access Steam Stats directly
|
|
function InitializeSteamStatInt(int Index, int Value);
|
|
|
|
// Called on Server to initialize Stats from Client replication, because Servers can't access Steam Stats directly
|
|
function InitializeSteamStatFloat(int Index, float Value);
|
|
|
|
// Sets the specified Steam Achievement as completed; also, flushes all Stats and Achievements to the client
|
|
function SetSteamAchievementCompleted(int Index)
|
|
{
|
|
if( PCOwner.PlayerReplicationInfo.bOnlySpectator )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( bDebugStats )
|
|
log("STEAMSTATS: SetSteamAchievementCompleted called - Name="$SteamNameAchievement[Index] @ "Player="$PCOwner.PlayerReplicationInfo.PlayerName);
|
|
|
|
FlushStatsToClient();
|
|
SetLocalAchievementCompleted(Index);
|
|
SetAchievementCompleted(SteamNameAchievement[Index]);
|
|
}
|
|
|
|
// Called from multiple locations on Client and Server to set Achievement booleans for later use
|
|
simulated event SetLocalAchievementCompleted(int Index);
|
|
|
|
// Called when the owner of this Stats Actor dies(used in subclasses to reset "in one life" stats)
|
|
function PlayerDied();
|
|
|
|
native function SteamAPICall(string callString);
|
|
|
|
function CheckEvents( Name EventName );
|
|
|
|
defaultproperties
|
|
{
|
|
FlushStatsToClientDelay=10.0
|
|
|
|
RemoteRole=ROLE_SimulatedProxy
|
|
bAlwaysRelevant=false
|
|
bOnlyRelevantToOwner=true
|
|
bOnlyDirtyReplication=true
|
|
bSkipActorPropertyReplication=true
|
|
bNetNotify=true
|
|
NetUpdateFrequency=5
|
|
|
|
bStatic=false
|
|
bNoDelete=false
|
|
bHidden=true
|
|
}
|