Eventing a Trophy Room
hiddenone
by
hiddenone
on
April 7, 2022
March 22, 2022

Eventing a Trophy Room

Eventing a Trophy Room
by

hiddenone

on

April 7, 2022

Achievements and trophies are something that show up in tons of games nowadays, but often they’re just listed in a menu. What if you wanted to create an in-game trophy room that your players can explore to see all that they’ve accomplished?

Besides giving our players a place to actually see all their achievements pile up, a trophy room could have extra rewards like special items or let our players replay minigames. The trophy room could also be the party’s base, making their rooms update and change as the player finishes more of the game. While the examples we’ll be working with here will only have simple messages and sprites as their rewards, keep in mind that you can add whatever extras you want to your own game’s trophies.

Trophies based on Game Progression (Switches)

One of the simplest ways to add trophies is to tie some to game progression. When your players defeat a boss or clear a specific point in the game, then they get a shiny trophy that appears in their trophy room.

For example, let’s have a trophy appear when our hero wins a card game that they have to play to advance the main plot. Winning the card game turns a specific switch On, which we can use to turn on the second page of our trophy event. Since I want our players to know that there will be a trophy there in the future, we can set the first page to have a question mark balloon appear with the script call $gameTemp.requestBalloon($gameMap.event(this.eventId()), 2); in the page’s move route. Alternatively, we could make a sprite that is just a question mark or stand without a trophy to show there could be something there in the future.

Then we can playtest in our trophy room. To make it easier on us, let’s also put in a helper event (Sir Oinkers here) that can turn on the switch in the room so that we don’t need to play the card game to make sure the trophy appears. When the switch is Off then our balloon will appear and the trophy hint will play.

But once we turn the switch On, our trophy will appear along with a message explaining what the trophy is for.

If we used variables to track the plot points we could also use those to have certain trophies appear, or combine them with switches for specific rewards. Maybe if our players befriend a party member (tracked with a variable) and reach the middle of the game (tracked with a switch) then they’ll unlock a special trophy.

Trophies based on Hidden Items

Giving trophies only for completing story beats works, but it’s always nice when our players can feel like they’ve really discovered a secret like hidden collectibles. Realizing that there are things like hidden bobble heads throughout the world can make our players want to explore more, which may help them stumble into a side quest or dungeon that they normally would have missed. But it can be a bit annoying as a player to have a bunch of collectibles that don’t do anything cluttering up our inventory, so why don’t we turn these collectibles into trophies?

We could use switches for this again, but if we make these into actual items then we can use them in other situations, such as having an NPC want to see a certain collectible and our players having to choose the right one with the Select Item event command to receive a reward.

First, we’ll need our collectibles. In this case, let’s make a magic book and make sure to set its Item Type to ‘Hidden Item A’ so that it won’t appear in the inventory. We’re only making one here, but you’ll need a different item for each collectible that has its own trophy.

Our trophy’s event can be similar to our switch one above, with the main difference being that we’ll be checking for our magic book item in the Conditions.

Then we just need to playtest and make sure our trophy appears properly when our players receive the item.

Storing Multiple Achievements in 1 Variable

Now, the methods we’ve looked at above work great, but only for single things since they can’t easily track trophies that require multiple things, such as a trophy for catching 5 butterflies that fly around maps or trophies for getting high scores in a fishing minigame. To track that stuff we’ll need to use variables, but that leads to another problem: what if we don’t want to use a bunch of variables for these trophies? For large games or ones with tons of possible trophies we may not want to use 10+ variables to track all the different trophy numbers when we could be using them for something else. So instead, let’s see one way we can store all our trophy details in a single variable. A tutorial by Trihan and my previous chat with caethyril helped inspire this method for storing achievements, so big thanks to them for sharing their knowledge.

For this example, let’s track our players’ fishing high score, number of dishes cooked, and number of butterflies caught. If our players reach specific scores for fishing they’ll receive either a bronze, silver, or golden fish trophy and if they catch 5 butterflies or cook 5 dishes then they’ll get the corresponding butterfly or cooking trophy.

While we could set our trophy events like above with two pages, for these trophies let’s have them be a surprise. That means we’ll only need one page for each, with the Conditions set to self-switch A being On (we’ll be activating those self-switches in another event using a script call).

Then we just need to make the rest of our trophies in the same way, making sure to name them so that it’s easy to check or edit them later.

With our trophies ready to go we can get started on the eventing. At the start of our game while we’re setting up things we need to turn our chosen variable into our trophy tracking array using the script option. For our three trophies we’ll be tracking, we’ll want to set up our array as [["fishing high score", 0], ["butterflies caught", 0], ["cooking mama", 0]] , so that each trophy is an array of two values stored in the larger variable array.

Why not just use a simpler array like [0, 0, 0] ? While that would work, it leaves it up to us to remember which number belongs to which trophy and once we start adding more numbers it makes it easy for us to make a mistake and then have trouble finding exactly where we made that mistake. By having each number connected to the trophy name, it should be easier for us to spot any issues.

With our trophy array numbers all set to 0, we can start finding ways to fill them. First, let’s take a look at how we can increase our butterflies caught number by 1 each time our player interacts with a butterfly event.

We’ll start our script call by checking each array inside our main variable by using for (var achieve of $gameVariables.value(1)) {} , where achieve will contain each of our trophy arrays separately as it runs (so for our butterfly trophy achieve[0] will equal “butterflies caught” and achieve[1] will equal 0 or the current number if it’s already been increased). Any word can be used in place of achieve, but you need to type it exactly the same throughout the code.

