Difference between revisions of "Map tutorial"

From Dragon Age Toolset Wiki
Jump to: navigation, search
m (Converting XLS files into GDA files)
(Added photoshop map making tutorials, and resources to the map making tutorial section.)
Line 59: Line 59:
  
 
[[Image:Worldmaps worksheet target_wps_epona.png]]
 
[[Image:Worldmaps worksheet target_wps_epona.png]]
 +
 +
  
 
== Using M2DAs to extend the game ==
 
== Using M2DAs to extend the game ==
Line 91: Line 93:
  
 
Note that there will be a separate GDA file for each worksheet in the XLS file, named after the worksheets in the XLS file. We only need to use two of them; <code>worldmaps_epona.GDA</code> and <code>target_wps_epona.GDA</code>. Copy these files into your game's override directory along with <code>epona.tga</code> and "Epona's Realm" will become available in the toolset's dropdown menu.
 
Note that there will be a separate GDA file for each worksheet in the XLS file, named after the worksheets in the XLS file. We only need to use two of them; <code>worldmaps_epona.GDA</code> and <code>target_wps_epona.GDA</code>. Copy these files into your game's override directory along with <code>epona.tga</code> and "Epona's Realm" will become available in the toolset's dropdown menu.
 +
 +
=== Creating maps in photoshop to use in-game ===
 +
 +
----
 +
 +
 +
Here are some tutorials that can be used to make yourself a map in photoshop.
 +
 +
