Sign up Calendar Latest Topics
 
 
 


Reply
  Author   Comment  
HaydenBarca

Registered:
Posts: 127
Reply with quote  #1 
Hello team,

After writing a script for the TSN Armada Contest and learning a lot (thanks to all here for the answers to questions from past to present), I started looking at some of the other scripts from older versions that aren't working any more.  My first step was Whale Of A Good Time from Armada IV by Paul Rockwell.  In looking at 1) someone else's scripting and 2) an older version of Artemis, I realized that there are multiple ways to do the same thing (or at least under 2.7.5 there is).  So I wanted to reach out to the community to see what you see as best practices for mission scripting.

Here's a starter list and I'll update with additional ones that folks contribute:
  • Use Artemis Mission Editor program, it makes everything much easier. https://artemis.forumchitchat.com/post?id=8115862&trail=120
  • Use Artemis Mission Editor's "Find Potential Problems" feature under Tools > Analyze menu. Just understand that everything flagged there isn't necessarily a show-stopper, just be sure you're comfortable with it.
  • Use Artemis Mission Editor event folders to group together related events and make larger projects easier to navigate and read.
  • When in doubt, check the Artemis Wiki.  It's the best resource for scripting documentation I've found:  http://artemiswiki.pbworks.com/w/page/51088806/Mission%20Scripting
  • Learn to use the Debugging Mode built into Artemis.  While the server is running press F7 to cycle through different debugging views.  This lets you see: 1. Latest commands executed by the script, 2. Status of all scripted timers, 3. Status of all scripted variables, 4. Information about the latest scripted keypresses from consoles, 5. Brain stack for the Science console's selected NPC ship, with its current mission, 6. Brain stack for the Science console's selected monster, with its current mission.  If there are too many variables to fit on the screen, temporarily move them to the top of the Start block and they will appear at the start of the debug variables view.
  • Use script comments to help you read your scripts.  Also, it will help others to keep your scripts current if you fade away (so that your legend will live on).
  • Plan your adventure and make sure there's something for every station to do in each phase of the mission.  If there's a station that's not needed (e.g. "no Weapons for this one"), specify that in the mission description so there aren't any boring surprises.
  • When creating scripts, use Hull ID to specify the ship type, rather than Race and Hull Keys (the older method).  This let's you be very specific and not run into ambiguities like different Arvonian carriers.  The exception might be if you want to randomly generate a ship from a race and any hull will work.
  • Specify the player ship using player_slot="0" (for example) rather than a name if you can help it.  This lets players specify a custom name and everything still works.  The exception is if you need to detect if the players have tagged a monster, which only accepts name (not player slot).
  • When you have incoming messages that should only happen once, create a unique "message check variable" for that message (integer works fine).  For instance, create "Msg_ArvonianDistressCall" or "Msg_Intro1" and set them to 0 in the Start block.  Then in the event, check to see if they're still zero (haven't played), play them, and set the variable to 1 (have played).  This prevents messages from spamming the ship and the "Msg_" prefix makes it clear what that variable is for.
  • Initiate all variables in your start block.  If it's a flag for arbitrary states (e.g. 0 = docked, 1 = near base, 2 = in deep space, 3 = in nebula, etc.), comment that in the Start block so you can refer back to it and use it consistently throughout the rest of the script.
  • If you're going to use the shuttle for a mission, specify the name of the shuttle before the player ship is created (<set_player_carried_type ... /> ).  Then clear the fighter inventory at a friendly base (<clear_player_station_carried ... /> ) and fill it with replacement shuttles of the same name (<set_player_station_carried ... /> ).  Unless you want the players to only have one shot at it in which case losing the shuttle (destroyed when not close to the player ship) should end play a ending message and then end the mission.
  • Provide a satisfying ending to your mission (or multiple endings) -- don't just end the mission abruptly.  You can use <big_message ... /> if you're sure everyone can see the main screen, or a warning popup message (<warning_popup_message ... />, if it needs to display on each console (such as for online play).  Tell them how they did, set a timer for 15-30 seconds, and then trigger the End Mission (<end_mission /> ).

What else do folks see as best practices to make mission scripting a little bit easier?  This is such a fun part of the game, but can be intimidating for others to join us, so I'm thinking about how to make it easier.
ryleyra

Registered:
Posts: 2,960
Reply with quote  #2 
This is an excellent idea. I'll try to contribute once I have some spare time, but I'll mention only a few things for now.

I am working on a Tutorial on the wiki. It isn't linked from any other pages because it's only one page and has been half finished for years, but it can be accessed directly: http://artemiswiki.pbworks.com/w/page/107601084/Introduction

I'll add that the mission scripting section is currently being maintained by Dave Thaler and he is doing an incredible job of keeping it up to date. I try to contribute bits and pieces where I can, but in many cases what's posted here is more complete than the official documentation -- but it's also subject to some quesswork, although we try to test whatever we can. So it may not strictly match the documentation.

Also, I believe that in previous versions variables appeared in alphabetical order, although I may be remembering wrong. In any case, your advice to declare your variables in order in which you want them to be displayed in a good one. I've used creative naming in the past, but you always want the variables you are watching to be visible. And you can change this order to debug a problem section of code.

As a consequence, pre-defining your variables will also ensure they are in the format you want them to be in, integer or float. A "declaration block" where you define all your variables is a good idea. Note the Mission Editor won't do this for you.

ryleyra

Registered:
Posts: 2,960
Reply with quote  #3 
Oh, and you got it backwards. HullId was the original way to specify ships, raceKeys and hullKeys were added later to add more flexibility. The problem with using hullId is that if the hullIds in vesselData ever change (or you use a mod like the Star Trek mod) your script will no longer summon the ships you want.

You have to use hullId to specify an Arvonian (Heavy) Carrier, which as far as I'm concerned is a bug. Thom should have specified a key that could not be confused with the general key "carrier". (All you have to do is add the key "heavy" to the broadType of the Arvonian Carrier, but that's a lot to ask of the people who download your script) I prefer to use raceKey and hullKey, though, because a) it makes it obvious what ship you are creating and b) you can specify a "fallback" for mods that don't define your ship type, for instance "Kralien standard" "Dreadnought large" will create a random large standard enemy if there are no Kralien Dreadnoughts.

