Anyways, since many people probably don't know about this: there are tutorials and guidelines for the Mission Director leftover from X3:R. This topic holds the X3:R Mission Director questions/answers. Some important basics of MD usage are explained there and there's a link to a Mission Director download package. While the XML schema in there is basically no longer valid for TC (you have to extract your own from the TC .cat/.dat files), there's a nice PDF file there, the Mission Director guide, which contains some useful information. Some of it is no longer valid (there's no special menu for viewing MD states, for example, nor is there any BBS functionality), but it's still a good start.
What has changed very much from the beta MD in X3:R is the massive use of libraries in the mission scripts that come together with TC. The reason is probably that, since all the mission content from TC is written in the MD (including all the plot missions!), some modularity was required. Therefore, although we don't get any new MD tutorial included with TC, we do get a lot of sample scripts plus a lot of reusable libraries that we can use in our missions. This tutorial will focus on the OBS library (the Opponent Balancing System, as it's innocently called), which is basically the main "foe-spawner library" in the set.
I'm assuming you have extracted the entire "director" folder from the game files (for information on how to do that, consult the sticky topics). I will be referring from now on to contents of files within that directory.
The first thing to notice is that the files have a certain hierarchy built upon them. The general idea is this: files without numbers are the most generic libraries (OBS = Opponent Balancing System, SRST = Set Random Ship Type and so on, the descriptions are in the files themselves), files starting with 0. are the "generic mission [part] templates" - they are used as building blocks for constructing real missions. Files starting with 1. (currently only one of them) describe generic mission sets (here, the corporation missions), files starting with 2. - the real missions or plotlines, files starting with 3. - setup procedures for the missions.
Now, if we open a random "level 2" mission, for example "2.145 Scan Asteroids.xml", we will notice the main cue is itself defined as a library cue:
Code: Select all
<cue name="L2M145" library="1" check="cancel" comment="Root Cue for this Mission / Holds all variables" >
The comment in the abovementioned MD file is quite informative, since it shows us a characteristic feature of hierarchical MD code - lots of information is now kept in variables that get passed down to lower-level library scripts. This has two uses - we might want to recycle the same variable for various library files (for example, an opponent's race), or we want a top-level variable to be accessible via a library script.
This second concept requires some detailed explanation. Let's say we have some cue:
Code: Select all
<cue name="A01 Foobar">...
Code: Select all
<cue ref="ALIB01"> ...
Code: Select all
<set_value name="A01 Foobar.SomeVar" ... />
Code: Select all
<cue ref="ALIB01">
<param name="Cue" value="A01 Foobar">
...
</cue>
Now, a case study. As we know, the TerraCorp (and OTAS, and maybe other) escort missions are bugged - they spawn friendly pirates. To check why this happens, we will have to trace the entire library call structure down to the very level of the OBS, which spawns the ship.
First of all, we look at the "3.06 Corporation Missions.xml" file. It does nothing interesting, just call the appropriate corporation missions, with no parameters set, so there's certainly nothing wrong here:
Code: Select all
<cue ref="L2M41" comment="Terracorp"/>
Code: Select all
<cue ref="COM01">...</cue>
<cue ref="L0M19">...</cue>
Code: Select all
<content reference="L0M19" name="Escort Convoy" description="Escort some ships to a destination."/>
Code: Select all
<cue name="L0M19 ref OBS">
<cues>
<cue ref="OBS">
...
Code: Select all
<param name="OBS Cancel Cue" value="L0M19 ref OBS" comment="The cue which is canceled after the OBS finishes"/>
<param name="OBS Fleet Group Name" value="Enemies" comment="The group name where all main ships are saved too"/>
<param name="OBS Support Fleet Group Name" value="Enemy Support" comment="The group name where all support ships are saved too"/>
<param name="OBS Mother Ship Group Name" value="Enemy Carriers" comment="The group name where all ships with owned ships are saved too"/>
<param name="OBSPosition" value="10km" comment="how far away should the OBS ships be from FleetPositionObject"/>
<param name="OBSFleetPositionObject" value="{group.object.random@{param@GroupName}}" comment="The object which will provide the location information"/>
<param name="OBSSector" value="{group.object.random@{param@GroupName}}" comment="The sector where the ships will spawn if OBSFleetPositionObject not set"/>
To solve the mystery, we have to remember how the parameters work. They are a kind of "local variable definitions" - ones that either have to be passed explicitly to the library script or defined somewhere "up the ladder". In other words - if there is a parameter defined in a top-level library cue and that cue calls a lower level library cue, the parameter is passed on by default. The TerraCorp mission itself does not provide parameters for the OBS script, but it provides some parameters for the L0M19 script, which passes them on to the OBS script.
Indeed, if we look up, we will find out that most OBS parameters are reintroduced as parameters to L0M19 and they are filled out by the call to L0M19 in the TerraCorp mission script. So, why are the pirates friendly?
A good idea is to try to compare the broken call in the TerraCorp mission with one that works. Let's take the station defense script, L0M35. After comparing the parameter lists passed to OBS, we find our possible culprits:
Code: Select all
<param name="OBSRaceSetup" value="1"/>
<param name="OBSFleetRelation" value="-1"/>
Code: Select all
<param name="OBSRaceSetup" type="boolean" description="If pilot race is neutral/friend/enemy then add pilots and race names to ships when set"/>
<param name="OBSFleetRelation" type="number" description="-1,0,1 OBS fleet relation to the player"/>
So, how can we fix it? We have to add the OBSRaceSetup and OBSFleetRelation as paramters to L0M19 first, to have them passed on. Alternatively, we could just call OBS from within L0M19 with those two extra parameters. If we decided for the first approach, we have to now put the extra parameters to the L0M19 call from the TerraCorp and the OTAS mission scripts. If we do it on the level of L0M19, we just need to do the change once. The question to ask here is: will we ever need different functionality? Do we want escort missions to spawn non-hostile fleets? Since the answer is probably "no", adding the functionality to L0M19 is probably a better idea - future missions utilizing this library won't have to remember about the two extra parameters to pass.
This concludes the tutorial - I hope I've illustrated some points about MD script file design and ways of using provided code. Hopefully this can help any potential mission writers out there.