Artemis Tutorials

Timing Artemis Mission Scripting 101 Part Three

This is a three part tutorial written for Artemis 1.702

Writing missions for the Artemis Spaceship Bridge Simulator is much different from writing the usual fan fiction. There is a heavy dose of Mary Sue, since the player ship drives the action, and you can never count on the players following your story.
In our first tutorial we laid out an exciting playfield for open action, pitting our protagonist against some predictable enemies. In our second tutorial we created an actual story with an impossible outcome that only cheating could overcome.

For this tutorial we're going to create three mission scripts, each a simple example of an important building block that can be strung together for more ambitious missions.

All story telling is about characters, events and timing. Characters move through the events in a certain structure, one thing happening after another, sometimes the end is told first, sometime we end in the middle. With Artemis each mission has the chance of being told in any order.

This part of the tutorial will be about managing timing.

The Artemis simulator uses "timers" to keep track of when things will happen. Timers can be set to begin in the "start" block, or in "events" that are set off when conditions are met. Setting timers in the "start" block is a good way to ensure important story elements are exposed to the player crew at the same time every time a mission is played. Setting timers inside events with conditions can infleunce other events, heighten drama, give the crew time to think about their next move before there are consequences and help push them in any direction.
In order to set up a compelling adventure we need something for a storyline. It doesn't need to be lengthy or complicated, but you'll usually want to be more than "go there, shoot that". Artemis already has a competent "Invasion" mode if you just want to fly around blowing up aliens.

For the purposes of this tutorial we are going to borrow from a famous scenario that is short, to the point and always ends with a bang.

As a reminder when creating a new mission you need to create a new folder in the /Program Files/Artemis/dat/Missions folder. The new folder name must start with MISS_, contain no spaces and should give a clear, but abbreviated, idea about the mission name. As an example the "Module 3 bases" folder is called "MISS_Module_3_bases". Inside the folder you only need one file, the XML mission that must be similarly named, but end with dot xml, as opposed to dot doc or dot txt.
There are many text editors that you can choose from, I personally prefer BBEdit, and the Artemis community has the fantastic Artemis Mission Editor.

Folder: MISS_AJAX_tutorial_3
XML File: MISS_AJAX_tutorial_3.xml
Download this tutorial mission as zip file.

We still recommend that you don't get in the habit of editing the mission files while they are in the Mission folder itself, instead work on the files somewhere else and then copy them into the Mission folder for testing. This is just good workflow habit.

Artemis missions are structured as XML. Timers are self closing XML tags.

<!---this will be our first timer -->
<set_timer name="distressSignal_timer" seconds="60"/-->

Now we have a timer counting down. The "time" tag has two properties, name and seconds. I try to keep a consistent naming convention so things can be told apart at a glance.

We're going to use our AJAX tutorial 2 as the starting point for experimenting with timers. We want a nice opening title, our player ship, what resources it should have at start, a friendly space station and our neutral ship. We want to keep our neutral ship from wandering off, so clear the AI stack and tell it to stay in one place. We also don't want a mischievous Comm officer accidentally ordering our "crippled" nuetral to head anywhere.
After that we'll drop in a nebula for color, a minefield to give our Helm something to think about and an asteroid field for fun.

<!-- mission_data is the big wrapper for all the parts of a mission -->
<mission version="1.22">
<!--- COMMENT: this is where we specify what appears when the mission first starts -->
<!--- have a nice big mission title appear on the main screen -->
<big_message title="AJAX tutorial 3" subtitle1="written by Michael Sweeney"/>

<!--- add the player ship named "AJAX" to the exact center -->
<!--- this is just a training cruise, after all... -->
<create type ="player" x="50000" y="0" z="50000" name="SS AJAX"/>
<set_object_property name="SS AJAX" property="countNuke" value="0"/>
<set_object_property name="SS AJAX" property="countHoming" value="2"/>
<set_object_property name="SS AJAX" property="countMine" value="0"/>
<set_object_property name="SS AJAX" property="countECM" value="2"/>

<!--- add space station "OUTPOST ALPHA" to the center right -->
<create type ="station" raceKeys="friendly" hullKeys="base" x="25000" y="0" z="50000" name="OUTPOST ALPHA"/>