Then we can put the conditional branch if (achieve[0] == "butterflies caught") {} inside that so that when we reach the butterfly trophy array it will run the code achieve[1] += 1; inside the condition. Putting it all together, our code should like something like this:

for (var achieve of $gameVariables.value(1)) {

 if (achieve[0] == "butterflies caught") {

   achieve[1] += 1;

   console.log("It worked! Another butterfly was caught")

 }

}

This will run through our trophy arrays and when it finds the one with “butterflies caught” as the first array value (achieve[0]) it will increase the second value (achieve[1]) by 1. So when it is run, our array will change from

[["fishing high score", 0], ["butterflies caught", 0], ["cooking mama", 0]]

to

[["fishing high score", 0], ["butterflies caught", 1], ["cooking mama", 0]],

leaving our other trophy values untouched.

The console.log($gameVariables.value(1)) and other console.log() parts do not affect the eventing, but they are helpful since they’ll show those values in the engine console (which you can open with F8 while playtesting). That makes spotting any issues, such as a number not increasing when it should, more visible which in turn makes it easier to fix right away since you’re aware of it earlier. So while console.log() isn’t necessary, it can be nice to have while using lots of these script calls.

So, that method works for trophies that are increased each time our players interact with the events like the butterflies and cooking ones, but what about ones that are based on a high score? We don’t want to keep increasing a high score each time a player tries the minigame, because then even if they scored low if they kept playing they’d eventually get the higher trophies. So we’ll need to add some extra conditions before we can change the value. Before we can get to the code though, we’ll need to know how we’re storing the fishing score in the minigame so that we can use that exact number later. For this tutorial, I’ll set a variable (2 in this case) to randomly pick a number between 0 and 25 to act as the fishing score.

The start of our code will be the same as our butterfly example, though since we’re looking for our fish high score we need to check if achieve[0] == “fishing high score”. When it is a match, then we can run another conditional branch, this time being

if (achieve[1] < $gameVariables.value(2)) {} . This checks the current high score that’s saved in the array and sees if it is lower than the score stored in variable 2. If it is, that means our players hit a new high score and the current high score needs replaced with

achieve[1] = $gameVariables.value(2); . If achieve[1] is higher than variable 2 then our players’ current high score is higher than the new score and we don’t need to change anything.

All together, our code ends up like this:

for (var achieve of $gameVariables.value(1)) {

 if (achieve[0] == "fishing high score") {

   if (achieve[1] < $gameVariables.value(2)) {

     achieve[1] = $gameVariables.value(2);

     console.log("It worked! Fishing high score has been changed")

   } else {

     console.log("No change. Fishing high score is higher than new score.")

   }

 }

}

Then we just have to run that after our fishing minigame, and our players’ high score will be recorded.

Our code doesn’t need the } else {console.log("No change. Fishing high score is higher than new score.")} to run, but having it there does give us a chance to check the console to make sure the script is running properly.

Once we set up our cooking trophy to run similar to our butterfly one, we can move on to the last step: checking our trophy values and making the trophies appear if our players have successfully reached the scores we decided on. If the scores are reached, then we’ll need to turn on the specific trophy’s self-switch A On, using

$gameSelfSwitches.setValue([$gameMap._mapId, id, 'A'], true);

Where id will be the corresponding trophy’s event ID.

To check both the trophy name and score value in one conditional branch we’ll be using &&, so it will only run if both achieve[0] and achieve[1] are the values we’re looking for. So if we want to give our players the bronze fishing trophy (which has 3 as its event ID) when they get a high score of 5 or better, our code would be:

 if (achieve[0] == "fishing high score" && achieve[1] >= 5) {

   $gameSelfSwitches.setValue([$gameMap._mapId, 3, 'A'], true);

 }

Once we decide that for the silver fishing trophy our players need a score of 10 and for gold they need 20, we can type those conditional branches out along with our butterfly and cooking ones that need a score of at least 5. When they’re all ready, our code should look like this:

for (var achieve of $gameVariables.value(1)) {

 //Fishing achievement check

 if (achieve[0] == "fishing high score" && achieve[1] >= 5) {

   $gameSelfSwitches.setValue([$gameMap._mapId, 3, 'A'], true);

 }

 if (achieve[0] == "fishing high score" && achieve[1] >= 10) {

   $gameSelfSwitches.setValue([$gameMap._mapId, 4, 'A'], true);

 }

 if (achieve[0] == "fishing high score" && achieve[1] >= 20) {

   $gameSelfSwitches.setValue([$gameMap._mapId, 5, 'A'], true);

 }

  //Butterfly achievement check

 if (achieve[0] == "butterflies caught" && achieve[1] >= 5) {

   $gameSelfSwitches.setValue([$gameMap._mapId, 6, 'A'], true);

 }

 //Cooking achievement check

 if (achieve[0] == "cooking mama" && achieve[1] >= 5) {

   $gameSelfSwitches.setValue([$gameMap._mapId, 7, 'A'], true);

 }

}

Since we really only need the check event to run when our players enter the trophy room, we can make it an autorun event that runs the code and then uses the Erase Event command to remove it while on the map. When our players leave and re-enter the map, the event will run again so any newly achieved trophies can appear.

Last thing we need to do is playtest and make sure our trophies appear when we want them to. Comparing the console log to our known target values can make it easier to tell if our trophies are appearing properly, and if they are not then we can check if we mistyped somewhere.

Now we can set up as many trophies as we want! How would you use trophies and achievements systems like this in your own games?

Recommended Posts