Skip to main content

On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Achievements for Ren'Py

In-depth ingame achievement support for Ren'Py that plugs into the Steam backend. · By Feniks

Need Support? Post here! Sticky

A topic by Feniks created Sep 14, 2023 Views: 805 Replies: 54
Viewing posts 1 to 20
Developer

If you're having trouble or run into any bugs with the code, post a comment here! I will try to get back to you within a few days.

Hey, bro. How do you set up a steam connection? 

Developer(+2)

Hello! In Steamworks, you can go to Technical Tools > Edit Steamworks Settings > Stats & Achievements > Achievements and add a new achievement. The first column, called API Name, is the ID for the achievement. This should be the same ID as you set when you make your Achievement objects in-game using the system. You can then add the locked/unlocked images in Steamworks as per usual. The only important thing is that the achievement has the same ID as the in-game one! Aside from that, the backend of registering and granting the achievement for Steam is all taken care of via the system. Hope that helps!

Thanks for the quick response! I added an achievement with the same ID as in your Example 1 to Steamworks. I also added a steam_appid.txt file with the game id near the .exe file. The in-game achievement works (using $ sample_achievement.grant() ), but it is not granted at Steam. I run the game through Steam and the overlay (Shift+tab) works.

 

Developer(+1)

Did you install the Steam support from the Ren'Py launcher? That's required for any Steam integration. Remember also that you'll have to go through Steam to clear any achievements if you'd like to re-see the popup, as the clear method only clears it on Ren'Py's end. You can install the Steam support via the launcher Preferences -> Install Libraries -> Install Steam Support. The overlay isn't related to whether Steam support is installed or not, just if you're playing it through Steam. Let me know if that fixes it for you!

It's all working now! Thank you!

Hey, this is probably a stupid question, but in what script do you need to write the first code?

Developer

If I understood your question - you can declare the achievements in whichever rpy file in your project you like. The included achievements.rpy file has several example achievements, so it probably makes sense to declare your own achievements there. Be sure to read the included README for more instructions on what details you can provide to each achievement as well! You might consider reading https://feniksdev.com/organizing-a-renpy-project/ if you're new to Ren'Py project organization in general.

Deleted 361 days ago
Developer

Sure thing! You can remove the achievement gallery screen or just not use it anywhere. The popups will work just fine. 

Same thing goes in reverse, too - you can use the config options at the top of the file to remove popups and just use the gallery if you like.  

Deleted 361 days ago
Developer

So if I understood, you just want a notification screen? You certainly don't need to go through the achievement system for that; just make yourself a screen and show it with your desired notification. You can copy the general format of the achievement popup screen and methods for that, but I'm afraid that would be out of the scope of things I can help with for this system.

(1 edit)

Hi, I was having difficulties accessing the achievement screen on my main menu so I looked around and found that deleting the second datetime (line 131 and 148) in the achievements backend solved it. I do not know if it's a bug on my end or my game but thought I'd let you know! Fanatastic asset, very excited to customise it!

Developer

The current achievement code is correct! But sometimes other people import the datetime module separately, which could cause this conflict. It usually looks like from datetime import datetime instead of just import datetime. I would check your project for other places where the datetime module is used to see what's causing that. If you've imported datetime differently, then your fix will work.

Glad you like the system! I hope you find it useful :)

Hello! Thank you very much for the great feature!

As I was testing out the achievement pop-ups I saw that the name of the achievements and descriptions were not showing up, then I realized I set gui.text_color in gui.rpy to black, is there a way to make the achievement text not rely on the same gui type as that of dialogue? Or is there a way to change the color of the popup box to white?

I sincerely apologize for any inconvenience :c

Developer(+1)

Sure! You can change the text colour of any of the screens however you like by adjusting the styles; all of the existing styling is meant to be changed to suit your project. I suggest you hover over the text in question and hit shift+i to find which styles are affecting it, or you can find the lines in achievements.rpy and just add color "#fff" or similar to whichever line of text you need. For example, you can change the line text a.description size 25 to text a.description size 25 color "#fff" to make the text white. Hope that helps!

I figured it out! Thank you very much!

Because of the code in the first image for a minigame, the code in the second image stops working 

https://imgur.com/a/udq9pEE

Developer

Yes, time is a reserved name that refers to the Python library time. Call the variable something else and it should work.

the problem is that the minigame uses that time variable to countdown to the end of each phase. im not entirely sure what to change in order to separate the countdown time from the default time https://imgur.com/ZxmZGCv

Developer

Find and replace the variable time with some other name - it can be whatever you like. It's just a variable name, and it'll be better to change it to avoid conflicts with Python libraries.

did so, but this still came up https://imgur.com/Q3G6a2k

nvm there's something i forgot to rewrite! it all works