If you do use hullId, you should specify that it is designed for the stock game. As least Thom has never changed his hullIds, so it should be safe to use for the foreseeable future.
HaydenBarca

Registered:
Posts: 127
Reply with quote  #4 
Quote:
Originally Posted by ryleyra
Oh, and you got it backwards. HullId was the original way to specify ships, raceKeys and hullKeys were added later to add more flexibility. The problem with using hullId is that if the hullIds in vesselData ever change (or you use a mod like the Star Trek mod) your script will no longer summon the ships you want.


I'm curious if there's a consensus among the other scripters whether one way is preferable -- anyone?  It sounds like race and hull keys is more robust (with the exception of Arvonian carriers).
Darrin

Registered:
Posts: 159
Reply with quote  #5 
Quote:
Originally Posted by HaydenBarca

I'm curious if there's a consensus among the other scripters whether one way is preferable -- anyone?  It sounds like race and hull keys is more robust (with the exception of Arvonian carriers).


I haven't really done much with modding, so I prefer the (misplaced?) certainty of HullID. I haven't reached the point where I want to muck around much with vesselData.xml. 

So... some other Best Practices:

  • If you're using Comms buttons, put in a "reset" event that will repopulate the Comm buttons. If the Comms player disconnects or has to go back to the console selection screen to fix something, this will wipe out the buttons. I've been using "Engineer sets Sensor Power to 0% and Sensor Coolant to 8" to reset the Comms buttons. 
  • Make sure every event has an "exit" variable that changes to break one of the conditions for triggering the event. If possible, put this variable on the last line in the event, so it's easy to spot when scrolling through events quickly. (You may still have events that need to trigger every tick, in which case don't do this, but these tend to be rare.)
  • Global Replace is not your friend. Make sure "Only in selected node" is selected before doing "Replace All". 
  • Freesound.org is awesome if you're looking for sound effects or audio clips. Provide attribution credits when needed. (I've been adding audio credits to the comments at the top of the mission script.) 
  • If you're using any voice recordings, you have to lower or kill the background music, or most players won't be able to hear the audio. Measure how many seconds, lower the global music volume for that many seconds, then bring the volume back up. Even then, you can't assume the players will be able to hear the audio (loud people talking/yelling, some crews may turn off main screen sound, etc.), so provide a text message or popup with the same information.
  • Avoid overloading the players with too much information. I spent a lot of time in my missions with how would official TSN orders be formatted, making fancy unpronounceable names for NPCs/ships, or adding as much backstory as I could... (oh, the ravages of a Liberal Arts degree...) Except during play, the Comms officer's eyes would glaze over with too much text to dig through, the important information would be ignored, and the rest of the crew would have no idea what they needed to do. In a chaotic high-pressure environment, BREVITY and CLARITY are more important than a robust and believable backstory. 
