Tutorials & Achievements

After working on consoles for a long while, you get to know the all the systems in a game engine – even ones you don’t actively work on. You talk over algorithms with other programmers, make sure your systems work well with others, and help fix all sorts of bugs near ship time. Given that, there’s very few systems that I needed to write for Banished that I hadn’t had any exposure to at all. These past few weeks I’ve found two. Tutorials and Achievements. Implementing them has been a typical round of designing something, getting halfway through it, and realizing there is a better way I could be doing it.

There is a hard issue to deal with tutorials in a city builder or RTS. If you tell the player to do something, you have to make sure they can actually do it, and do it without error. Whatever they do, the next tutorial step has to be valid as well. In addition, anything the player is allowed to do that isn’t part of the tutorial shouldn’t invalidate anything in the tutorial.



There are way to many things that can go wrong if the tutorial gives the player freedom. If you say, ‘Place a Log House’ and let the player pick the location, they could place in a location where the townsfolk can’t get to it. They could try to build a stone house instead when there isn’t any stone available.

Given that, the tutorial needs to be a predictable experience where the player can’t get anything wrong.

The first issue I dealt with in trying to do this is that Banished has so much user interface. There are lot of buttons and widgets that the player can fiddle with. In most tutorial steps the player should only be allowed to only press one button, or place one object. I didn’t want to inject any tutorial code into the main UI code – that’s just messy coding and bug prone. So instead I built the tutorial system to just disable all UI widgets with a special flag that only the tutorial uses.

This allowed all UI code to proceed normally without knowledge that the tutorial is occurring. Once that system was in place, the tutorial can disable all widgets except for a few buttons per step. I also added the ability to add an overlay dialog to highlight any widget so the user would know on screen where things are.

The configuration for the tutorials works the same way as all my other data serialization. The setup for what UI elements are available looks like this.