(1 edit)

i'm sorry, but where do i need to put this?..

textbutton _("Achievements") action ShowMenu("achievement_gallery")
Developer

It's not a requirement or anything! That's just an example of a button you can make so players can see your achievement gallery. In a standard Ren'Py project, that would go on screen navigation in the same pattern as all the other buttons there. But you can create whatever kind of button or method to access the achievement gallery that you want.

Oh, okay... I would like a video tutorial, since i'm not good at English at all... Do you have it, or you know if someone did it already?

Developer

You can look up regular screen language in Ren'Py for more information on how UI works in Ren'Py. I have some tutorials on my website also https://feniksdev.com/navigation/

(1 edit)

Hello, my friend. Just one stupid question.

In achievement_backend.rpy, line 457:

ACHIEVEMENT_SOUND = "audio/interface/ach.ogg"

I got the right path and there's no problem with this sound, but in-game granting going without any sound. I really don't know, why, mb I need to change smth, not the only one line?

Sound channel is also correct

btw sry my english is bad and im drunk a little
Developer

You're meant to change the sound with your own define statement, not in the backend file! For example,

define myconfig.ACHIEVEMENT_SOUND = "audio/interface/ach.ogg"

The achievements.rpy file has examples of that. If you're only changing it in the backend, then the redeclaration in achievements.rpy will be overwriting it with None. The backend file has an early initialization order so it can be set up early before it's used and modified with a regular define statement.

So, in short, change it in achievements.rpy not in the backend file :) Hope that helps!

My gosh it helps I feel so stupid rn. Thanks, brother

Deleted 199 days ago
Deleted 199 days ago

Hey! Just a small question, how do I stop the achievements being opened by clicking on them in the achievements gallery? 

Developer

Hello! That option is only available to developers during development for testing, so if you make a build then players can't toggle achievements. To remove it altogether you can look for the action under a `if config.developer:` block and get rid of it.

Thanks! 

I can't find the Achievements Gallery button in the main menu, I don't know what to do. I tried deleting the datetime in the backend to try and fix it (because I was reading through the other comments here) but that didn't work either. 

Developer

Hello! You have to make a button to lead to the achievement gallery yourself - it's not built into your project or the tool because I don't know how your main menu screen is set up. That's what this bit of code in the instructions is for:

textbutton _("Achievements") action ShowMenu("achievement_gallery")  

You need to add that or something similar to your project to access the achievement gallery. Don't delete datetime either - that was a very specific case where another bit of code had imported datetime already in a different way. I suggest not changing anything in the backend unless you understand what you're doing.

Ok! Thank you

I'm having trouble with coding the Platinum Achievement. I've tried to code different things onto the script file but nothing works and I'm not very experienced in coding. (apart from coding visual novel stuff). What do I do?

Developer

Can you share any code you've tried?

So my game has 15 achievements (14 dis-including Platinum Achievement) sorry if this is a lot

This is what I've coded every time an achievement is unlocked

These are my "if"s I've set up