Xavier Wise

Registered:
Posts: 1,134
Reply with quote  #6 
These are great ideas. I would suggest having two broad categories though

1. Mission design (i.e. considering the audience): good practise for communicating information to the players, creating an engaging script for the whole crew, adding content such as sound/ video files etc.

2. Script writing (i.e. the coding side): naming variables, organisation of the script etc.

The ideas above mainly fit into the second category, but some could definitely be more 'Mission design' focused.

If I think of any specific things I do when scripting, and they haven't already been covered, I'll post them up! Looking through the ideas above, I agree with a lot of them.

A quick one:

MISSION DESIGN - Consider where/how your mission will be played. If you know the players are going to be taking part in a traditional LAN game, all in the same room, then audio played on the server Mainscreen isn't a problem. If the players are playing remotely (an online game) then have alternatives to allow for the fact that players will not be able to hear the sounds played through the server Mainscreen (this could also apply to players who have a hearing impairment or are deaf).

__________________
Fleet Captain Xavier Wise - TSN Sabre
Link to TSN RP Community website
Dave Thaler

Registered:
Posts: 499
Reply with quote  #7 
Quote:
Originally Posted by HaydenBarca
I'm curious if there's a consensus among the other scripters whether one way is preferable -- anyone?  It sounds like race and hull keys is more robust (with the exception of Arvonian carriers).


Thom's mission-file-docs.txt file that ships with Artemis says this:

Quote:
The old way was to use the hullID attribute to specify the exact ID of the hull (from the vesselData.xml file).  That way is still active, but no longer recommended. ... Instead, when you create a ship using the 'create' command, use the raceKeys and hullKeys to pick the best hull indirectly. ...[example]... NOW, if the Torgoth race isn't found, a race with the "enemy" key will be.  If a Battleship isn't found, the "medium" broadtype will be.  Now your script stands a much better chance of working, no matter what changes have happened to the vesselData.xml file.


So I've been following that guidance.
Dave Thaler

Registered:
Posts: 499
Reply with quote  #8 
Agree this is a great idea to write up best practices, thanks for starting this thread!  As yes I would love to see a page on it kept up to date in the wiki.

Some comments and additions:

Quote:
Originally Posted by Darrin
If you're using Comms buttons, put in a "reset" event that will repopulate the Comm buttons. If the Comms player disconnects or has to go back to the console selection screen to fix something, this will wipe out the buttons. I've been using "Engineer sets Sensor Power to 0% and Sensor Coolant to 8" to reset the Comms buttons.


