Finding FormIDs of elements
One thing that you will need to know across the board to create your own achievements is knowing how to find FormIDs. If you're an experienced modder you can skip to the next section.



Let's start by loading up the Creation Kit and let's take as example the simplest of items: Iron Dagger.
First you need to use the icon in the top-left corner of your menu to choose what plugins to load. If you're looking for items in mods you will need to load those too, in this case the Iron Dagger is defined in the base game, so let's load only "Skyrim.esm"
In the top left of the object window you can find research filter. Let's search for "IronDagger".
The first column shows you what is called _EditorID_, which is a textual ID or the item. You will never need the second and third column so let's skip to the fourth, which shows you what type of element that entry is, as example WEAP for weapon, QUST for quest, ANIO for animations, etc... sometimes multiple entries have a similar name but a different form type, so you want to be able to distinguish what you're looking for.
If you hover your mouse on the EditorID for a couple of seconds you will get an eight-digit hexadecimal string, called FormID. In this string, the first two digits (most significant digits) represent the position in the load order of the mod they are defined in, the remaining six define the relative FormID, which is mostly what you will use to create a configuration.
So in our case Iron Dagger has Editor FormID "IronDagger", absolute FormID "0001397E" and relative FormID "01397E". 
You can also fetch FormIDs using xEdit, however as I'm not proficient in that tool it will not be featured here. There is, instead, a simpler way to view FormIDs of most items, characters, objects and enemies in-game, which I will refer to later. For the time being let's assume that you know how to find the FormID of what's relevant for your mod.

General JSON Configuration.
Let's setup the base of the JSON configuration.
{
    "groupName": "Example Group",
    "plugin": "Skyrim.esm",
    "achievements": [
    ]
}

If you've read through the whole wiki you know that the groupName is the identifier of the group of achievements, and it will also be the Display Name in the achievement menu, and the plugin refers to base plugin that will be used to find the Absolute FormIDs given the Relative FormIDs.
This is because load orders are different for everyone, so you can't just use the absolute FormID and call it a day: mod 2A for you is probably not the same I have.

Example 1 - Trigger an achievement when the player has a specific item in the inventory.
This type of event requires you to know the FormID of the item and what quantity of item that you want the player to have. So let's start writing that.
{
    "groupName": "Example Group",
    "plugin": "Skyrim.esm",
    "achievements": [
        {
            "achievementName": "Up the gullet",
            "description": "Find, buy or craft an Iron Dagger",
            "conditions": [
                {
                    "type": "ItemInInventory",
                    "formID": "0896F5",
                    "quantity": 1
                }
            ]
        }
    ]
}

Now when the player acquires in any way an Iron Dagger, the achievement "Up the gullet" will unlock, and the player will be notified.
This shows an important property of ItemInInventory: it doesn't matter how the player acquires the item, the only important thing is that it is acquired.

Example 2 - Trigger an achievement when the player has acquired, over the playthrough, all the available daggers.
Now let's add a new achievement. In this case we want the player to have acquired an Iron Dagger, a Steel Dagger, a Glass Dagger, an Ebony Dagger and... well you got the point.
{
    "groupName": "Example Group",
    "plugin": "Skyrim.esm",
    "achievements": [
        {
            "achievementName": "Up the gullet",
            "description": "Find, buy or craft an Iron Dagger",
            "conditions": [
                {
                    "type": "ItemInInventory",
                    "formID": "01397E",
                    "quantity": 1
                }
            ]
        },
        {
            "achievementName": "Dagger Collector",
            "description": "Get all types of daggers.",
            "joinType": "AND",
            "conditions": [
                {
                    "type": "ItemInInventory",
                    "formID": "01397E",
                    "quantity": 1
                },
                {
                    "type": "ItemInInventory",
                    "formID": "013986",
                    "quantity": 1
                },
                {
                    "type": "ItemInInventory",
                    "formID": "0139A6",
                    "quantity": 1
                },
                {
                    "type": "ItemInInventory",
                    "formID": "0139AE",
                    "quantity": 1
                }
            ]
        },
    ]
}

Notice now the JoinType parameter, that shows that for the achievement to be unlocked, it is required for all the conditions to be met.
This is cool, now we have an achievement that pops up if you have these four types of daggers but... what if you're making a collection of items... from other mods? Let's add a dagger from JS Unique Utopia SE.
In the creation kit we see that the filename of the plugin is "JS Unique Utopia SE - Daggers - Johnskyrim.esp"  and we are looking for the dagger "0ECD53".
We can add it to our list using the pluginOverride property.
{
    "groupName": "Example Group",
    "plugin": "Skyrim.esm",
    "achievements": [
        {
            "achievementName": "Up the gullet",
            "description": "Find, buy or craft an Iron Dagger",
            "conditions": [
                {
                    "type": "ItemInInventory",
                    "formID": "01397E",
                    "quantity": 1
                }
            ]
        },
        {
            "achievementName": "Dagger Collector",
            "description": "Get all types of daggers.",
            "joinType": "AND",
            "conditions": [
                {
                    "type": "ItemInInventory",
                    "formID": "01397E",
                    "quantity": 1
                },
                {
                    "type": "ItemInInventory",
                    "formID": "013986",
                    "quantity": 1
                },
                {
                    "type": "ItemInInventory",
                    "formID": "0139A6",
                    "quantity": 1
                },
                {
                    "type": "ItemInInventory",
                    "formID": "0139AE",
                    "quantity": 1
                },
                {
                    "type": "ItemInInventory",
                    "pluginOverride": "JS Unique Utopia SE - Daggers - Johnskyrim.esp",
                    "formID": "0ECD53",
                    "quantity": 1
                },
            ]
        },
    ]
}