(The 8th achievement is the bar one, I've already done coding for that one)

And this is the Platinum Achievement code on the achievement script


Developer

So what I'm understanding based on the code you've posted is that you're very new to coding. That's all right, but you will need to have a basic grasp of how variables (getting and setting them) work in order to understand how to use the achievement code. I really recommend you begin with https://feniksdev.com/a-quick-primer-on-variables-in-renpy/ and go through the rest of the tutorials in that series to see how to declare variables and update them. Then I recommend you read over the examples included with the achievements - you should follow the example very closely and just tweak things until they work how you want. A better understanding of variables will help you see what the system is doing and how you can follow the examples to do what you want. Good luck!

This is very useful! Thank you very much

Hi, I am pretty new to Ren'py and coding but I am slowly figuring things out. Here's my issue, I want to make an achivement for skipping the dialogue but I cannot figure out how to make it work. I'd appreciate any help/tips ^^'

Developer(+1)

If you want to check if the player is skipping a specific section of dialogue, you can check for if renpy.is_skipping(): (https://www.renpy.org/doc/html/other.html#renpy.is_skipping) at the start of that dialogue, and if it's true, grant your achievement. Otherwise, you can also add an achievement action to the Skip button on the quick menu (e.g. action [skip_achievement.Grant(), Skip()] on the quick menu button). The latter suggestion will *not* cover the case if the player uses a keyboard key like CTRL or Tab to start skipping; the best way to handle that more general case would be through a callback https://www.renpy.org/doc/html/config.html#var-config.interact_callbacks. If you're new to coding, I would wait to implement the last option until you're a bit more comfortable with Python! I hope that helps :)

Thank you! For now I'll use the second option but once I figure more stuff out I'll check out the callback stuff ^^

Hello! I'm sorry if it sounds like a silly question, but is it possible to change the frame image depending on the achievement? 

Developer

Sure! The achievement itself is passed into the popup screen (by default, as the argument called "a"), so you can check for that and use a different background e.g. 

frame:
    style_prefix 'achieve_popup'
    if a is all_achievements:
        background Frame("my_platinum_frame.png", 5, 5)

ohhhh, thank you so much!

Hello! I'm having a strange issue with granting achievements during the game.

Here's one achievement as an example:

define ACHex = Achievement(     
    name = _("EXTERMINATOR"),
    id = "Exterminator",
    description = _("Get the good ending to the RATS scenario after choosing to kill them."),
    unlocked_image = "gui/ach/Exterminatora.png",
    locked_image = "locked_achievement",
    hidden = False,
    hide_description=True,
    )

My issue lies with the [achievementName].grant() function. It's very strange, because while some instances of the function work, others (and the ones I need most) don't seem to. For example, when I grant the achievement as a screen function like this (for testing purposes only):

textbutton "GET" action Function(ACHex.grant)

It works! The art and description show up, which is what I want. But the problem is that I want to grant the achievements in the game itself as you play. But, when I do so by putting this in the actual scene of the game:

$ ACHex.grant()

Nothing happens. I've toggled all of my achievements to hide and unhide them while testing, so I can confirm that they all have the proper art, title, and description once their achievements are granted. I've also made sure to restart the game, and double check that Steams support is up to date (My game is already on Steam so this was just to be sure). 

The main thing I want to know is how I can get the achievements to be granted in real time as you play like in the example above (only functional lol). Any help would be awesome, this is a neat tool and I'd like to get it working! ✌✨

Developer

So, when you say nothing happens - does it not grant the achievement at all, or are you just not seeing the popup? You can watch the status of the achievement by bringing up the console with shift+o and typing watch ACHex.has() for example. If you already have the achievement, it won't re-grant it. If proceeding past that line in your script does not change the achievement to being unlocked, then that's a different issue from it changing it and you not seeing the popup screen. If you're testing on Steam, you may need to clear the achievements from their backend as well. See the bottom of this article: https://partner.steamgames.com/doc/features/achievements/ach_guide

Thanks! As it turns out, it was actually an issue with how I was calling the achievements menu (I had a feature that was able to delete all achievements after clicking another confirmation box) that was clearing the achievements as the menu was called for some reason. The good news is that I found this out by using the shift+o console method which I actually didn't know about before, so thanks for the help! I used this to test all of my achievements and if they were being granted correctly, and it's been a big help! ✌✨

Hello   i have a question, how do you  

how to invoke the method to appear in the story?

the achievements are shown in the option menu, I implemented the bad ending test code, but when I invoke it, it does nothing and I don't know what I am missing.


Developer(+1)

Hi there! In-script, you can grant achievements with

$ achievement_you_made.grant()

Remember it'll only show a popup if you've got the configuration options set to allow them + you haven't gotten that achievement before. You can use the Delete Persistent option in the Ren'Py launcher to fully reset all achievements.

How do I delete an achievement and remove it from my  VN?

Developer

Just delete your definition of it! You can hit Delete Persistent on the Ren'Py launcher to purge any achievement history as well during development.

Hello! Can you please explain this part  in a bit more detail. I am trying to make an achievement that is granted once player tries all 4 options of something.


# $ persistent.seen_endings.add("end1")

# $ ending_achievement.progress(len(persistent.seen_endings))

## This will prevent the achievement from being added to multiple times if the

## player sees the same ending multiple times.


I tried to do my own version and keep getting the error 

```

AttributeError: 'int' object has no attribute 'add'

or 

AttributeError: 'NoneType' object has no attribute 'add'


Do we need to define the class somewhere? I'm also severely sleep deprived so may be making simple mistake. Overall love this code a lot though!

Developer

You need to create a persistent set, e.g.

default persistent.seen_endings = set()

and then you will add to that set when you reach a relevant part in the game (that's this part:)

$ persistent.seen_endings.add("end1")

and in order to record that progress for an achievement, you can set the progress to the length of the list e.g.

$ ending_achievement.progress(len(persistent.seen_endings))

Sets are used because they can't have duplicates, so the length of the list will be the number of unique endings the player has seen, and it won't matter if they go through the same ending multiple times/it won't count them more than once towards the achievement.

Thank you for the speedy response! I really appreciate the breakdown.

I discovered that the issue was actually with the name I was giving my variable...I'm still not sure why it was happening but I suspect it was too similar to the name of something else in my project. Once I followed your code with a different name it worked!

Thanks again for your contributions as I'm really excited to have this feature and I will be crediting you in the final release!