I've been doing this on a timer, like every 30 or 60 seconds, so there's no need to know the magic "reset" sequence.  The downside is that the custom buttons blink when that happens.

Also the same best practice applies to any GM buttons too, in case the GM console gets disconnected.

Quote:
Make sure every event has an "exit" variable that changes to break one of the conditions for triggering the event. If possible, put this variable on the last line in the event, so it's easy to spot when scrolling through events quickly. (You may still have events that need to trigger every tick, in which case don't do this, but these tend to be rare.)


In general this is true (which is why the Artemis Mission Editor generates a warning if you don't!) but there are valid exceptions.   Two common (for me anyway) exceptions are:

1. If you need to force something that is normally changeable to be fixed.  For example, if you need to force a player ship's heading to be stuck at a specific angle no matter what helm/engineer do, or whatever else.   The Artemis engine can change properties based on normal physical and player events, and having an event that applies every cycle can override this, at the expense of some performance so use this sparingly.

2. If you have complex if/then/else logic on the expiration of a periodic timer, then it may need to span multiple events with differing conditions (one event per case), with the last event of the set being to restart the timer.

Two more pieces of advice:
  • Make sure your mission has a description that will show up in the server screen when picking the mission.  It makes the mission look much more polished.  (Artemis Mission Editor will warn if you don't.)
  • Document what version of Artemis that it was originally designed and tested for.  Some people put this in the big_message, or in the description, but someone (I forget who) before me suggested putting it in the XML in the first line like this:
    <mission_data version="2.7.5" ...>
    and so that's what I've been doing.
ryleyra

Registered:
Posts: 2,960
Reply with quote  #9 
Quote:
Originally Posted by Dave Thaler

I've been doing this (resetting Comms Buttons) on a timer, like every 30 or 60 seconds, so there's no need to know the magic "reset" sequence.  The downside is that the custom buttons blink when that happens.

Also the same best practice applies to any GM buttons too, in case the GM console gets disconnected.


The GM console can also define a keypress to reload the GM buttons. Since keypresses are not lost when the console gets disconnected, this will always work.

Unfortunately, the inconsistencies with console keypresses means this isn't a robust solution for Comms buttons. If there is a GM, I like giving the GM the ability to reset the Comms buttons. 

A trick I've used is to keep refreshing the Comms buttons until Comms presses one of the buttons. This lets you know Comms has logged in and you can stop refreshing. Comms will still lose its buttons if it disconnects, but at least Comms won't miss something important because they weren't logged in when the game was started.

I've also used docking with a base to reset Comms.

Quote:

Make sure your mission has a description that will show up in the server screen when picking the mission.  It makes the mission look much more polished.  (Artemis Mission Editor will warn if you don't.)



This feature was added in 2.6, I think, and it is a great addition to the startup interface. Don't forget that you can also provide the Instructions text for display on the GM Screen, and you can change it during execution of the script, as well! This is a great way to help the GM follow along if you have implemented a layered menu system. (i.e, you select a menu option, and it recreates the menu for the task you selected to perform)

Quote:

Document what version of Artemis that it was originally designed and tested for.  Some people put this in the big_message, or in the description, but someone (I forget who) before me suggested putting it in the XML in the first line like this:

<mission_data version="2.7.5" ...>
and so that's what I've been doing.



This has been the case since the first version of Artemis, but I've noticed that for the most part authors ignore this feature. You could also use the version number for the version of the SCRIPT, but that should probably be put in the readme file, if you have one. Using the version of Artemis at least lets your users know what version of Artemis you wrote the script for.

I'm pretty sure the game ignores this value, so it won't refuse to run it because it's too old or something. Of course, since 2.6 Artemis has been pretty bad about backward compatibility with earlier scripts. Which really makes it all the more important to note which version the script is for.

Previous Topic | Next Topic
Print
Reply

Quick Navigation:

Easily create a Forum Website with Website Toolbox.