The new condition will force the framework to look for the dagger in the specified plugin, rather than in the base plugin that we defined in the root of the JSON.

Example 3 - Listening for the completion of a quest
Now, Skyrim is full of quests, what if you want to add achievements to a quest? Well the procedure is the same. I'll use as example the achievement "War Hero" from the base game:
{
    "achievementName": "War Hero",
    "description": "Capture Fort Sungard or Fort Greenwall",
    "conditions": [
        {
            "type": "QuestStageDone",
            "formID": "083042",
            "stage": 9000
        }
    ]
},

Here you can see that I'm referring to "083042" (of Skyrim.esm) which is the quest "CWFortSiegeFort".
Through the creation kit you can see that the last stage of the quest is stage 9000, so if you want to reward an achievement on quest completion you want to use the last stage possible for that specific quest. Most vanilla quests have either 100 or 200, so this is an exception.
A note about vanilla quests is that you can also see most of the quest stages on https://en.uesp.net/wiki/, so if you're working on vanilla content go check it out.
If you looked closely at the format for quest conditions you might have noticed an OP property. What the heck is this? Let's explain it by taking a specific vanilla quest in consideration.
Say that I want to track whether the player has finished the quest "The House of Horror" by receiving the Mace of Molag Bal. Depending on the player action this item is missable. 
Stage 200 means the mace has been obtained, while stage 500 and 550 mean that the mace has not been received. When the game finishes the quest and misses the mace, the game will advance the quest from stage 140 to stage 500 or 550 depending on the player action.
Now the default OP value is GT which means "Greater Than", and what I do is a simple operation QuestStage >= Value, but you can see that using this operation, stage 500 will yield the achievement even if the mace of molag bal has not been received, since 500 >= 200.
If instead you use the OP value EQ, which means "Equals", the framework analyzes state of the quest on change, and if the stage 200 is skipped it will simply not trigger.
This does however mean that there is not backwards detection, so I cannot detect if the quest has already been completed with the determined stage or not, so keep this in mind.

Example 4 - Achievements granted on character death
There are two different conditions that you can use to grant achievements on character death, and which to use depends on the implementation of the base mod.
Let's first discuss how actors work (based on my very limited knowledge of the ck). The engines defines many Base Actors that are pretty much templates of NPCs, Objects and Enemies that can be placed on the map. These can be either placed manually on the map or added to a leveled list that will spread them throughout the land.
So let's suppose that you're working on granting achievements upon defeating a boss. Usually bosses are hand-placed, which means that the ReferenceID of that specific actor placement doesn't change, since it's been programmed statically. Now in this case you would normally have to go into the creation kit, open the cell window and see the Reference ID of the actor, or something similar.
My suggestion instead, is that by using More Informative Console we can just go into the cell in-game and check the Reference ID from the console. Pair this with Clicklight and you have a fairly robust development-system in-game.
If you delve in the sewers of Skyrim Sewers 2 you will see that underneath Whiterun a dragon priest is awaiting the player, let's go pay him a visit.



This shows that Jsashe has Reference ID 03D6E7. Notice also that the first two digits aren't 00 but 0A, and More Informative Console also shows you what esp defined the Base Actor and what esp defined the Ref, so in plugin (or pluginOverride) we will need to use "SkyrimSewers.esp".
{
    "groupName": "Example Group",
    "plugin": "SkyrimSewers.esp",
    "achievements": [
        {
            "achievementName": "A battle underneath the earth.",
            "description": "Defeat Jsashe.",
            "conditions": [
                {
                    "type": "ActorDeath",
                    "formID": "03D6E7"
                },
            ]
        },
    ]
}

Using More Informative Console is a nice way to get FormIDs and plugin in-game without having to open xEdit or the Creation Kit.
If instead you're trying to reference an enemy that has been defined through the Levelled List (sparse enemies like wolves, bandits, etc...), it will be enough to know the name of the enemy to define the BaseActorDeath condition. This is because different "Bandits" derive from different Base Actors (like for different classes of bandits that all have the same name but different properties), so while it's also possible to use the FormID of the BaseActor, that will guarantee that only the death of that specific type of base actor is counted.



So if you want the condition to happen every time the player kills a bandit, then probably your best bet is to use the "Bandit" name, if instead they need to kill a specific type of bandit you will need to use the correct FormID and plugin esp.
In case you use the name as parameter, you don't need to specify the plugin.
{
    "groupName": "Example Group",
    "plugin": "SkyrimSewers.esp",
    "achievements": [
        {
            "achievementName": "Bandit hunter",
            "description": "Kill 40 bandits",
            "conditions": [
                {
                    "type": "BaseActorDeath",
                    "name": "Bandit",
                    "quantity": 40
                }
            ]
        },
    ]
}

There are plenty more condition types, however just these four examples should be enough to give you some sort of basic understanding of the framework and how it works.

FAQ
I am using the correct FormID for an enemy / location / spell but the condition isn't triggering.
Properties are case sensitive, check that your configuration has the property formid written exactly like this: [code single]formID[/code]. 
My mod requires a custom condition, can you add it?
Writing a condition can take a couple of hours to different days, to being straight up not possible depending on your request. If you feel that your achievement cannot be written as a combination of the current conditions hit me up on nexus, github or discord and explain me what you need!
I've created a .dds icon but it won't show up.
Try saving it using BC3 compression. For some reason BC7 doesn't work, not sure why.

Article information

Added on

Written by

ItsNicklaj

0 comments