<!--- add a friendly spaceship to the center left -->
<create type ="neutral" raceKeys="friendly" hullKeys="cargo" x="75000" y="0" z="55500" name="TR80" angle="0"/>
<set_object_property name="TR80" property="willAcceptCommsOrders" value="0" />
<clear_ai name="TR80"/>
<add_ai name="TR80" type="DIR_THROTTLE" value1="0" value2="5" />

<!--- add a nebula to the top left -->
<create type ="nebulas" count="10" startX="75000" startY="0" startZ="25000" radius ="5000" startAngle="0" endAngle="360" randomRange="2000" randomSeed="1"/>

<!--- add a mine field that seperates the bad guys from our player -->
<create type ="mines" count="20" startX="65000" startY="0" startZ="25000" endX="65000" endY="0" endZ="75000"/>

<!--- add an asteroid field that seperates the our player from the station -->
<create type ="asteroids" count="20" startX="35000" startY="0" startZ="25000" endX="35000" endY="0" endZ="75000"/>

<!---this will be our first timer -->
<set_timer name="distressSignal_timer" seconds="30"/>
<set_timer name="admonishDistress_timer" seconds="90"/>

<!-- ******************************************************************************************** -->
<!-- events -->


With our playfield defined we can start adding our timers.

We have a basic story we want to encourage the player crew to follow (to their doom). In the previous tutorial we notified the player crew of our ship in distress when they left small sphere we created around them. This requires the player crew to take some action and actually move a certain distance. Since we can't count on a player crew to do anything, as they may option to just sit there, we set a timer in the "start" block so our distress signal will appear at the same time every time this mission is played.
Having a timer running is great, but it will run out eventually and does nothing on its own. We need to update our first event to accommodate the timer.

We still need the "distressSignal" variable to be set to "1" so this event will be ignored after and not fire off over and over forever. This means that we could set "distressSignal" to 0 and run our "distressSignal_timer" again to have this event block be revealed to the player again in the future.

When the mission started the neutral cargo ship was placed on the left center of the minefield. We gave it a direction of 0 and throttle of 0, so it wouldn't be moving.
This is a little boring, and might be seen as an obvious set up by a justifiable suspicious player crew.

We will change the location and "DIR_THROTTLE" for the neutral cargo ship to value1 of 0 and value2 of 5. This will make the neutral cargo ship fly straight north at high speed.

Obviously we don't want to ship to be flying away from the player crew after it has sent the distress signal, so we'll update the "DIR_THROTTLE" for the neutral cargo ship to value1 of 0 and value2 of 0 in the same event as the distress signal.

<!--- our first event, get the player crews attention -->
<if_variable name="distressSignal" comparator="!=" value="1"/>
<if_timer_finished name="distressSignal_timer"/>

<add_ai name="TR80" type="DIR_THROTTLE" value1="0" value2="0" />
<incoming_comms_text from="TR80">
This is the Transport 80 ARGUS! 19 light years out of Altair Six!^
We have struck a gravitic mine and have lost all power!^
Our hull is penetrated and we have sustained many casualties!^
Our life support system is failing!
<warning_popup_message message="ALERT! Distress signal from TR80!" consoles="M"/>
<set_variable name="distressSignal" value="1"/>

We don't need to change the events that fire off as the player ship moves through our minefield, and only a small change to our conditions about how our cargo ship is revealed as a trap. We will change the fatal blow for our crew from them trying to escape, moving outside of a sphere, to a very short timer. This ensures that the crew doesn't accidentally survive without knowing how to cheat the mission.

<!--- our fifth event, what happens when we get in range of TR80? ;) -->
<if_variable name="distressSignal2" comparator="!=" value="1"/>
<if_distance name1="SS AJAX" name2="TR80" comparator="<" value="940"/>
<incoming_comms_text from="TR80">
Terran Cruiser?!^
Are you there?
<warning_popup_message message="ALERT! TR80 SIGNAL LOST!" consoles="M"/>
<warning_popup_message message="ALERT! TR80 SIGNAL LOST!" consoles="C"/>

<!--- remove neutral ship -->
<destroy name="TR80"/>

<warning_popup_message message="ALERT! ENEMY SHIPS DETECTED!" consoles="M"/>
<!--- mixing up our franchise references a little? -->
<warning_popup_message message="IT'S A TRAP!" consoles="M"/>

