-
Notifications
You must be signed in to change notification settings - Fork 10
Achievement Templates
Here you'll see examples of some typical achievements. You can use them as inspiration to create your own achievement. But keep in mind the following:
EVERY GAME IS DIFFERENT! The memory has a different behavior from game to game.
So do NOT take these templates as a rule. They are here just for educational purposes.
In these examples we use the following convention 0xLEVEL is the memory address with the level ID; 0xLIFE is the address used for the character life; 0xTIME for time, 0xITEM for getting an item, etc...
- Collecting an Item N Times
- Finish Level N
- Finish Level N Before Time Reaches T
- Finish Level N In Under Time T When There Is No In-Game Timer
- Finish Level N without Dying (or getting hit, using a weapon, etc.)
- Finish Level N with Item
- Collect an Item in a Specific Level
- Collected 100 Percent of Something
- Circumvent the Problem of a Counter Incrementing Twice in the Same Frame
- Check for a Specific Value Changing to Another Specific Value Ten Times
- Conditional Resets
There are some situations where you want to award an achievement for collecting an item (like a coin or a ring) N times. You'll need to find in the memory the address responsible to count how much of the item you have. Once you have the address, this logic usually does the job:
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
1 | Mem | 0xCOUNT | > | Delta | 0xCOUNT | (N) |
But you most likely will want to be more specific, for example "get item N times without dying". Then you should use another condition with a ResetIf
, like this:
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
1 | Mem | 0xCOUNT | > | Delta | 0xCOUNT | (N) | |
2 | ResetIf | Mem | 0xLIVES | < | Delta | 0xLIVES |
The ResetIf
condition could be "while in level X", "without using a bomb", etc.
In this example we want to award when the player finish the level N
and goes to level N+1
.
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
1 | Delta | 0xLEVEL | = | Value | N | (0) | |
2 | Mem | 0xLEVEL | = | Value | N+1 | (0) |
Requirements
- 1: On Level
N
in previous frame. - 2: Now at level
N+1
on current frame.
This logic is true only on the exact frame the level advances from N
to N+1
, which makes it safe from being triggered by a level select cheat or loading a password to Level N+1
. For robust achievement logic, you'll want other conditions too, such as checking the player is in-game or there is no demo active.
In this example we consider a game where the time decreases (e.g.: Super Mario Bros). Adapt it accordingly the time on your game has a different behavior.
We want to award if the player finishes the level N
while time is greater than T
.
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
1 | Delta | 0xLEVEL | = | Value | N | ||
2 | Trigger | Mem | 0xLEVEL | = | Value | N+1 | |
3 | Mem | 0xTIME | > | Value | T |
Requirements
- 1-2: Functionally the same as conditions 1-2 from the Finish Level N template, but with a Trigger on the final line so that the challenge icon shows to the player while the challenge is active.
- 3: Ensure the
TIME
address has a value greater than the failure time. When the time is at or below this value, a non-Trigger-flagged condition is now false and the challenge icon will disappear, indicating a failure to the user.
Notes
- Keep in mind that besides knowing how the time behaves in game you also need to research how it behaves in memory.
In this example we consider a game where there is no in-game timer to use for a speed run.
We want to award if the player finishes the level N
before a a time T
in the level, calculated as number of frames, has passed.
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
1 | Delta | 0xLEVEL | = | Value | N | ||
2 | Trigger | Mem | 0xLEVEL | = | Value | N+1 | |
3 | Pause If | Mem | 0xLEVEL | = | Value | N | (T*FRAMERATE) |
Requirements
- 1-2: Functionally the same as conditions 1-2 from the Finish Level N template, but with a Trigger on the final line so that the challenge icon shows to the player while the challenge is active.
- 3: The hit target
T*FRAMERATE
should be set equal to the number of frames that equal the time at which the challenge fails. For a system that runs at 60 frames per second,T*FRAMERATE = TimeInSeconds x 60
. When the player is in the level for that many frames, the Pause If will become true and locked achievement processing in the core group until a Reset occurs (see Notes, below).
Notes
- A player should be able to re-try this challenge. You will need a Reset to clear the pause lock at an appropriate time, such as dying. You can use a
Reset If
in an alt group (an activePause If
will prevent a reset in the core group from working), or you can attach a Reset Next If right before the Pause If. - You may want some other conditions on the
Pause If
. You can link more usingAnd Next
flag. If a game has a flag that indicates the player has control of the character, this may be a good choice. Experiment!
(or getting hit, using a weapon, etc.)
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
1 | And Next | Mem | 0xLEVEL | = | Value | N | |
2 | Mem | 0xLVL_STATE | = | Value | LVL_N_INTRO | (1) | |
3 | Delta | 0xLEVEL | = | Value | N | ||
4 | Trigger | Mem | 0xLEVEL | = | Value | N+1 | |
5 | Reset If | Mem | 0xLEVEL | = | Value | TITLE | |
6 | And Next | Mem | 0xLEVEL | = | Value | N | |
7 | Reset If | Mem | 0xLIVES | < | Delta | 0xLIVES |
Requirements
- 1-2 Supposes there is a
LEVEL_STATE
address that has values like "In Level Intro Screen," "Playing Level," etc and sets a checkpoint hit when you are in the correct level's intro. This is a stand in for some "checkpoint" where you want the challenge to start. You will need to determine the proper conditions and timing and set up your own appropriate start checkpoint. - 3-4: Functionally the same as conditions 1-2 from the Finish Level N template, but with a Trigger on the final line so that the challenge icon shows to the player while the challenge is active.
- 5: Resets the start checkpoint if the player has a game over or otherwise is able to quit back to the title screen early. Prevents the checkpoint hit from sticking around when it shouldn't.
- 6-7: A Reset for when the
LEVEL
address has the value of levelN
and theLIVES
address is less than it was on the previous frame, indicating the player lost a life. Clears the starting checkpoint hit and so fails the challenge.
Notes
- The requirements in 6-7 can also be modified to reset hit count if a weapon was used, damage taken, or anything else that you want the player to NOT do. -The requirements in 1-2 may vary widely depending on the game.
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
1 | Delta | 0xLEVEL | = | Value | N | (0) | |
2 | Trigger | Mem | 0xLEVEL | = | Value | N+1 | (0) |
3 | Mem | 0xITEM | = | Value | TRUE | (0) |
Requirements
- 1-2: Functionally the same as conditions 1-2 from the Finish Level N template, but with a Trigger on the final line so that the challenge icon shows to the player while the challenge is active.
- 3: Value that is true when the player has the correct item. The lack of a Trigger flag here allows the icon to appear while the player has the item, and disappear when the player does not have it.
This template is for battery save or password protection for items. It avoids awarding "get item X" by loading a password or save where the player already has the item. It checks that an item is collected in the level/room ID it is supposed to be collected, and only allows it be earned at that time.
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
1 | Mem | 0xLEVEL | = | Value | COLLECT_LEVEL | (0) | |
2 | Mem | 0xLEVEL | = | Delta | 0xLEVEL | (0) | |
3 | Delta | 0xITEM | = | Value | FALSE | (0) | |
4 | Mem | 0xITEM | = | Value | TRUE | (0) |
Requirements
- 1-2: Must be in the correct Level (
COLLECT_LEVEL
) for at least two frames during the frame at which the item status changes, preventing the following conditions from triggering the logic on load. - 3: Did not have the item last frame
- 4: Have the item on the current frame.
Notes
- Requirements 1 and 2 together mean you have to have been in the level for at least two frames. The frame at which you load the data (from password or save) will be considered false, so any change in the item status at this time won't cause the trigger.
- It does not necessarily have to be level/Room ID. There are other ways to approach this problem, for example a unique Mem/Val that only occurs on collection. Etc.
This is limited battery save/password protection for when a player will collect 100% of something like clearing each stage in Super Mario world, or getting a 100% collection rate in Super Metroid. It's necessary so that a player cannot just load a save at 100% and get the achievement for free. (As usual there are other ways to approach this problem too.)
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
1 | Delta | 0xCollectPercent | < | Value | 100% value | ||
2 | Mem | 0xCollectPercent | = | Value | 100% value | ||
3 | Mem | 0xGuardConditions | = | Value | When to Check for Increase |
Using the correct condition or conditions for requirement 3+ is especially important. You need to find an address or addresses that represents a unique time in the game where this percent increases. You'd not want the achievement to trigger when the player is loading their in game save file, which means this achievement must evaluate to False
at that time.
Examples
- Check for an in-game state and look for it being active for multiple frames, similar to the level check in Collect an Item in a specific Level:
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
3 | Mem | 0xGAME_STATE | = | Value | IN_GAME | (0) | |
4 | Mem | 0xGAME_STATE | = | Delta | 0xGAME_STATE | (0) |
- In Super Mario World this change happens while the player sees the world map after completing a stage. So you construct your conditions for this timing in a way to distinguish that from loading a save. Here the player state would be
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
3 | Mem | 0xPlayerState | = | Value | Returned to map from completed |
In the Collecting an Item N times we are counting how many times the counter goes up. But in some games there are situations where the counter goes up twice in the same frame, and the hit counter is incremented only by one. This behavior, obviously, ruins our logic. We're going to see a way to circumvent this issue.
The technique used here relies on two other ones:
Here's the trick:
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
1 | Sub Source | Delta | 0xCOUNT | ||||
2 | Add Hits | Mem | 0xCOUNT | = | Value | 0x02 | |
3 | Mem | 0xCOUNT | > | Delta | 0xCOUNT | (N) | |
4 | Reset If | Mem | 0xLIVES | < | Delta | 0xLIVES |
It can look a bit confusing at a first sight, but maybe using a real example it can be more clear. Check the Circumvent the Problem of a Counter Incrementing Twice in the Same Frame.
In this example we want to detect a value changing from V1
to V2
ten times:
ID | Flag | Type | Memory | Cmp | Type | Mem/Val | Hits |
---|---|---|---|---|---|---|---|
1 | And Next | Delta | 0xADDRESS | = | Value | 0xV1 | |
2 | Mem | 0xADDRESS | = | Value | 0xV2 | (10) |
Requirements
- 1: If value in
0xADDRESS
in the previous frame is0xV1
- 2: AND If the current value in
0xADDRESS
is0xV2
, increases the hitcount (up to 10).
Conditional resets can be used for many things.
Lets say you want to have a reset if a player enters a certain X and Y zone of a level:
CORE
- The Core is whatever condition(s) you need for your achievement to be true. It can also include normal reset behavior.
ALT1
ID | Flag | Type | Memory | Cmp | Type | Mem/Val |
---|---|---|---|---|---|---|
1 | Reset If | Mem | 0xLEVEL | = | Value | LEVELID |
2 | Pause If | Mem | 0xX-COORDS | > | Value | RESET-X-ZONE |
3 | Pause If | Mem | 0xX-COORDS | < | Value | RESET-X-ZONE |
4 | Pause If | Mem | 0xY-COORDS | > | Value | RESET-Y-ZONE |
5 | Pause If | Mem | 0xY-COORDS | < | Value | RESET-Y-ZONE |
- The reset will only happen if all of the Pause If conditions are not true.
- The pause is local to the alt but the reset resets the entire achievement.
ALT2
ID | Flag | Type | Memory | Cmp | Type | Mem/Val |
---|---|---|---|---|---|---|
1 | Mem | 0x1 | = | Mem | 0x1 |
- Any true condition. (to satisfy alt behavior having an always true alt is needed)
Notes
- You can use multiple conditional resets, each one in their own alt group to have far greater control of reset behavior.
- User Guidelines
- Developer Guidelines
- Content Guidelines
- FAQ
- Setup Guide
- Emulator Support and Issues
- Ways to Contribute
- RABot, the RA Discord Robot
- Events
- Overlay Themes
- Useful Links
- Contributing with the docs
- About Us
- Tutorials
- Developer Docs
- How to Become an Achievement Developer
- Getting Started as an Achievement Developer
- Game Identification
- Achievement Design
- Achievement Scoring
- Difficulty Scale and Balance
- Progression and Win Condition Typing
- Badge and Icon Creation
- Achievement Development Overview
- Flags
- BitCount Size
- Alt Groups
- Hit Counts
- Delta Values
- Prior Values
- Value Definition
- Condition Syntax
- Minimum Required Versions for Logic Features
- Memory Inspector
- Real Examples
- Set Development Roadmap
- Achievement Templates
- Tips and Tricks
- Leaderboards
- Rich Presence
- RATools
- Console Specific Tips
- Emulator Hotkeys for Developers
- libretro core support
- Docs To Do List
- WIP User Code of Conduct
- WIP CoC FAQ
- WIP Content Guidelines
- WIP-Jr
- WIP---Dev-Tips---Code-Notes-En-Masse
- WIP-‐-Reauthorship-Policy
- Manifesto RetroAchievements
- Código de Conduta do Usuário
- FAQ - Perguntas Frequentes
- Como contribuir se você não é um desenvolvedor
- Tutorial para Jogos Multi-Discos
- Introdução
- Primeiros Passos como um Desenvolvedor de Conquistas
- Recursos de Lógica para Achievements
- Exemplos Reais
- Dicas e Truques
- Dicas Específicas de Console
- Modelos de Achievement
- Escala de Dificuldade e Equilíbrio
- Roteiro de Desenvolvimento de um Set de Conquistas
- Criação de Ícones e Emblemas
- Leaderboards
- Rich Presence
- Design de Conquistas
- Manifesto RetroAchievements
- Código de Conducta del Usuario
- FAQ - Preguntas Frecuentes
- Tablas Globales y Reglas para la Casería de Logros
- Mi juego no esta cargando los logros
- Como contribuir si no eres un desarrollador
- Por que no deberías utilizar la función de cargar estado
- Contribuyendo con los documentos
- Como funciona la Documentación de RA
- Descargas
- Intro
- Código de Conducta del Desarrollador
- Como convertirme en un Desarrollador de Logros
- Primeros pasos como un Desarrollador de Logros
- Un vistazo al Inspector de Memoria
- Características en la Logica de un Logro
- Ejemplos Reales
- Intro
- Utilizando Hit Counts como un Temporizador
- Utilizando Valores Delta y Hit Counts para Detectar un Incremento
- Un Ejemplo Simple en como evitar el Abuso de Estados de Guardado
- Evitar el Problema de que un Contador se Incremente Dos Veces en el Mismo Frame
- Creando un Temporizador con un ResetIf Hits basándote en la Velocidad de un Juego
- Plantillas para Logros
- Tips y Trucos
- Escala de Dificultad y Balance
- Diseño de Logros
- Mapa de Desarrollo de Set
- Revisiones en Set de Logros
- Creación de Iconos y Badges
- Tablas de Clasificación
- Rich Presence
- Trabajando con el ROM apropiado
- Identificación del Juego
- Guía para Sets Bonus
- Logros para ROM hacks
- Tips Específicos por Consola