403 lines
15 KiB
Ucode
403 lines
15 KiB
Ucode
/**
|
|
* Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
|
|
*
|
|
* Gameplay event interface
|
|
*/
|
|
class GameplayEvents extends Object
|
|
abstract
|
|
native;
|
|
|
|
`include(Engine\Classes\GameStats.uci);
|
|
|
|
// Bitmasks for flags stored on the MCP header
|
|
const HeaderFlags_NoEventStrings = 1;
|
|
|
|
/** Stat verbosity level */
|
|
enum EGameStatGroups
|
|
{
|
|
GSG_EngineStats,
|
|
GSG_Game,
|
|
GSG_Team,
|
|
GSG_Player,
|
|
GSG_Weapon,
|
|
GSG_Damage,
|
|
GSG_Projectile,
|
|
GSG_Pawn,
|
|
GSG_GameSpecific,
|
|
GSG_Aggregate
|
|
};
|
|
|
|
struct native GameStatGroup
|
|
{
|
|
/** Group stat belongs to*/
|
|
var EGameStatGroups Group;
|
|
/** Level of the stat */
|
|
var int Level;
|
|
|
|
structcpptext
|
|
{
|
|
friend FArchive& operator<<( FArchive& Ar, FGameStatGroup& T );
|
|
}
|
|
};
|
|
|
|
/** Basic file header when writing to disk */
|
|
struct native GameplayEventsHeader
|
|
{
|
|
/** Version of engine at the time of writing the file */
|
|
var const int EngineVersion;
|
|
|
|
/** Version of the stats format at the time of writing the file */
|
|
var const int StatsWriterVersion;
|
|
|
|
/** Offset into the file for the stream data */
|
|
var const int StreamOffset;
|
|
|
|
/** Offset into the file for aggregate data */
|
|
var const int AggregateOffset;
|
|
|
|
/** Offset into the file where the metadata is written */
|
|
var const int FooterOffset;
|
|
|
|
/** Amount of data in the stream (not including header/footer data) */
|
|
var const int TotalStreamSize;
|
|
|
|
/** File size on disk */
|
|
var const int FileSize;
|
|
|
|
/** What filter class is being used on the data, if any */
|
|
var string FilterClass;
|
|
|
|
/** Various settings */
|
|
var int Flags;
|
|
};
|
|
|
|
/** Game stats session information recorded at log start */
|
|
struct native GameSessionInformation
|
|
{
|
|
/** Unique title identifier */
|
|
var int AppTitleID;
|
|
|
|
/** Platform the session was run on */
|
|
var int PlatformType;
|
|
|
|
/** Language the session was run in */
|
|
var string Language;
|
|
|
|
/** Time this session was begun (real time) */
|
|
var const string GameplaySessionTimestamp;
|
|
|
|
/** Time this session was started (game time) */
|
|
var const float GameplaySessionStartTime;
|
|
|
|
/** Time this session was ended (game time) */
|
|
var const float GameplaySessionEndTime;
|
|
|
|
/** Is a session currently in progress */
|
|
var const bool bGameplaySessionInProgress;
|
|
|
|
/** Unique session ID */
|
|
var const string GameplaySessionID;
|
|
|
|
/** Name of the game class used */
|
|
var const string GameClassName;
|
|
|
|
/** Name of map at time of session */
|
|
var const string MapName;
|
|
|
|
/** Game URL at time of session */
|
|
var const string MapURL;
|
|
|
|
/** Value used to distinguish between contiguous sections */
|
|
var const int SessionInstance;
|
|
|
|
/** Gametype ID */
|
|
var const int GameTypeId;
|
|
|
|
/** UniqueID of player logging stats */
|
|
var const UniqueNetId OwningNetId;
|
|
|
|
/** ID of the playlist in use */
|
|
var int PlaylistId;
|
|
|
|
structcpptext
|
|
{
|
|
/** Constructors */
|
|
FGameSessionInformation() {}
|
|
FGameSessionInformation(EEventParm)
|
|
{
|
|
appMemzero(this, sizeof(FGameSessionInformation));
|
|
}
|
|
|
|
/** Return the unique key for this session */
|
|
const FString GetSessionID() const { return FString::Printf(TEXT("%s:%d"), *GameplaySessionID, SessionInstance); }
|
|
}
|
|
};
|
|
|
|
/** List of team information cached during the play session */
|
|
struct native TeamInformation
|
|
{
|
|
/** Index of the team in game */
|
|
var int TeamIndex;
|
|
|
|
/** Name of the team */
|
|
var string TeamName;
|
|
|
|
/** Color of the team */
|
|
var color TeamColor;
|
|
|
|
/** Max size during the game */
|
|
var int MaxSize;
|
|
|
|
structcpptext
|
|
{
|
|
friend FArchive& operator<<( FArchive& Ar, FTeamInformation& T );
|
|
}
|
|
};
|
|
|
|
/** List of player information cached in case the player logs out and GC collects the objects */
|
|
struct native PlayerInformation
|
|
{
|
|
/** Name of Controller object */
|
|
var name ControllerName;
|
|
/** Controller.PlayerReplicationInfo.PlayerName */
|
|
var string PlayerName;
|
|
/** UniqueID of the player */
|
|
var UniqueNetId UniqueId;
|
|
/** Whether the player is a bot or not */
|
|
var bool bIsBot;
|
|
|
|
structcpptext
|
|
{
|
|
friend FArchive& operator<<( FArchive& Ar, FPlayerInformation& T );
|
|
}
|
|
};
|
|
|
|
/** Holds the information describing a gameplay event */
|
|
struct native GameplayEventMetaData
|
|
{
|
|
/** The unique id of the event (16 bits clamped) */
|
|
var const int EventID;
|
|
|
|
/** Human readable name of the event */
|
|
var const name EventName;
|
|
|
|
/** Group that this stat belongs to, for filtering */
|
|
var const GameStatGroup StatGroup;
|
|
|
|
/** Type of data associated with this event */
|
|
var const int EventDataType;
|
|
|
|
structcpptext
|
|
{
|
|
friend FArchive& operator<<( FArchive& Ar, FGameplayEventMetaData& T );
|
|
}
|
|
};
|
|
|
|
/** Metadata describing the weapon classes recorded during gameplay */
|
|
struct native WeaponClassEventData
|
|
{
|
|
/** Name of the weapon class used **/
|
|
var name WeaponClassName;
|
|
|
|
structcpptext
|
|
{
|
|
friend FArchive& operator<<( FArchive& Ar, FWeaponClassEventData& T );
|
|
}
|
|
};
|
|
|
|
/** Metadata describing the damage classes recorded during gameplay */
|
|
struct native DamageClassEventData
|
|
{
|
|
/** Name of the damage class used **/
|
|
var name DamageClassName;
|
|
|
|
structcpptext
|
|
{
|
|
friend FArchive& operator<<( FArchive& Ar, FDamageClassEventData& T );
|
|
}
|
|
};
|
|
|
|
/** Metadata describing the projectile classes recorded during gameplay */
|
|
struct native ProjectileClassEventData
|
|
{
|
|
/** name of the projectile class used **/
|
|
var name ProjectileClassName;
|
|
|
|
structcpptext
|
|
{
|
|
friend FArchive& operator<<( FArchive& Ar, FProjectileClassEventData& T );
|
|
}
|
|
};
|
|
|
|
/** Metadata describing the pawn classes recorded during gameplay */
|
|
struct native PawnClassEventData
|
|
{
|
|
/** Name of the pawn class used **/
|
|
var name PawnClassName;
|
|
|
|
structcpptext
|
|
{
|
|
friend FArchive& operator<<( FArchive& Ar, FPawnClassEventData& T );
|
|
}
|
|
};
|
|
|
|
cpptext
|
|
{
|
|
/** Access the current session info */
|
|
const FGameSessionInformation& GetSessionInfo() const
|
|
{
|
|
return CurrentSessionInfo;
|
|
}
|
|
|
|
/** Returns the metadata associated with the given index */
|
|
virtual const FGameplayEventMetaData& GetEventMetaData(INT EventID) const;
|
|
|
|
/** Returns the metadata associated with the given index */
|
|
const FTeamInformation& GetTeamMetaData(INT TeamIndex) const;
|
|
|
|
/** Returns the metadata associated with the given index */
|
|
const FPlayerInformation& GetPlayerMetaData(INT PlayerIndex) const;
|
|
|
|
/** Returns the metadata associated with the given index */
|
|
const FPawnClassEventData& GetPawnMetaData(INT PawnClassIndex) const;
|
|
|
|
/** Returns the metadata associated with the given index */
|
|
const FWeaponClassEventData& GetWeaponMetaData(INT WeaponClassIndex) const;
|
|
|
|
/** Returns the metadata associated with the given index */
|
|
const FDamageClassEventData& GetDamageMetaData(INT DamageClassIndex) const;
|
|
|
|
/** Returns the metadata associated with the given index */
|
|
const FProjectileClassEventData& GetProjectileMetaData(INT ProjectileClassIndex) const;
|
|
|
|
/**
|
|
* Returns the metadata associated with the given index
|
|
* @param ActorIndex the index of the actor being looked up
|
|
* @return the name of the actor at that index
|
|
*/
|
|
const FString& GetActorMetaData(INT ActorIndex) const
|
|
{
|
|
return ActorArray(ActorIndex);
|
|
}
|
|
|
|
/**
|
|
* Returns the metadata associated with the given index
|
|
* @param SoundIndex the index of the soundcue being looked up
|
|
* @return the name of the actor at that index
|
|
*/
|
|
const FString& GetSoundMetaData(INT SoundIndex) const
|
|
{
|
|
return SoundCueArray(SoundIndex);
|
|
}
|
|
};
|
|
|
|
/** FArchive pointer to serialize the data to/from disk */
|
|
var const native pointer Archive{FArchive};
|
|
|
|
/** The name of the file we are writing the data to (const so set only upon create natively) */
|
|
var const private string StatsFileName;
|
|
|
|
/** Header of the gameplay events file */
|
|
var GameplayEventsHeader Header;
|
|
|
|
/** Information specific to the session when it was run */
|
|
var GameSessionInformation CurrentSessionInfo;
|
|
|
|
/** Array of all players 'seen' by the game in this session **/
|
|
var const array<PlayerInformation> PlayerList;
|
|
|
|
/** Array of all teams 'seen' by the game in this session **/
|
|
var const array<TeamInformation> TeamList;
|
|
|
|
/** The set of events that the game supports writing to disk */
|
|
var array<GameplayEventMetaData> SupportedEvents;
|
|
|
|
/** The set of weapons recorded during gameplay */
|
|
var array<WeaponClassEventData> WeaponClassArray;
|
|
|
|
/** The set of damage types recorded during gameplay */
|
|
var array<DamageClassEventData> DamageClassArray;
|
|
|
|
/** The set of projectiles recorded during gameplay */
|
|
var array<ProjectileClassEventData> ProjectileClassArray;
|
|
|
|
/** The set of pawns recorded during gameplay */
|
|
var array<PawnClassEventData> PawnClassArray;
|
|
|
|
/** The set of actors recorded during gameplay */
|
|
var array<String> ActorArray;
|
|
|
|
/** The set of sound cues encountered during gameplay */
|
|
var array<String> SoundCueArray;
|
|
|
|
/**
|
|
* Creates the archive that we are going to be manipulating
|
|
* @param Filename - name of the file that will be open for serialization
|
|
* @return TRUE if successful, else FALSE
|
|
*/
|
|
function bool OpenStatsFile(string Filename);
|
|
|
|
/**
|
|
* Closes and deletes the archive created
|
|
* clearing all data stored within
|
|
*/
|
|
function CloseStatsFile();
|
|
|
|
/** Retrieve the name of the file last in use by the gameplay event serializer, possibly empty */
|
|
event string GetFilename()
|
|
{
|
|
return StatsFileName;
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
SupportedEvents.Empty()
|
|
|
|
//Must leave this first as a fallback for failed event retrieval
|
|
SupportedEvents(0)={(EventID=-1,EventName="UNKNOWN",StatGroup=(Group=GSG_EngineStats,Level=999),EventDataType=1)}
|
|
//Real events start here
|
|
SupportedEvents.Add((EventID=GAMEEVENT_MATCH_STARTED,EventName="Match Started",StatGroup=(Group=GSG_Game,Level=1),EventDataType=`GET_GameInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_MATCH_ENDED,EventName="Match Ended",StatGroup=(Group=GSG_Game,Level=1),EventDataType=`GET_GameInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_ROUND_STARTED,EventName="Round Started",StatGroup=(Group=GSG_Game,Level=1),EventDataType=`GET_GameInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_ROUND_ENDED,EventName="Round Ended",StatGroup=(Group=GSG_Game,Level=1),EventDataType=`GET_GameInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_GAME_CLASS,EventName="Game Class",StatGroup=(Group=GSG_Game,Level=1),EventDataType=`GET_GameString))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_GAME_OPTION_URL,EventName="Game Options",StatGroup=(Group=GSG_Game,Level=1),EventDataType=`GET_GameString))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_GAME_MAPNAME,EventName="Map Name",StatGroup=(Group=GSG_Game,Level=1),EventDataType=`GET_GameString))
|
|
|
|
SupportedEvents.Add((EventID=GAMEEVENT_TEAM_CREATED,EventName="Team Created",StatGroup=(Group=GSG_Team,Level=1),EventDataType=`GET_TeamInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_TEAM_GAME_SCORE,EventName="Team Score",StatGroup=(Group=GSG_Team,Level=1),EventDataType=`GET_TeamInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_TEAM_MATCH_WON,EventName="Match Won",StatGroup=(Group=GSG_Team,Level=1),EventDataType=`GET_TeamInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_TEAM_ROUND_WON,EventName="Round Won",StatGroup=(Group=GSG_Team,Level=1),EventDataType=`GET_TeamInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_TEAM_ROUND_STALEMATE,EventName="Round Stalemate",StatGroup=(Group=GSG_Team,Level=1),EventDataType=`GET_TeamInt))
|
|
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PLAYER_LOGIN,EventName="Player Login",StatGroup=(Group=GSG_Player,Level=1),EventDataType=`GET_PlayerLogin))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PLAYER_LOGOUT,EventName="Player Logout",StatGroup=(Group=GSG_Player,Level=1),EventDataType=`GET_PlayerLogin))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PLAYER_KILL,EventName="Player Killed",StatGroup=(Group=GSG_Player,Level=1),EventDataType=`GET_PlayerKillDeath))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PLAYER_DEATH,EventName="Player Death",StatGroup=(Group=GSG_Player,Level=1),EventDataType=`GET_PlayerKillDeath))
|
|
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PLAYER_TEAMCHANGE,EventName="Player Team Change",StatGroup=(Group=GSG_Player,Level=1),EventDataType=`GET_PlayerInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PLAYER_SPAWN,EventName="Player Spawn",StatGroup=(Group=GSG_Player,Level=1),EventDataType=`GET_PlayerSpawn))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PLAYER_LOCATION_POLL,EventName="Player Locations",StatGroup=(Group=GSG_Player,Level=10),EventDataType=`GET_PlayerLocationPoll))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PLAYER_KILL_STREAK,EventName="Kill Streak",StatGroup=(Group=GSG_Player,Level=1),EventDataType=`GET_PlayerInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PLAYER_MATCH_WON,EventName="Player Match Won",StatGroup=(Group=GSG_Player,Level=1),EventDataType=`GET_PlayerInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PLAYER_ROUND_WON,EventName="Player Round Won",StatGroup=(Group=GSG_Player,Level=1),EventDataType=`GET_PlayerInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PLAYER_ROUND_STALEMATE,EventName="Player Round Stalemate",StatGroup=(Group=GSG_Player,Level=1),EventDataType=`GET_PlayerInt))
|
|
|
|
SupportedEvents.Add((EventID=GAMEEVENT_WEAPON_DAMAGE,EventName="Weapon Damage",StatGroup=(Group=GSG_Weapon,Level=10),EventDataType=`GET_DamageInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_WEAPON_DAMAGE_MELEE,EventName="Melee Damage",StatGroup=(Group=GSG_Weapon,Level=10),EventDataType=`GET_DamageInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_WEAPON_FIRED,EventName="Weapon Fired",StatGroup=(Group=GSG_Weapon,Level=10),EventDataType=`GET_WeaponInt))
|
|
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PLAYER_KILL_NORMAL,EventName="Normal Kill",StatGroup=(Group=GSG_Weapon,Level=1),EventDataType=`GET_PlayerKillDeath))
|
|
|
|
SupportedEvents.Add((EventID=GAMEEVENT_MEMORYUSAGE_POLL,EventName="Memory Usage",StatGroup=(Group=GSG_EngineStats,Level=10),EventDataType=`GET_GameInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_NETWORKUSAGEIN_POLL,EventName="Network Usage IN",StatGroup=(Group=GSG_EngineStats,Level=10),EventDataType=`GET_GameInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_NETWORKUSAGEOUT_POLL,EventName="Network Usage OUT",StatGroup=(Group=GSG_EngineStats,Level=10),EventDataType=`GET_GameInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_PING_POLL,EventName="Ping",StatGroup=(Group=GSG_EngineStats,Level=10),EventDataType=`GET_GameInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_FRAMERATE_POLL,EventName="Frame Rate",StatGroup=(Group=GSG_EngineStats,Level=10),EventDataType=`GET_GameInt))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_GAMETHREAD_POLL,EventName="Game thread time",StatGroup=(Group=GSG_EngineStats,Level=10),EventDataType=`GET_GamePosition))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_RENDERTHREAD_POLL,EventName="Render thread time",StatGroup=(Group=GSG_EngineStats,Level=10),EventDataType=`GET_GamePosition))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_GPUFRAMETIME_POLL,EventName="GPU render time",StatGroup=(Group=GSG_EngineStats,Level=10),EventDataType=`GET_GamePosition))
|
|
SupportedEvents.Add((EventID=GAMEEVENT_FRAMETIME_POLL,EventName="Total frame time",StatGroup=(Group=GSG_EngineStats,Level=10),EventDataType=`GET_GamePosition))
|
|
SupportedEvents.Add((EventID=`GAMEEVENT_AI_PATH_FAILURE,EventName="AI Path Failure",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
SupportedEvents.Add((EventID=`GAMEEVENT_AI_FIRELINK,EventName="AI Firelink",StatGroup=(Group=GSG_Game,Level=10),EventDataType=`GET_GenericParamList))
|
|
}
|