<!--- replace neutral ship with enemy ship -->
<create type ="enemy" raceKeys="Kralien enemy" name="KR01" hullKeys="large" x="75000" y="0" z="50000" angle="0" fleetnumber="1"/>
<clear_ai name="KR01"/>
<add_ai type="CHASE_PLAYER" name="KR01" value1="5000" value2="3000"/>
<add_ai type="CHASE_ANGER" name="KR01"/>

<!--- add two enemy ships near AJAX -->
<create type ="enemy" raceKeys="Kralien enemy" name="KR02" hullKeys="medium" x="75000" y="0" z="50000" angle="90" fleetnumber="1"/>
<set_relative_position name1="SS AJAX" name2="KR02" distance="940" angle="165"/>
<clear_ai name="KR02"/>
<add_ai type="CHASE_PLAYER" name="KR02" value1="5000" value2="3000"/>
<add_ai type="CHASE_ANGER" name="KR02"/>

<create type ="enemy" raceKeys="Kralien enemy" name="KR03" hullKeys="medium" x="75000" y="0" z="50100" angle="90" fleetnumber="1"/>
<set_relative_position name1="SS AJAX" name2="KR03" distance="940" angle="0"/>
<clear_ai name="KR03"/>
<add_ai type="CHASE_PLAYER" name="KR03" value1="5000" value2="3000"/>
<add_ai type="CHASE_ANGER" name="KR03"/>

<!-- exagerate damage to player ship for drama -->
<set_object_property name="SS AJAX" property="shieldStateFront" value="26"/>
<set_object_property name="SS AJAX" property="shieldStateBack" value="19"/>
<set_object_property name="SS AJAX" property="energy" value="272"/>
<warning_popup_message message="ALERT: DIRECT HIT!" consoles="M"/>
<warning_popup_message message="ALERT: SHIELDS FAILING!" consoles="M"/>

<!--- kill off damage control teams so ship cannot repair -->
<set_damcon_members team_index="0" value="0"/>
<set_damcon_members team_index="1" value="0"/>
<set_damcon_members team_index="2" value="0"/>
<set_damcon_members team_index="3" value="0"/>

<warning_popup_message message="ALERT: DAMCOM TEAMS KILLED!" consoles="M"/>

<!-- set difficulty level to legendary ;) -->
<set_difficulty_level value="10"/>

<!-- set no escape -->
<set_timer name="noEscape_timer" seconds="30"/>

<set_variable name="distressSignal2" value="1"/>

<!--- our sixth event, no way to escape? -->
<if_variable name="distressSignal2" comparator="=" value="1"/>
<if_variable name="noEscape" comparator="!=" value="1"/>
<if_variable name="anomalyDrop" comparator="!=" value="1"/>
<if_timer_finished name="noEscape_timer"/>
<set_variable name="noEscape" value="1"/>

<!-- leave just enough power to limp away -->
<set_object_property name="SS AJAX" property="energy" value="47"/>

<warning_popup_message message="ALERT: DIRECT HIT!" consoles="M"/>
<warning_popup_message message="ALERT: WARP DAMAGED!" consoles="M"/>
<warning_popup_message message="ALERT: IMPULSE DAMAGED!" consoles="M"/>
<warning_popup_message message="ALERT: SHIELDS DAMAGED!" consoles="M"/>

<!--- set damage to player ship for unwinnable odds -->
<set_player_grid_damage systemType="systemDamageTactical" countFrom="left" index="0" value="1"/>
<set_player_grid_damage systemType="systemDamageTactical" countFrom="left" index="1" value="1"/>
<set_player_grid_damage systemType="systemDamageTactical" countFrom="left" index="2" value="1"/>
<set_player_grid_damage systemType="systemDamageTactical" countFrom="left" index="3" value="1"/>
<set_player_grid_damage systemType="systemDamageImpulse" countFrom="left" index="0" value="1"/>
<set_player_grid_damage systemType="systemDamageImpulse" countFrom="left" index="1" value="1"/>
<set_player_grid_damage systemType="systemDamageImpulse" countFrom="left" index="2" value="1"/>
<set_player_grid_damage systemType="systemDamageImpulse" countFrom="left" index="3" value="1"/>
<set_player_grid_damage systemType="systemWarp" countFrom="left" index="0" value="1"/>
<set_player_grid_damage systemType="systemWarp" countFrom="left" index="1" value="1"/>
<set_player_grid_damage systemType="systemWarp" countFrom="left" index="2" value="1"/>
<set_player_grid_damage systemType="systemWarp" countFrom="left" index="3" value="1"/>
<set_player_grid_damage systemType="systemTurning" countFrom="left" index="0" value="1"/>
<set_object_property name="SS AJAX" property="shieldStateFront" value="13"/>
<set_object_property name="SS AJAX" property="shieldStateBack" value="8"/>
<set_object_property name="SS AJAX" property="totalCoolant" value="5"/>


