Creating Automaps

From The DarkMod Wiki
Jump to navigationJump to search

Introduction

Normally the player is given a map at mission start, which is showing him the location he is attempting to sneak in. However, it may not seem very realistic that the player already possesses such detailed information without ever been in the specific place. An automap, thus meaning a map that gets drawn while the player proceeds in his mission may seem more realistic.

On the other hand such thing can also add a lot to immersion. The player don't know what is expecting him in the beginning, but benefits from the advantages a map brings to him while he proceeds. In addition an automap provides information about where the player already have been and therefore can avoid frustrating moments when he is searching for one little room he may have overseen.

The following article now describes how to set up such an item.

Preparations

The first step is to actually draw your map. How you do this is your business. After you have done so you should cut out all the seperate rooms you want to appear on the map later on. Make sure to make the background transparent (using gimp for example). If you do so you should have

- one picture containing the parts of the map the player already know at mission start (called startmap furthermore) - several pictures of the rooms he can discover later on

It is your choice if you want to put the startmap on the map_of_.tga file served with the startmap package or keep it seperate. However, for the tutorial let's just assume you have choosen the first possibility.

Furthermore you should get familiar with the zone system as it is needed here.

Setting up the gui

The gui looks like this:

 windowDef Desktop
 {
   	rect      0,0,640,480
   	nocursor 1
        
       windowDef background_map
       {
               rect      64,48, 512, 394
               background "guis/automap/map_of"
               visible 1
       }
       ...
       // Required include for inventory map
       #include "guis/readables/inventory_map.guicode"	
 }

In our case guis/automap/map_of is the file that holds the startmap. Where the dots are you have to add the following code for each area visible on the map.

   windowDef nameOfArea
   {
        rect 100,100,380,300
        background "path_to_imagefile"
        visible "gui::gui_XYZ"
   }

- nameOFArea can be choosen as you like, but each name must be unique and it makes sense to make it recogniseable - path_to_imagefile holds the path to the image to be drawn. Where nothing gets drawn the image should be transparent - the gui variable gui::gui_XYZ determines whether the image is visible or not. XYZ is the name of the corresponding location entity. You can easely get typos, so if something isn't working this is the first place to check

Note that all pictures are using the same area of the gui. This easens the setup, but must be taken into account when creating the images for the map.

Things to do in DarkRadiant

This is the easiest part. In DR create an custom_static_item entity (darkmod/items/custom). Set the model to whatever you like, but if you plan it to be found later in the game you may choose a scroll or similar. Than set the following spawnargs:

- inv_name: the name to be shown to the player

- inv_map_start: set this to "1" if the player should start with the map in his inventory

- inv_category: set to "#str_02390" (important), this allows the map to become visible via the map key (m by default)

I will refer to this entity as map entity furthermore. Now create a target_callscriptfunction entity (darkmod/targets) and give it a suitable name. Set the spawnarg "call" "map1ShowHide" on it and target it from the just created map entity.

If the player 'uses' the map (by pressing the map key for example) the function map1ShowHide will be executed.

Redo this for every map and set "call" "mapXShowHide" where X is the map number.

The next thing needed to get the automap to work is to set up zones in your map. Every room that has it's own picture on the map must be represented by an own zone in you mission. Give every zone a suitable name, we will need those later on. Now set the spawnarg "call_on_entry" "mark" on them. This is the function that gets called whenever the player enters the specific zone.

 Note: Functions called via the target_callscriptfunction entity take the form void functionname() while functions called
       by zones take the form void functionname(entity zone)

The script file

Create a scriptfile called mymapname.script. Once we are finished it should lool like this

 float roomName1,...;    // stores if the player has been there (needed for every room)
 float h_roomName1,...;  // stores the handle to the room guis (see below, needed for every room)
 float h_map1,...;       // stores the handles to the startmaps (needed for every map)
 float map1Shown,...;    // if the map is currently shown (needed for every map)
 
 void mapXShowHide() {   // shows/hides the map (needed for every map, X is the map number)
   if (mapXShown) {      // player hides the map
     mapXShown=0;
     $player.destroyOverlay(h_mapX);
     if (roomName1) $player1.destroyOverlay(h_roomName1); //destroys the gui overlay for the startmap
     ...                 // destroys the gui overlays for all shown rooms (repeat this line for every room om map X)
     return;             // that's it, the map is hidden
   }
   sh=1;                 // player shows the map
   h_mapX=$player1.createOverlay("path to startmap.gui",100);           // show startmap
   if (roomName1) h_roomName1=$player.createOverlay("path to gui",101); // show room if player was there, do this for every room on map X while continuing the numbering (102,103,...)
   ...
 }
 
 void mark(entity zone) { //mark the area the player just entered as visited (you can use one function for all map or seperate them, your choice)
   string name;
   name=zone.getKey("name"); // the name of the zone
   if (name=="roomName1") {  // markes the room as visited if the player is there (needed for every room
     roomName1=1;
     return;
   }                         
   ...
 }
 
 void main() {
   roomName1=0; //do this for every room
 }

That's it. If you do this for large missions with many rooms the code will get quite long, but the single steps should be easy to understand. roomName1 and so one are just placeholders. Choose the name of the corrosponding zones in you mission.

If you use several maps it may be a good idea to put the map number into the zone names, for example "m1_tavern". It may also be a good idea to split the guis and images into several folders, one for each map. This is your choice.

Conclusion

It is quite simple to setup a fully functional automap. The main effort for the mapper is to actually draw the map and align the pieces later one. The script is easy but gets long. This is caused by the lack of suitable containers in the doom3 scripting language.

Additions

If you want to test the alignment in game, just change the lines in the main method in the script file. Set all the values to "1".

If you want to have an automap that marks where the player currently is, the following changes need to be done:

- The mark method is called via "call_on_exit" by the zones. "call_on_entry" calls a similar function that sets the value for the room to "2"

- The show method checks for the values to be "1" or "2" separately. For "2" a highlighted version is shown on the map

- Obviously you have to make these highlighted version first

If you want the map to be fond in the mission you have to do the following to avoid the rooms the player was before finding the map to be drawn on it

- create a hidden, non-mandatory objective "if player possesses item". The item is the map.

- fill the success_script field with drawMap

- in the script file, add a float mapDraw at the beginning of the file

- set this to zero in the main method

- in the beginning of the mark method add the line if (!mapDraw) return;

Obviously you will need to do this several times if the player can find several maps. If so, be sure to make different mark methods for every map to be found (thus meaning entities in the map file)

You can use this setup as a starting point for setting up objectives like "investigate 50% of the area".

Questions, replies and advices of any kind can go here

--Obsttorte (talk) 06:33, 25 January 2013 (EST)