Wintermute Engine Forum

Wintermute Engine => Scripts, plugins, utilities, goodies => Topic started by: Mnemonic on October 19, 2013, 12:28:02 PM

Title: Steam plugin
Post by: Mnemonic on October 19, 2013, 12:28:02 PM
Steam plugin for WME

If you are lucky enough to have your game published on Steam, this plugin will allow you to leverage some of the Steam features, namely achievements and game stats.

Getting started

Download the plugin here:
Source code is also available:
Note: If your game is not on Steam yet and you want to test the Steam integration anyway, you can use a test game called Spacewar. Its ID is 480 and the defined achievements are listed on this site (

Accessing Steam functions from WME scripts

First you need to create a SteamAPI object and store it in a global variable. Typically you will do this when the game starts, i.e. somewhere in the beginning of game.script:
Code: WME Script
  1. global g_Steam = new SteamAPI();

To check whether the initialization was successful, check the SteamAvailable property.
Code: WME Script
  1. if (g_Steam.SteamAvailable) ...
If the SteamAvailable property is false, something is wrong. The typical reasons are that either the Steam client is not running or you've provided an invalid game ID (see above).

Working with achievements

To unlock an achievement, call the SetAchievement method. It accepts a string ID of the achievement (the ID you assigned to your achievement when defining it) and it returns true/false, depending on the success. It is safe to call this method multiple times, if the achievement is already unlocked, subsequent unlock attempts will be ignored.
Code: WME Script
  1. g_Steam.SetAchievement("ACH_WIN_ONE_GAME");

This is pretty much everything you will typically need. The plugin provides more functions, though:

To check whether an achievement has already been unlocked by the player, use the IsAchieved method:
Code: WME Script
  1. Game.Msg(g_Steam.IsAchieved("ACH_WIN_ONE_GAME"));

To reset an achievement back to unlocked state, use the ClearAchievement method. You will probably only need this for testing purposes, not in the actual game:
Code: WME Script
  1. g_Steam.ClearAchievement("ACH_WIN_ONE_GAME");

To query all achievements defined for the game, use the NumAchievements property and GetAchievementId method. The following example will print out all achievement IDs:
Code: WME Script
  1. for (var i = 0; i < g_Steam.NumAchievements; i = i + 1)
  2. {
  3.   Game.Msg(g_Steam.GetAchievementId(i));
  4. }

Working with stats

Stats are some persistent values related to your game, stored by Steam across multiple gaming sessions. You can use them for tracking information such as the number of times the player started your game, the number of miles the player traveled in total etc. Steam can store either integer numbers or float (decimal) numbers. Just like with achievements, you define stats using the Steam partner site.

To store a stat value, use the SetStat method. It accepts either integer or float numbers. If unsure about the value of your variable, convert it explicitly using the ToFloat() or ToInt() WME functions.
Code: WME Script
  1. g_Steam.SetStat("NumGames", ToInt(10));
  2. g_Steam.SetStat("FeetTraveled", ToFloat(100.5));

To retrieve stored stats, use either the GetStatInt or GetStatFloat method:
Code: WME Script
  1. Game.Msg(g_Steam.GetStatInt("NumGames"));
  2. Game.Msg(g_Steam.GetStatFloat("FeetTraveled"));

Other functions

For testing purposes you may need to clear all stats and achievements. To do that, use the ResetAllStats method. It accepts a logical argument, specifying whether you want to reset just stats or also all achievements:
Code: WME Script
  1. // reset just stats
  2. g_Steam.ResetAllStats(false);
  4. // reset both stats and achievements
  5. g_Steam.ResetAllStats(true);

To reload the stats/achievements states from the server, use the RequestStats. Normally you shouldn't need to call this method. The plugin will call it automatically upon initialization.
Code: WME Script
  1. g_Steam.RequestStats();

To check whether the stat/achievement info is available, use the StatsAvailable property. Stat info is downloaded from Steam asynchronously, meaning that there may be a slight delay between plugin initialization and stats becoming available. Until this property is true, all other calls to methods dealing with stats and achievements are ignored.
Code: WME Script
  1. if (g_Steam.StatsAvailable) ...

You can query the game ID using the AppId property:
Code: WME Script
  1. Game.Msg("Current game ID is: " + g_Steam.AppId);
Title: Re: Steam plugin
Post by: Mnemonic on October 19, 2013, 12:43:15 PM
What if my game is already on Steam and I want to add achievements?

Ok, it's a little tricky, because even if you add the plugin initialization to game.script, when the player loads an old saved game with old game.script, the plugin won't get initialized.

You will need to find a way to "inject" the plugin initialization to an existing game. To do that, I recommend finding some script that isn't running all the time, but it's likely to get executed eventually. For example, is there a scene in your game where the player keeps returning to? Patch the script of this scene and add some code to initialize the plugin:

Code: WME Script
  1. global g_Steam;
  3. // if the variable is empty, it means the player is running an old game.script
  4. // so we'll just initialize the plugin now
  5. if (g_Steam == null)
  6. {
  7.   g_Steam = new SteamAPI();
  9.   // you may also want to unlock some achievements the player may have missed so far
  10.   if (someGameVariable) g_Steam.SetAchievement("SomeAchievement");
  11. }

However, since the g_Steam variable may or may not be initialized (depending on whether the player visited the "injection" scene yet), you need to be careful when calling any method:

Code: WME Script
  1. // always make sure the plugin is initalized before calling SetAchievement
  2. if (g_Steam != null)
  3. {
  4.   g_Steam.SetAchievement("SomeAchievement");
  5. }
Title: Re: Steam plugin
Post by: Azrael on October 19, 2013, 02:17:35 PM
Thanks a lot  :)
Title: Re: Steam plugin
Post by: hubertMichael on October 20, 2013, 10:27:45 PM
WOW :D You are great :D Thank you :D
Title: Re: Steam plugin
Post by: metamorphium on October 21, 2013, 08:26:34 AM
Thank you! This couldn't have come in a better time. :)
Title: Re: Steam plugin
Post by: Azrael on October 31, 2013, 10:00:51 AM
I'm having some problems with the plugin, it seem to work perfectly for a while (completely random) and then simply stop working.