TutorialUISetup enabletransport { String _exclusions [ "ToolbarDialog:transport" // allow toolbar 'transport' group to be pressed "ToolbarDialog:options" // allow options button so user can save/load/quit ] // highlight the transport button with standard arrow and highlight String _highlight = "ToolbarDialog:transport"; Dialog _highlightDialog = "Dialog/TutorialHighlight.rsc"; int _highlightRotation = 0; }

There are also other setup items that can occur, like changing the speed the game runs at.

TutorialChangeGameSpeed normalspeed { int _speed = 1; // set game speed to normal. bool _forcePlay = true; // force the game into the run state if it was paused. }

Each tutorial step also has a goal – what should the user have to do for the tutorial to proceed? Press a button? Place a house? Set a certain number of workers? The tutorial system has a bunch of different goals it can wait for – they all just monitor the state of the game. Again this was done without adding code to any real game system – everything is limited to the tutorial system. Once the goal is met the tutorial moves onto the next step. A typical goal looks like this:

TutorialGoalButtonPress goaltransport { String _button = "ToolbarDialog:transport"; // wait for transport to be pressed }

Finally I needed a way to display information to the user explaining what they should do. This is a simple dialog with some text and images on it. The setup for this looks like so:

// grabs the icon from the toolbar for display in the tutorial window TutorialImageToolbarIcon icontransport : "baseIcon" { Toolbar _toolbar = "Game/Toolbar.rsc:transport"; int _locationX = 0; int _locationY = 0; } // hotkey images read from user input map so it always shows the current key TutorialImageHotKey hotkeytransport : "baseKeyPress" { Toolbar _toolbar = "Game/Toolbar.rsc:transport"; int _locationX = 2; int _locationY = 0; } TutorialStep stepPlaceRoad0 : "baseStep" { bool _isSafeRestart = true; // safe resume point if returning from a save game StringTable _stringTable = "tutorialStrings"; // all strings for the tutorial String _preText = "Step_Road_0_Pre"; // text to display before the images String _postText = "Step_Road_0_Post"; // text to display after the images TutorialGoal _goals [ "goaltransport" ] // list of goals TutorialSetup _setup [ "enabletransport", "normalspeed" ] // list of setup items TutorialImage _images [ "icontransport", "or", "hotkeytransport" ] // list of images }

After all that setup, what do we get? A step in a tutorial that waits for a button press!



The only other major thing I had to add was a way to show the user where to place things, and not allow them to place them in any other location or orientation. Unfortunately this did require some code added to the system that allows the user to place something – it has to know if it’s in a ‘restricted’ mode where the current item has to be placed in a specific location. It also resulted in nicer placement footprints that show building orientations and where roads can overlap the building area.

The process of building the tutorial is slow – mostly in testing and deciding what things to cover and in what order. I’ve got the first ‘Getting Started’ tutorial finished – it shows the basics of survival, building things, and basic resource production. I’m planning on doing a few more tutorials on the different methods of food production as well as long term survival. These tutorials show how to play, but really won’t give away any best way to play. There’s more than one, and that’s for the player to twiddle with.

So with the tutorial system out of the way, I turned to finishing the achievements.

Whether you love them, hate them, or use them to show off your gaming prowess with your friends, Achievements seem to be an integral part of games now. In some ways they’ve always been there – just not formalized. For me, finding a room full of goodies and then and seeing only 34% of secrets found at the end of a level made me play Wolfenstein3D levels over and over and over. I generally only try to get 100% of achievements in games I really like – where the extra gameplay time isn’t a grind.



Like the tutorial, the achievements are setup so that they don’t interfere with any actual game code, they just monitor the state of the game and keep their own state.

I’ve tried to keep the achievements for Banished reasonable, but also make them things that aren’t likely to happen except when you build big cities and do a good job while doing so.



Here’s what the setup for the achievement looks like – very similar to tutorials, but with different goal types. This particular achievement requires a certain amount of food be produced in a single year by every type of food production building.

Achievement foodie : "AchievementList.rsc:achievement" { String _sprite = "AchieveFoodie"; String _text = "Foodie"; String _description = "FoodieDesc"; Goal _goals [ "hunter", "gatherer", "fisherman", "pasture", "cropfield", "orchard" ] } StatGoal base { StatType _stat = ProducedFromBuilding; // count total produced from buildings StatOp _op = GreaterEqual; int _count = 2000; // must get 2000 for achievement to be met RawMaterialFlags _rawMaterial = Edible; // only count edible items } StatGoal hunter : "base" { WeakExternal _object = "Template/HunterLodge.rsc"; } StatGoal gatherer : "base" { WeakExternal _object = "Template/GathererShelter.rsc"; } StatGoal fisherman : "base" { WeakExternal _object = "Template/FishermansDock.rsc"; } StatGoal pasture : "base" { WeakExternal _object = "Template/Pasture.rsc"; } StatGoal cropfield : "base" { WeakExternal _object = "Template/CropField.rsc"; } StatGoal orchard : "base" { WeakExternal _object = "Template/Orchard.rsc"; }

Here’s an image of me testing this achievement, and nearly filling the screen with the UI.





The second worst part about all these achievements is making an icon that goes with each achievement and somehow represents what it is. It took at least an entire work day to make 36 icons that I was pleased with. The actual worst part of achievements is testing them.

A lot of the achievements have population requirements or time requirements. For example, one achievement is to maintain high health for a population of more than 200 people over 10 years. For most people this is somewhat likely to happen as you play, but getting there is tough. You can build a town of 200 people in maybe 5 hours (if no disasters occur and you’re familiar with the game already.) Then maintaining the health of those people for ten years takes at least another hour if the game is running at fastest speed. Now do this for all the achievements….

My guess is that to truly test all the achievements would take me more than two weeks of nonstop play. Instead I’ve been testing them using cheats. Being the developer, I can build things with no resource cost, disable health and warmth concerns, and get people to survive without homes. I can add resources and unlock things you normally have to trade for. This really speeds things along and makes the goals for the achievements attainable in a reasonable time. However when I do use the cheats, I try to cheat in a way that makes sure to validate the attainability of the achievement. Even with the cheats, getting 100% of the achievements took about 11 hours. With cheats! Phew!

For those of you that noticed it in the image above, no I’m not planning on having that ‘Debug’ dialog available in the final version of the game, and yes you can switch the temperature display to Celsius. And if the overhead map area looks small, that’s because I’m playing on a small map. 🙂

So what’s next? Not sure. My schedule has fewer and fewer items on it each day! Am I actually coming to the end of development!? Sweet!