[http://www.jezelf.co.uk/tutorials_map01.htm Basic Map tutorial] - required as it is the basic stepping stone to make any map [Difficulty = Basic]
 +
 +
[[File:Map01_thumb.jpg‎]]
 +
 +
[http://www.jezelf.co.uk/tutorials_map02.htm Paper style/aged Map tutorial ] Style #1 [Difficulty = Beginner]
 +
 +
[[File:Map02_thumb.jpg]]
 +
 +
[http://www.jezelf.co.uk/tutorials_map04.htm Colored 2D Map Tutorial ] Style #2 [Difficulty = Beginner/Intermediate]
 +
 +
[[File:Map04_thumb.jpg‎]]
 +
 +
[http://www.jezelf.co.uk/tutorials_map05.htm Pseudo 3D Map Tutorial ] Style #3  [Difficulty = Intermeditate/Advanced]
 +
 +
[[File:Map05_thumb.jpg‎]]
 +
 +
 +
''
 +
All map making tutorials above are done courtesy of Jeremy Elford and [http://www.jezelf.co.uk/index.html www.Jezelf.co.uk]''
 +
 +
'''Other Valuable Map Making Resources'''
 +
 +
[http://www.profantasy.com/ Cartographer 3 + Addons -$] Simple easy to use map maker for those who don't have photoshop or the skills/knowledge to work it.
 +
 +
[http://cartographersguild.com/ Cartographers Guild Map Making Community  -Free] Great website if you are seeking other tutorials, inspiration, help, possibility of hiring someone to make you a map, and more!
 +
 +
[http://www.youtube.com/ZombieNirvana#p/u/18/KO4XZfaSAoA Youtube Tut series by ZombieNirvana -Free] Great Series of tutorials on youtube
  
 
== Creating a map and adding pins ==
 
== Creating a map and adding pins ==

Revision as of 09:32, 27 November 2009

Map objects are a way to allow the player to travel from area to area without having to follow a rigid path from one exit to the next. They're useful for representing large expanses of wide-open countryside, for example, or a city with various districts that the player can travel between freely but is too large to conveniently fit in a single area. Maps allow a world to be large without having to detail every little irrelevant place in it.

If you start by creating a new map resource within the designer toolkit, you'll quickly find that there is only a very limited pre-defined list of map images that are available for use. That's because map layouts are defined in a 2DA ("two-dimensional array"), a binary table of data that is used by the toolset to provide definitions but that is not itself editable from it. You may have encountered references to 2DAs when working with other objects. For example, the list of variables that an object's scripts can refer to is stored in a 2DA. This tutorial is going to assume that you've never worked with 2DAs themselves before. In a sense, this tutorial is as much a 2DA tutorial as it is a map tutorial.

Terminology

This tutorial makes use of a number of different three-letter acronyms and specific terms that may be troublesome to keep track of at first. Before we dive straight in, here's a cheat sheet that may prove useful:

  • 2DA - "two-dimensional array", the table of data we'll be editing. Note that a 2DA can be stored in a human-readable or machine-readable format, each of which has their own names. "2DA" is used to refer to the table as an abstract concept.
  • XLS - the file extension for an Excel spreadsheet.
  • Worksheet - tabbed panes within an Excel spreadsheet. Each Excel spreadsheet can contain multiple worksheets and each worksheet can represent one 2DA, so one spreadsheet can contain multiple 2DAs.
Worksheet tabs along the bottom of an Excel spreadsheet
  • GDA - The file extension for a binary file usable by the game. 2DAs that have been processed by the resource exporter will be stored in this form.
  • TGA - Targa graphics file extension. TGA graphic files are used to define the underlying appearance of the map itself.
  • M2DA - "Multiple 2DA". Previous BioWare games have made use of 2DAs, but the 2DAs used in Dragon Age use this new format instead. It allows several different 2DAs to be combined together and treated as a single 2DA by the game, which is very useful for adding new content to an existing 2DA.

The worldmaps.xls spreadsheet

See also worldmaps.xls.

If we're creating maps for a brand new module we could in theory start with a blank Excel spreadsheet and build the required 2DAs from scratch. It's much easier, however, to start with an existing copy of the relevant spreadsheet from another module and replace the values within it with our own.

The spreadsheet that contains all the 2DAs relevant to world maps is worldmaps.xls. Open it in Excel and you'll find that it contains, among other worksheets, the "worldmaps" worksheet.

The redaction will be removed when the game ships !!Note: mere moments after these screenshots were taken a NameStrRef column was added to allow localized map names. These screenshots will have to be redone anyway!!

This is the core 2DA that defines what maps are available in the Designer Toolset's "Map" dropdown menu.

First, some standard features that all 2DA worksheets will have:

  • The first row of the worksheet contains the labels of the columns. Don't change the names of columns or the game won't be able to recognize them.
  • The second row contains a keyword describing the data type of that column. Again, don't change this or the game will become confused by what it's seeing.
  • The first column contains ID numbers. Each row needs to have a unique ID number.

In the case of the worldmaps worksheet there are four columns that contain the data defining the map layout.

  • Label - The name that this map layout will be known by in the Designer Toolkit's dropdown menu. It's not seen by the player.
  • MAP - The filename of the .tga that defines the map's appearance, without the .tga extension.
  • TargetWpTable - The names of 2DAs that contains information about what waypoints the player appears at within areas accessible from the map. This is discussed in greater detail below.
  • TripsCounterTable - A table showing which trips should have random encounters. We won't be going into detail about this in this tutorial.

We'll need to add a new row to this table to describe the map area that we want to use in the toolset. For this example we have a map of a region named "Epona's Realm", in a file named epona.tga. We'll need to assign a unique number ID, which we'll arbitrarily set to 700 (using a high number like this makes it less likely to interfere with other people's additions in the future.). We'll call the target waypoint table "target_wps_epona" to fit with the naming convention of the other maps.

Worldmaps worksheet with epona added.png

In our hypothetical game module we've got three different cities that the player can reach via the world map; Dunland, Agrabia, and Serepta. They'll be represented by the areas dunland_main, agrabia_main, and serepta_main. The next thing we might want to do is create a 2DA that defines which waypoints you wind up in when you travel to each of these areas from each of the possible origin points. This isn't strictly necessary but can be used to make travel around the worldmap seem more realistic by having the player arrive at different waypoints depending on which direction they're arriving in an area from.

Again, a convenient starting place is an existing 2DA. This 2DA is another worksheet in worldmaps.xls that shows the target waypoints for a group of areas accessible from a city map in the game's single-player campaign:

Worldmaps worksheet target wps example.png

All of the source areas are listed in the second column, and then each column after that corresponds to a destination area for that source. Every source needs a destination column, so there should always be a number of columns equal to the number of sources plus two (the "ID" and "SourceLocation" columns). In this example, if you're in the "markets" area and then use the map to go to the "elven_alienage" area, you'll be placed at the waypoint "wmw_alienage_from_market". Since you can never travel from an area to that same area via the map the diagonal entries are left blank.

To repurpose this 2DA for Epona's Realm, first copy the worksheet and then rename it to "target_wps_epona". We'll only need three rows and three destination columns so delete the extras.

The geometry of these three cities is quite simple, they lie in an east-west row with Serepta to the west, Agrabia in the center, and Dunland to the east. We'll place waypoints in the eastern and western ends of agrabia_main's area layout to represent the player arriving from each of those directions.

So, the final version of the target_wps_epona worksheet will look like:

Worldmaps worksheet target wps epona.png


Using M2DAs to extend the game

There's one remaining complication to be addressed now. When you generate worldmaps.GDA it will include our new map ID 700, but it also includes the old maps with the IDs 1-5. Since the file is in the override directory, these rows override the existing maps with those ID numbers in the single player campaign. This isn't a problem right now since the data is identical but it could be a problem in the future; if BioWare releases an update that needs to change those original five maps, or if some other modder wants to add some maps of his own, only one version will "win" and the result could be a mess.

This can be overcome by splitting up a 2DA into different files that all get loaded by the game and are combined into one 2DA internally. These multi-part 2DA files are known as M2DAs, which stands for "multiple 2DA". The identity of M2DA files is kept track of via their "prefix", a string of text that all M2DAs being with. In the case of the worldmaps 2DA, the prefix is "worldmaps" (ie, the worldmaps.GDA file has the "worldmaps" prefix and no suffix, so it belongs to the "worldmaps" 2DA).

What we'll do now is split out the data relating to our "Epona's Realm" map into a separate M2DA file named worldmaps_epona.GDA. Simply rename the worksheet to "worldmaps_epona" and delete the first five rows of data entirely, leaving us with this:

Worldmaps epona worksheet.png

Now when the game encounters this 2DA in the override directory it will keep the data from the original worldmaps 2DA in memory and add the data from worldmaps_epona to it. If in the future some other modder builds on top of your work they can add further worldmap M2DAs, and if a patch comes out that updates the contents of the original 2DA your mod will incorporate it without needing to be updated.

Converting XLS files into GDA files

The game can't use Excel files directly, the 2DAs must first be converted into a "binarized" form. This is done by a command-line utility called ResourceBuilder.exe. Command-line utilities are not very user-friendly, however, so a more convenient "wrapper" is included in the form of another spreadsheet named 2daExporter.xls. 2daExporter.xls uses macros to run ResourceBuilder.exe with the appropriate command-line options. You'll need to provide 2daExporter.xls with the following parameters:

  • ResourceBuild Path: The path to ResourceBuilder.exe, which is installed by default in your Dragon Age directory under tools\ResourceBuild
  • 2DA Path: The source path of the XLS files to be exported.
  • Override Path: The path to the directory that the completed GDA files should be exported to. This doesn't have to be your actual override directory, you can move the files there manually after creating them if you prefer.

Note that 2daExporter.xls' macro can have trouble with paths that have spaces in them, so you may need to move your XLS files to a path without any. Likewise, you may not be able to send the output files directly to the override directory if there are spaces in its path.

Here's how we've set up 2daExporter.xls for converting our example:

2da exporter for worldmap tutorial.png

To convert worldmaps.xls into binary form, select it and click the "Export Selected" button. A command-line window should pop up briefly while ResourceBuilder runs and then the finished GDA files will be placed in the directory listed in "Override Path."

If you can't get 2daExporter.xls working, just run ExcelProcessor instead. You can learn more about ExcelProcessor by reading the 2DA section.

Note that there will be a separate GDA file for each worksheet in the XLS file, named after the worksheets in the XLS file. We only need to use two of them; worldmaps_epona.GDA and target_wps_epona.GDA. Copy these files into your game's override directory along with epona.tga and "Epona's Realm" will become available in the toolset's dropdown menu.

Creating maps in photoshop to use in-game



Here are some tutorials that can be used to make yourself a map in photoshop.

Basic Map tutorial - required as it is the basic stepping stone to make any map [Difficulty = Basic]

Map01 thumb.jpg

Paper style/aged Map tutorial Style #1 [Difficulty = Beginner]

Map02 thumb.jpg

Colored 2D Map Tutorial Style #2 [Difficulty = Beginner/Intermediate]

Map04 thumb.jpg

Pseudo 3D Map Tutorial Style #3 [Difficulty = Intermeditate/Advanced]

Map05 thumb.jpg


All map making tutorials above are done courtesy of Jeremy Elford and www.Jezelf.co.uk

Other Valuable Map Making Resources

Cartographer 3 + Addons -$ Simple easy to use map maker for those who don't have photoshop or the skills/knowledge to work it.

Cartographers Guild Map Making Community -Free Great website if you are seeking other tutorials, inspiration, help, possibility of hiring someone to make you a map, and more!

Youtube Tut series by ZombieNirvana -Free Great Series of tutorials on youtube

Creating a map and adding pins

Now we can at last see the map as an option in the drop-down menus of the toolset. Create a map and set the "Map" property to Epona's Realm, and the map should appear.

Worldmaps selecting Epona.png

There's not much to the map itself - its only configurable properties are Parent Map, Tag, and Map. To make the map useful beyond simply displaying a graphic we'll need to add map pins (icons representing destinations). You can also add "trails", which are a series of icons that you can make appear between different pins to mark the player's passage, but these are of lesser importance and can be left for later or omitted entirely.

To insert a pin, right-click on the map and select "insert pin" from the drop-down menu. The pointer will turn into a crosshair that you can click anywhere on the map to place a pin (pins can also be dragged around after creation so don't worry if you miss slightly). The pin will be added to the tree view to the left of the map and, when selected, you can view its properties in the object inspector.

Worldmaps placing a pin.png

The most important properties to set here are:

  • AreaTag - tells the game which area to take the player to when he clicks on this pin. Our Dunland pin will have this set to dunland_main.
  • Initial State - tells the game whether to display the pin and whether to make it clickable; you will often want to have pins on the map that only become available to the player at some point later in the game. We'll set Dunland to "grayed out" right now, since we'll want the player to know about its existence but not be able to go there right away.
  • Name - This name is shown to the player.
  • Pin Type - A list of icons that can be used for the pin. The list of appearances available can be added to in worldmaps.xls, you may have noticed the map_pin_images worksheet when you were editing it earlier.

Other properties you may wish to set include "Tooltip" (a longer description that will be shown to the player if he hovers the mouse pointer over the pin) and "Waypoint Override", which designates which waypoint in the pin's target area to send the player to when he clicks on it. This waypoint overrides the one set in target_wps_epona but has less fine-grained control available; it can be useful for testing purposes.

The "TerrainType" property is used to determine which group of random encounters to draw from. Setting up random encounters is a more advanced topic that we won't cover in this tutorial.

Worldmaps pins placed.png

Showing the player the map

Once you've got a map built for your module you'll need to tell the game how to use it. There are a number of wrapper functions in wrappers_h that you'll find useful for this:

void WR_SetWorldMapPrimary(object oMapId)

This function tells the game what the current default "world map" is. You'll want to set this to your default world map as part of the initial setup of your module, and if you have multiple different maps you'll need to call this function again later in the game to switch which one is active (for example in a plot script that triggers when the player completes a certain task or moves to a certain area).

void WR_SetWorldMapSecondary(object oMapId)

!!Need to find out more about this one.!!

void WR_SetWorldMapLocationStatus(object oLocation, int nStatusId, int bSuppressActiveFlash = FALSE)

oLocation is a map pin, nStatusId is an integer identifier for one of the status states (such as active, grayed out, destroyed), and the optional bSuppressActiveFlash flag tells the game to omit the visual highlighting that is usually shown around map pins that have had their status changed since the last time the player looked at the map.

void WR_SetWorldMapPlayerLocation(object oMap, object oLocation)

This marks the player's current location on the map.

Sending the player to the world map via an area transition

To set up an area transition placeable (such as a door) to send the player to the world map when an area transition is performed, set the placeable's PLC_AT_DEST_AREA_TAG variable to the string "world_map". This is a special string that's used to signal the placeable_core script's area-transition-handling code that it needs to show a map instead. When the placeable is triggered it will send an EVENT_TYPE_TRANSITION_TO_WORLD_MAP event to the module's event script.

The default module_core script doesn't handle this event so you'll need to add your own module event script to override this behavior. The module's event script should call the following core script functions:

 SetWorldMapGuiStatus(WM_GUI_STATUS_USE);
 OpenPrimaryWorldMap();

This displays the map to the player.

Activating and deactivating map pins

This can be done via scripting.

First get the world map pin object:

object oVillage = GetObjectByTag(WML_WOW_VILLAGE);

Then call the following to activate the pin:

WR_SetWorldMapLocationStatus(oVillage, WM_LOCATION_ACTIVE);

Area transitions using the default area transition core script can also automatically enable certain map pins when the player travels through them. The names of these pins are set in the area transition's variables.

Handling the player's map usage

If the proper destination areas and waypoints have been set in the map pins (and optionally the target_wps 2DA) the player's movement from one location to another should be handled automatically. However, the game does provide some hooks that allows further customization or non-standard actions to be performed.

When a player clicks on a map pin, the EVENT_TYPE_BEGIN_TRAVEL event is sent to the module script.

This event has the following parameters:

  • string sSource = GetEventString(ev, 0); // area tag for the source location (the area the player's leaving)
  • string sTarget = GetEventString(ev, 1); // area tag for the target location (the area the player's travelling to)
  • string sWPOverride = GetEventString(ev, 2); // the tag for the target waypoint override (the waypoint in the destination area that the player will appear at)
  • int nSourceTerrain = GetEventInteger(ev, 0); //The terrain type of the source location
  • int nTargetTerrain = GetEventInteger(ev, 1); //The terrain type of the target location - these two parameters are used in the main campaign's code for determining what sort of random encounters to generate, but that's handled entirely in scripting so you can use them for other purposes or ignore them completely if you prefer.
  • int nWorldMap = GetEventInteger(ev, 2);
  • object oSourceLocation = GetEventObject(ev, 0); // the map pin object representing the source location.

In the main Dragon Age campaign's module script, a large amount of complex code is triggered by the EVENT_TYPE_BEGIN_TRAVEL event. This code takes into account a lot of special-case situations that are relevant only to the particular plot and structure of the Dragon Age main campaign. But it is important to note one thing that is not done in the EVENT_TYPE_BEGIN_TRAVEL event; the actual call to UT_DoAreaTransition().

Instead, once you have finished doing whatever special-case coding and random encounter tests you choose to implement, you will need to store the destination that you're sending the player to in the module's variable table. Then call the WorldMapStartTravelling(); function to begin the map trail animation (the WorldMapStartTravelling function has optional parameters to insert a random encounter partway through the trip and to override the map pin the trail starts at).

The engine will send the EVENT_TYPE_WORLDMAP_PRETRANSITION event as it begins the map trail animation. This is where you want to call UT_DoAreaTransition(); the level will begin loading in the background as the map trail animation plays.

The following code is the most basic amount that you should need to put in your module script in order to implement area transitions via the world map:

case EVENT_TYPE_BEGIN_TRAVEL:
{
    string sTarget = GetEventString(ev, 1); // area tag target location
    string sWPOverride = GetEventString(ev, 2); // waypoint tag override
    //if you want to do any special-case code or random encounter handling, insert it here
    SetLocalString(GetModule(), "WM_STORED_AREA", sTarget); //store target area's tag to a local module variable
    SetLocalString(GetModule(), "WM_STORED_WP", sWPOverride); //store target waypoint tag
    WorldMapStartTravelling(); //initiate the map's travelling animation. The engine will send EVENT_TYPE_WORLDMAP_PRETRANSITION once it's started. 
}

case EVENT_TYPE_WORLDMAP_PRETRANSITION:
{
    string sArea = GetLocalString(GetModule(), "WM_STORED_AREA"); //retrieve the target area tag stored in EVENT_TYPE_BEGIN_TRAVEL
    string sWP = GetLocalString(GetModule(), "WM_STORED_WP"); //retrieve the target waypoint tag
    UT_DoAreaTransition(sArea, sWP); //execute the area transition to that target.
    break;
}

There is also a EVENT_TYPE_WORLDMAP_POSTTRANSITION event. In the Dragon Age main campaign it is used only to trigger certain cutscenes that play as a result of world travel.


Other map-related events

The EVENT_TYPE_WORLD_MAP_CLOSED is sent to the module script when the world map is closed. It has only one parameter, an integer flag that indicates whether the map was closed due to cancel being selected or due to the player traveling to a new destination.