I've checked the scripts and seem to be ok. I've done many test and everything seem to be working but achievements will not me setted on steam. I inserted also F5 as reset button for achievements and stats and at the beginning it works, but when achievement stop to be set also this don't work anymore.

For example:
Code: WME Script
  1. #include "scripts\"
  2. global g_Steam;
  4. ////////////////////////////////////////////////////////////////////////////////
  5. on "observe"
  6.         {
  7.         Game.Interactive = false;
  9.         actor.TurnTo(this);
  10.         actor.TalkUp("/sysengXXXX/Text");
  12.         //Steam Achievement
  13.         if (g_Steam != null)
  14.                 {
  15.                 g_Steam.SetAchievement("ACH_MALTESE_FALCON");
  16.                 Game.LOG("Achievement Set.");
  17.                 }
  18.         else Game.LOG("Steam not working!");
  20.         Game.Msg("New version loaded"); //To be sure that the news script was loaded
  22.         if (g_Steam.SteamAvailable) Game.LOG("Steamworks available!");
  23.         else Game.LOG("Steamworks not available");
  25.         Game.Interactive = true;
  26.         }
  28. on "take"
  29.         {
  30.         Game.Interactive = false;
  32.         actor.TurnTo(this);
  33.         actor.TalkUp("/sysengXXXX/Text");
  35.         Game.Interactive = true;
  36.         }

This sometimes works, sometimes not. I've a save now right before and it doesn't work. But with the log enable it says:
Code: WME Script
  1. 09:44: Achievement Set.
  2. 09:44: Steamworks available!
None of the errors above are show.

Ah the Achievement is obviously not already set.

The Game.Msg("New version loaded"); is displayed so i know that the script is correctly loaded (i change it each time i upload something new).

global g_Steam = new SteamAPI(); is enabled at game.script, i tried also to put it on this script but with the same result.

As i said is completely random, the first time i was able to play more than 1 hour before it stop to work, the second time half an hour.