Next, we'll change the event that has our space station chastise our crew for ignoring the distress signal to a repeating alert. This should pester our crew into action if the chose to explore the playfield instead. We already snuck the "set_timer" into the "start" block.

<!--- our eighth event, just in case the player ignores the distress signal -->
<if_variable name="distressSignal2" comparator="!=" value="1"/>
<if_timer_finished name="admonishDistress_timer"/>

<incoming_comms_text from="OUTPOST ALPHA">
We received a distress signal?^
Proceed to help vessel in distress!
<warning_popup_message message="ORDERS: Proceed to help TR80!" consoles="M"/>

<set_timer name="admonishDistress_timer" seconds="60"/>

We also need to add a new event block with timer to our "game over" conditions so our player crew can see the homage to our stories inspiration.

<!--- our nineth event, fail, end the game -->
<if_variable name="distressSignal2" comparator="=" value="1"/>
<if_variable name="noEscape" comparator="=" value="1"/>
<if_variable name="gameOver" comparator="!=" value="1"/>
<big_message title="Prayer, Mr. Saavik..." subtitle1="Klingons don't take prisoners."/>
<warning_popup_message message="Your ship is dead in space." consoles="M"/>
<set_variable name="gameOver" value="1"/>

<set_timer name="gameOver_timer" seconds="15"/>


<!--- our tenth event, end the game -->
<if_variable name="distressSignal2" comparator="=" value="1"/>
<if_variable name="gameOver" comparator="=" value="1"/>
<if_timer_finished name="gameOver_timer"/>

<big_message title="Game Over" subtitle1=""/>
<warning_popup_message message="Game Over" consoles="M"/>



Lastly, we need to update our cheat so it obeys the new game over timer.

<!-- our twelfth event, must get that simulator checked? ;) -->
<if_variable name="distressSignal2" comparator="=" value="1"/>
<if_variable name="gameOver" comparator="!=" value="1"/>
<if_fleet_count fleetnumber="1" comparator="<=" value="0"/>
<big_message title="You won? ..." subtitle1="Enjoy your smirk."/>
<set_variable name="gameOver" value="1"/>

<set_timer name="gameOver_timer" seconds="15"/>


With just a little polish we have an exciting adventure that should encourage our players to trust their gamemaster much less, as is appropriate.

Timers are obviously quite useful, and we have only scratched the surface. We've seen creative use of switching one kind of object for another and making bad guys appear. With creative use of events, timers and create tags you could have a minefield that contracts around a player, or an asteroid field that moves across the playfield!
One thing you can't do in version 1.702 is change the time amounts as variables. This means you can't have a timer that increases itself after each pass, but it can be faked with creative scripting.

I hope this gives you a firm understanding of the possibilities!

Download the tutorial mission folder.

Safe journey!

Posted: Thursday, May 30, 2013

Past Articles - All:
Timing Artemis Mission Scripting 101 Part Three - Thursday, May 30, 2013
Events Artemis Mission Scripting 101 Part Two - Monday, April 29, 2013
SS AJAX - tutorial 2 - Monday, April 29, 2013
SS AJAX - Milk Run - Friday, April 26, 2013
Characters - Artemis Mission Scripting 101 - Part One - Monday, April 22, 2013
SS AJAX - tutorial 1 - Monday, April 22, 2013
What is Artemis? - Friday, April 19, 2013
A Day Full of Fail - Friday, July 20, 2012
A Table Top Factory - Thursday, July 19, 2012
Building More Things... - Wednesday, July 18, 2012
Our Adventure Begins... - Tuesday, July 17, 2012

Categories: Artemis Tutorials | Artemis Missions | 3D Printer |