So now you can create an entire scenario, which is a good thing to know how to do. But what if you don't want to go that far? There are some simple changes you can make to the game via plugins or even easier means.
The easiest way to change the way TraderMissions works is to mess with its data files. If you wanted to use a different font, for example, you could simply copy over the original font bitmap where the game is installed. The downside of that is that it's rather destructive. Fortunately, there's an easier way. By default, TraderMissions looks in three directories when asked to get a file:
(Where $TMDIR is the directory that TraderMissions is installed in)
In the event that TM finds more than one file with the same name, it will use the last one found. So you can override any image or game data that you want by simply putting a file in your .tradermissions directory or adding a directory to the options to search (though that approach won't work for everything; some items are loaded before these options take effect, such as the font).
If you want to try this out yourself, feel free! TraderMissions ships with a file called smallFont.png - you can find it in the images directory where you installed the game. Copy this file into your .tradermissions directory, and then rename it smallerFont.png. When TM goes to load smallerFont.png as its font, it will find this one last and use it. The game will look vastly different! Please note that while a lot of care has gone into making sure that all fonts are at least presentable with the game, only the default one has actually been tested. Other fonts might have... interesting effects on dialogs.
Of course, there's only so much you can do with the method above. You can change all the graphics you want, but the most you can do to the datafiles is to replace them with an entirely new datafile; this is not exactly the easiest way to make modifications.
Plugins, typically with a .TML extention, are used to make major modifications to a game. A player loads a plugin to a scenario by choosing the scenario, then the plugin. The plugin is read in after the scenario, but aside from that fact it's as though the plugin was part of the main scenario. Plugins work by overriding the values of the objects in the main scenario. Knowing how overrides work is an important part of writing a plugin:
It was mentioned in the Field section that when you specify the value for a field, you're overriding what was initially there. The first time it's done, you override the default value (0 for numbers, an empty string for strings) and from then on you override whatever the old value was.
For instance, say you wanted to write a plugin that gives the player a lot of money. Here it is, in its entirety:
# Greed Plugin # Need money, and fast? Here you go! gamestate <gamestate> { field money = 1000000; }
Recall that, if the parser encounters an object with the same name as an object that already exists ("gamestate", in our sample plugin here), it will modify that object instead of creating a new one.
The aspiring millionare would add the scenario to be played, and then add the "Greed Plugin". When the gamestate object is initially created, the money field will be given its default value (0). Then, when the 'field money' line is parsed, the default value will be overridden by whatever the scenario says the money ought to be. Finally, the greed plugin would be loaded, and the money field would be re-set to 1000000.
(To use this plugin, simply save it in your .tradermissions directory. The filename doesn't matter, so long as it has a .tml extention)
Field overrides are simple and allow you to change a number of things: from the names and locations of planets to the amount of firepower that a weapon dishes out. But there's a lot we're not able to touch with field overrides. As you might expect, children can be overriten as well, but in a different way.
The Child section of Syntax also mentioned children, but didn't mention how the overrides work. It's simple: when you do a object.add, it adds whatever object you say to the list of children. So, for instance, suppose this was the scenario:
Holly <test> { field test = "I'm the original Holly"; child dummychild1.add Adam; child dummychild1.add Beth; }
And this the plugin:
Holly <test> { child dummychild1.add Adam; }
The resulting object would be this:
Holly <test> { field test = "I'm the original Holly"; field number = 0.000000; list listtest = {}; child dummychild1.add Adam; child dummychild1.add Beth; child dummychild1.add Adam; }
The output comes straight from tmdverify, so it of course includes items we didn't mention, such as listtest and the number field. But the dummychild1 child has three children now: Adam, Beth, and Adam again, in that order.
Just like the syntax sections, we'll show an example of a plugin you can make yourself. This is a plugin for the tutorial, and it adds a new sector to the universe!
# Deep Space # #(A plugin for 'How to Play TraderMissions') # This plugin adds a new sector, entitled "Deep Space" DeepSpace <sector> { field mapx = 0.0; field mapy = -100.0; field title = "Deep Space"; field description = "Deep Space is a vast empty area of absolute "+ "nothingness; A dead end in spacetime."; child owner.add Humans; child links.add Sol; } OurMap <map> { child sectors.add DeepSpace; } Sol <sector> { child links.add DeepSpace; }
The plugin is actually very simple; it makes a new sector, and then adds on to the sectors list for the map and the links list for the Sol sector. As you can tell, using overrides to add on to a child can be fairly powerful.
But not powerful enough, of course. What if you actually want to change something? For instance, give the player a shiny new ship upon the start of the game instead of the dusty beaten-up one? Surprisingly enough, this can be done by adding on to children as well. There are some children that only expect one child, and if more than one is specified, they will take the last one on the list. You may have noticed the similarity between this and the location of images by the game; this is intentional. When TM expects one object and gets many, it will always choose the last given to it. I refer to this as:
So how do we exploit this punningly-named principle? All you need to do is to add on to one of these children in an object you want to modify. Note that it only works for some children: these are emphasized in the reference for each object. We'll use the activeShip child of gamestate as an example:
# Megaship plugin #(A plugin for 'How to Play TraderMissions') # You know how you always die at the end of the tutorial? No more! uberCraft <ship> { field maxrof = 0.15; field acceleration = 75.0; field angular = 250; field jumptime = 1; field traveltime = 1; field maxfuel = 10000; field maxspeed = 300; field cargospace = 700; field hardpoints = 50; field mass = 500; field shields = 10000; field regen = 100; field title = "Ultimate Shuttlecraft"; child image.add(colonyShuttleImg <image> { field filename = "shuttleGreen.png"; }); } frozenCraft <frozenship> { child ship.add uberCraft; field cost = 10000; field x = 5.0; field y = 5.0; field fuel = 10000; field angle = 0; field speedx = 0; field speedy = 0; child addons.add LaserAddon; child addons.add LaserAddon; child addons.add LaserAddon; child addons.add MissileLauncherAddon; child addons.add MissileAddon; child addons.add MissileAddon; child addons.add MissileAddon; child addons.add MissileAddon; child addons.add MissileAddon; child addons.add MissileAddon; child addons.add MissileAddon; child addons.add MissileAddon; child addons.add MissileAddon; child addons.add MissileAddon; } gamestate <gamestate> { child activeship.add frozenCraft; }
Here we go through all the trouble to create a fancy new ship and load it up with armnaments, and it turns out that it only requires three lines (those last three, everything else is just setup) to actually make the change. Overriding via the Principle of Last Surprise is pretty easy that way.