Title: Re: Steam plugin
Post by: Mnemonic on October 31, 2013, 10:40:27 AM
Try adding the return value of SetAchievement() to the message. It should return true or false, based on success of the call.
Title: Re: Steam plugin
Post by: Azrael on October 31, 2013, 11:20:19 AM
Uhm, it say "no", so i think "false". There is some way to know why?
Title: Re: Steam plugin
Post by: Mnemonic on October 31, 2013, 12:09:15 PM
Try checking the Steam.StatsAvailable property. It specifies whether steam downloaded the stats and achievements info from server. The download is requested when the Steam object is created and it may take a moment until the info is ready. Until then all the other functions will fail.
Title: Re: Steam plugin
Post by: Azrael on October 31, 2013, 01:41:21 PM
Ok, StatsAvailable return "false".
But the problems that the first time it happen i was playing for a while, without closing the game i mean.
And now i've tried to wait some minutes but nothing, there is a way to force download or something else?
Title: Re: Steam plugin
Post by: Mnemonic on October 31, 2013, 01:45:41 PM
That's what the RequestStats() method does (see above). But it shouldn't be necessary, it's called automatically when the Steam object is created.
Title: Re: Steam plugin
Post by: Azrael on October 31, 2013, 02:41:21 PM
Ok i tried with RequestStats but with the same result, any other advice? Otherwise he sadly had to leave the game without achievements  :'(
Title: Re: Steam plugin
Post by: Mnemonic on October 31, 2013, 03:42:23 PM
No idea then. Beyond that point it's under steam's control, as far as I can tell.
Title: Re: Steam plugin
Post by: Azrael on October 31, 2013, 07:05:34 PM
Ok, thanks a lot anyway for the help :)
Title: Re: Steam plugin
Post by: Gurkan on March 24, 2014, 04:27:30 PM
Hi everyone!

We've recently been greenlit and I'm trying to figure out how to create our achievements. I've managed to connect Steam with the game as g_Steam.SteamAvailable is returning true. What doesn't seem to work is setting the actual achievement, g_Steam.SetAchievement(). I've been logging it's status with Game.LOG(g_Steam.IsAchieved()) but it always returns false no matter what. I've followed these steps and created steam_appid.txt, the .dll files etc and I'm kinda out of options. I'm using 1.9.001, if that has any significance. Here is my setup:

In game.script:

global g_Steam = new SteamAPI();

In object:

global g_Steam;

on "LookAt"
   if(g_Steam != null)

on "Talk"
     if(g_Steam != null)
Title: Re: Steam plugin
Post by: Mnemonic on March 24, 2014, 04:38:08 PM
Did you define the achievements on your steam project page? Those achievements names ("achievement_2") need to be present in steam's database.
Title: Re: Steam plugin
Post by: Gurkan on March 25, 2014, 08:57:18 AM
Hi Mnemonic!

Thanks for the quick answer. I've added that achievement on our page on Steamworks, yes.

EDIT: Forgot the last step of "Really publish to Steam". Been trying builds through steam without publishing the achievements.
Title: Re: Steam plugin
Post by: piere on December 14, 2014, 09:28:03 AM
Hi guys,

Maybe you can help. I am trying to work with the Steam plugin, but I cannot compile my game because I get an error message saying "Object 'SteamAPI' is referenced but no constructor is defined". Anyone know whats going on? Thanks
Title: Re: Steam plugin
Post by: piere on December 18, 2014, 04:24:00 AM
Any suggestions anyone? I kinda need this fast.
Title: Re: Steam plugin
Post by: Dan Peach on June 02, 2015, 02:15:58 PM
Noob questions...

1) Do these .dll files go into the WME Devkit folder in program files?

2) Do I need to select wme_steam.dll in the "plugins" section of "project settings"?

3) Is that all I need to do? I notice that other games have steam_api.dll in their steam folders. Do I need to include that with my build?

