Overview
Steam Timeline is a feature that exists within the
Game Recording framework designed to make it easy for players to find, save and share gameplay moments.
https://youtu.be/YwBD0E4-EsIRequirements
Your game does not need to do anything special for the Game Recording to work, however the experience can be enhanced by adding some simple API calls to your game.
The calls are primarily used to pass information to the Steam Timeline UI
NOTE: The overlay is automatically disabled for 'Software' app types. If you need the overlay enabled, you can do so by:
- Making sure your Steam account has the Edit App Metadata permission
- Navigate from the App's landing page to > Edit Steamworks Settings > Installation tab > General Installation
- Check box for Enable Steam Overlay for Application
- Publish
Integrating Steam Timeline functionality in your app
The Steam Timeline API calls can be found here:
ISteamTimelineTimeline Icons
Steam Timelines includes a set of icons ready to use for your game. You can reference them in
AddTimelineEvent using the prefix "
steam_
". Additionally, you can generate number icons from 0-99 using the format "
steam_[number]
", e.g. "
steam_0
", "
steam_1
", etc.
You can also upload custom icons for your product on the Steamworks site.
Default set of icons:
Icon | Name | Description |
---|
| steam_marker | Marker |
| steam_achievement | Achievement |
| steam_attack | Attack |
| steam_bolt | Bolt |
| steam_bookmark | Bookmark |
| steam_bug | Bug |
| steam_cart | Cart |
| steam_caution | Caution |
| steam_chat | Chat |
| steam_checkmark | Checkmark |
| steam_chest | Chest |
| steam_circle | Circle |
| steam_combat | Combat |
| steam_completed | Completed |
| steam_crown | Crown |
| steam_death | Death |
| steam_defend | Defend |
| steam_diamond | Diamond |
| steam_edit | Edit |
| steam_effect | Effect |
| steam_explosion | Explosion |
| steam_fix | Fix |
| steam_flag | Flag |
| steam_gem | Gem |
| steam_group | Group |
| steam_heart | Heart |
| steam_info | Info |
| steam_invalid | Invalid |
| steam_minus | Minus |
| steam_pair | Pair |
| steam_person | Person |
| steam_plus | Plus |
| steam_purchase | Purchase |
| steam_question | Question |
| steam_ribbon | Ribbon |
| steam_screenshot | Screenshot |
| steam_scroll | Scroll |
| steam_square | Square |
| steam_star | Star |
| steam_starburst | Starburst |
| steam_timer | Timer |
| steam_transfer | Transfer |
| steam_triangle | Triangle |
| steam_trophy | Trophy |
| steam_view | View |
| steam_x | X |
Example Code
Below is a code sample for integrating Steam Timeline with Left 4 Dead. This code was used in the Steamworks video introduction linked above.
//=========== Copyright (c) Valve Corporation, All rights reserved. ===========
#include "cbase.h"
#include "igamesystem.h"
#include "gameeventlistener.h"
#include "steam/steam_api.h"
#include "steam/isteamtimeline.h"
#include "clientterrorplayer.h"
#include "fmtstr.h"
//-----------------------------------------------------------------------------
class L4DSteamVideo : public CAutoGameSystem, public CGameEventListener
{
public:
// CAutoGameSystem
virtual bool Init();
virtual void Shutdown();
// CGameEventListener
virtual void FireGameEvent( IGameEvent* pEvent );
private:
bool m_bEnabled;
};
//-----------------------------------------------------------------------------
bool L4DSteamVideo::Init()
{
ISteamTimeline *pSteamTimeline = SteamTimeline();
if ( pSteamTimeline )
{
pSteamTimeline->SetTimelineGameMode( k_ETimelineGameMode_Staging );
// Create the event listeners
ListenForGameEvent( "survival_round_start" );
ListenForGameEvent( "round_end" );
ListenForGameEvent( "heal_success" );
ListenForGameEvent( "player_incapacitated_start" );
}
// if pSteamVideo is null then the client's steam API is not recent enough
// in this case, we still init the system it just doesn't do anything
m_bEnabled = pSteamTimeline != nullptr;
return true;
}
//-----------------------------------------------------------------------------
void L4DSteamVideo::Shutdown()
{
StopListeningForAllEvents();
m_bEnabled = false;
}
//-----------------------------------------------------------------------------
void L4DSteamVideo::FireGameEvent( IGameEvent *pEvent )
{
if ( !m_bEnabled )
return;
int userid = pEvent->GetInt( "userid", 0 );
if ( userid != 0 && userid != C_BasePlayer::GetLocalPlayer()->GetUserID() )
return;
const char* eventname = pEvent->GetName();
if ( V_strcmp( "survival_round_start", eventname ) == 0 )
{
SteamTimeline()->SetTimelineGameMode( k_ETimelineGameMode_Playing );
}
else if ( V_strcmp( "round_end", eventname ) == 0 )
{
SteamTimeline()->SetTimelineGameMode( k_ETimelineGameMode_Staging );
}
else if ( V_strcmp( "heal_success", eventname ) == 0 )
{
SteamTimeline()->AddTimelineEvent(
"medkit32",
"Healed",
CFmtStr( "Restored %d Health", pEvent->GetInt( "health_restored" ) ),
0,
-5.f,
5.f,
k_ETimelineEventClipPriority_Standard );
}
else if ( V_strcmp( "player_incapacitated_start", eventname ) == 0 )
{
C_TerrorPlayer* pAttacker = (C_TerrorPlayer*)UTIL_PlayerByUserId( pEvent->GetInt( "userid" ) );
const char* pszAttacker = pAttacker ? pAttacker->GetCharacterDisplayName() : "the world";
SteamTimeline()->AddTimelineEvent(
"foo",
"Incapacitated",
CFmtStr( "INCAPACITATED by %s", pszAttacker ),
0,
0.f,
0.f,
k_ETimelineEventClipPriority_Featured );
}
}
static L4DSteamVideo s_steamVideo;