Generic Game Layout =================== The game data for the Adonthell engine requires a special directory layout, which is described here. game/ - audio/ - gfx/ - cutscene/ - mapcharacters/ - mapobjects/ - portraits/ - window/ - maps/ - scripts/ - actions/ - dialogues/ - events/ - modules/ - schedules/ - audio/ - mapcharacters/ - mapviews/ [*] The toplevel directory Apart from the subdirectories, the toplevel directory contains two things: 1. The initial save game which will be loaded when beginning a completely new game. This is not really required, but if such an initial save game exists it must be located here. 2. The gamename.txt file, which contains nothing but the name of the toplevel directory. This is used to compute the name of savegames and for error checking. This file is required. [*] audio/ Music and sound fx. Music needs to be in Ogg Vorbis format, sfx in wave format. [*] gfx/cutscene/ Various images or animations to be used in cutscenes and the like. Images can be in pnm or Adonthell's internal format. Animations need to be in the internal format. [*] gfx/mapcharacters/ The character animations in Adonthell's internal format. [*] gfx/mapobjects/ The scenery of the map in internal format. [*] gfx/portraits/ The character portraits displayed during dialogue in pnm format. [*] gfx/window/ The graphics and fonts used by Adonthell's GUI. Should be copied from Waste's Edge. [*] maps/ The world map. [*] scripts/ Apart from the subdirectories, there is the init.py script. This is the script the engine executes after reading the config file and initialising the various subsystems. Once the script returns, the engine quits. [*] scripts/actions/ Python scripts launched by an 'action event', i.e. the player hitting SPACE. (Part of those ended up in scripts/events though). [*] scripts/dialogues/ Python scripts for conversation with NPC's. [*] scripts/events/ Python scripts launched by 'map events', i.e. walking on a tile or leaving it. [*] scripts/modules/ Various scripts that either provide basic functionality for any of the others or otherwise fit into no category. [*] scripts/schedules/audio/ Scripts that control the audio system. Gets called every time a song finished playing. [*] scripts/schedules/mapcharacters/ Scripts that control NPC behaviour. The player is also controlled by a Python script. [*] scripts/schedules/mapviews Scripts that control the behaviour of the mapview. At least some of those directories should contain something sensible before the engine can run. So lets take a look at each of them in more detail. The Initial Game Data ===================== There are two different kinds of data. Static data, that does not change thoughout the game, like graphics and scripts. Then there is the dynamic data that reflects the current state of the gameworld and therefore changes as the game progresses. The initial game data contains the initial state of the game, and here we have a look what belongs to the initial game data and how it can be created. There are four major parts, that all go into a file of their own: 1. audio.data This is the state of the audio system and the most simplistic. All it contains is the name of the audio schedule to invoke once a song finished playing and the song currently playing, if any. audio_set_schedule ("name") will assign the scripts/schedules/audio/name.py script as the current audio schedule. 2. quest.data Quest data is nothing more than a mapping of ints to strings. New mappings can be added anytime to keep track of game progress. They can also be removed once they are no longer needed. Any quest variable not explicitly allocated is considered to have the value of zero. The initial quest.data can be created via the questedit tool. 3. character.data This file contains information about NPC's and the player. It's best created via the charedit tool and finished with Python. A possible player looks like that: # -- at engine startup, an 'empty' player is created player = gamedata_player () # -- set some attributes, only 'type' is required, # more can be set as you like player.set_val ("gender", MALE) player.set_val ("race", HUMAN) player.set_val ("type", PLAYER) # -- load the graphics (gfx/mapcharacters/player.mchar) player.load ("player.mchar") # -- add player to a certain map at a certain location # facing a certain direction player.set_map (a_map) player.jump_to (0, 4, 18) player.stand_east () # -- give the player a schedule # (scripts/schedules/mapcharacters/keyboard_control.py) # and activate it player.set_schedule ("keyboard_control") player.set_schedule_active (1) A NPC is a little different: # -- basic characters as created with charedit end up in the # character array after loading. erek = gamedata_get_character ("Erek Stonebreaker") # -- to be of any use they need a dialogue script, a portrait, # a text color and an action script that tells them what to # do when the player addresses them. erek.set_dialogue ("dialogues/erek_start") erek.set_portrait ("erek.pnm") erek.set_color (3) erek.set_action ("talk") erek.set_action_active (1) # -- the rest is similar to the player erek.load ("erek.mchar") erek.set_map (a_map) erek.jump_to (1, 5, 5) erek.stand_north () erek.set_schedule ("erek") That's what makes up a character. Later on, we'll take a closer look at actions, schedules and dialogue scripts. 4. mapengine.data ... The Init Script =============== When the game engine is invoked, it will first load the configuration file ($HOME/.adonthell/adonthellrc), test whether the given game exists and is valid, finally initialize graphics, audio, python and input subsystems and finally call the init script (scripts/init.py). The init script has a number of purposes: as long as no initial save game exists, game data like characters or events and even whole maps can be created from that script. Apart from that it can make calls to intro and extro scripts and do other setup tasks. Lets have a look at some specific things init.py should do. Initialize the window manager, i.e. load the themes and fonts that will be used later on: win_manager_add_theme ("original") win_manager_add_font ("original") It should at least load the initial save game (once there is one): gamedata_load (0) Instead of loading the complete game, it might be necessary to only load those parts that are available so far: gamedata_load_characters (0) gamedata_load_quests (0) gamedata_load_mapengine (0) gamedata_load_audio (0) We'll need to start the engine's main loop. That makes no sense before we don't have at least one window to display. This could be the window containing the intro scene or possibly the load game window. gamedata_engine ().main (some_window, "some_name") At the very end, we'll have to start the mapview: gamedata_engine ().mapview_start () gamedata_engine ().fade_in ()