Thanks. :)
Title: Re: Steam plugin
Post by: Mnemonic on June 04, 2015, 05:49:08 PM
1) Yes.
2) Yes. If you do that, ProjectMan will include the plugin with the final build. Otherwise you'd need to copy the file yourself.
3) Yes, you need to install steam_api.dll with your game.
Title: Re: Steam plugin
Post by: Dan Peach on June 05, 2015, 01:14:27 AM
Thanks man. :)
Title: Re: Steam plugin
Post by: Dan Peach on June 07, 2015, 01:25:53 AM
I seem to have found a problem with the plugin.

I've noticed that if you load a game, it stops working, and won't set any more achievements. I'm not loading an old save. I've tested it by starting a new game, doing the first achievement (which works fine), then saving the game, then loading the game, then doing the second achievement (does not get set). If I do not save and then load game, both achievements are set no problem.

I can't see how I am doing anything wrong. I'm just saving and then loading, which is what anyone playing the game would be doing.
Title: Re: Steam plugin
Post by: Dan Peach on June 07, 2015, 01:46:37 AM
Seems to work ok if you quit the game, restart it, and THEN load the game and continue playing. But if you save and then load within the game, and carry on playing, the achievements stop being set.

Ok, this actually doesn't seem to work. Nothing Steam related will work after loading a game. Not even my Achievement reset button. It's like the connection to Steam has been severed. I've tried adding "RequestStats" to AfterLoad to reconnect. Nothing. It just stops working after you load a game.

This is my reset code:

Code: WME Script
  1. else if(Keyboard.KeyCode==VK_HOME)
  2.   {
  3.    if(SteamAchieve.StatsAvailable)
  4.     {
  5.          SteamAchieve.ResetAllStats(true);
  6.          Game.Msg("Achievements Reset");
  7.         }
  8.   }

The reset code checks the connection, and if it's there, then it resets the achievements, and displays the message. After loading a game, I do not get the game.msg displaying, so that means the stats are NOT available, which means the connection is not there anymore. But why should loading a game result in this?  :-\

Ok, so after more tests, I've discovered that if I put "global SteamAchieve = new SteamAPI();" in game.script, then nothing Steam related will work after loading a game, no matter if you exit the game and reboot or not.

But, if I define "SteamAchieve" in a scene_init.script (only on first visit), then Steam WILL work if you exit the game, reboot, and then load. But, it still won't work if you save and then load without exiting inbetween.

Also, I've discovered that if you define the Steam object more than once, then everything stops working. I'm no expert, but it kind of feels like the reason this issue is occuring is because for some reason, after you load a game, there is more than once instance of the Steam object. Or it's been defined again after loading. That would explain why, if you don't define it in game.script, then you exit, restart the game, THEN load, everything works normally. If you define it in game.script, it gets defined everytime you start the game, so if you load at that point, then the issue occurs. Hope I'm making some sense.  ;D

I think this might have been the problem Azrael was experiencing. If you didn't notice it was occuring after loading, then it would seem like a random problem with no explanation.

Title: Re: Steam plugin
Post by: Dan Peach on June 07, 2015, 05:44:41 PM
Ok, I think I've solved this problem.

I had to put "SteamAchieve = null" in the load.script just before "Game.LoadGame(SelectedSlot)".

This seems to reset the Steam object before loading the previous instance of it in the save game. Everything seems to work now. Phew!  ;D
Title: Re: Steam plugin
Post by: HanaIndiana on July 26, 2015, 01:33:49 AM
Thanks Dan!!
Title: Re: Steam plugin
Post by: hubertMichael on January 23, 2016, 10:08:27 PM

I have a problem with this plugin. I've copied wme_steam.dll and steam_api.dll to WME DevKit folder. At the begining of game.script I added line
Code: [Select]
global g_Steam = new SteamAPI(); in base.script I have
Code: [Select]
global a_ship_escape; and in my scene.init script where I want to unlock achievment I have:
Code: [Select]
if(a_ship_escape == null)
a_ship_escape = true;

Problem is that I can't compile my game because I got error:
Method is called for 'g_Steam' which is not defined
Error applying filter to file [my scene.ini path here]

In project settings/plugins I turned on wme_steam.dll

I really need a help


I have forgot to initialize "global g_Steam;" at my scene.init :D