Versions Compared
Key
- This line was added.
- This line was removed.
- Formatting was changed.
Overview
Excerpt |
---|
This mod adds a new rules.js in order to increase the number of situation report audio messages in the game. It also adds a number of new audio files. |
Folders and Files
Image Modified Enhanced_SitRep_Mod.wz – the
...
mod folder
...
packaged as
...
...
).
Image Modified audio
Image Modified sitrepmod – contains several new .ogg format audio files
Image Modified audio.cfg – used to define volume and other settings for the new audio files
Image Modified multiplay
Image Modified skirmish
Image Modified
...
...
js – custom game rules
Image Modified
...
...
js – player initialisation script
Image Modified
...
...
js – situation reporting API
Image Modified
...
...
js – situation reporting message config
Image Modified wrf
Image Modified audio.wrf – defines locations of custom audio files
Let's take a closer look at each of those things...
Image Modified audio, multiplay, skirmish and wrf
These are all standard Warzone folders - places where Warzone is expecting to find its Config files (Stats) and other resources such as audio and scripts.
Image Modified sitrepmod
This is a custom folder to store audio files that are specific to the Enhanced SitRep Mod - it just keeps them together and separate from Warzone (or other mods) audio files.
To ensure filenames were unique, each audio file is prefixed with "sit-". You can see a list of the files and download them from sitrepmod.
The audio files were created using Audacity, a free open source audio editor that has native support for OGG audio files.
It was desirable to use the same female voice that's used for other in-game messages and mission briefings for these new audio files. In order to do that, segments of existing audio files (see Audio Directory) were spliced together in Audacity and then saved as new .ogg files.
Tip: You can use the search box on this wiki to locate audio files based on the words spoken in them (we've transcribed every single audio file!) to save time when looking for specific words.
There's also lots of voice audio in the Video Directory, however don't load video .ogg files in to Adacity as it tends to crash horribly - you'll have to somehow extract the audio track from the files (I used an audio recorder app to record the audio while the video was playing to achieve this).
Image Modified audio.cfg (download)
This is one of Warzone's Config files (Stats) - it defines the volume and several other properties for each of the custom audio files included in the mod:
No Format |
---|
/*sitrepmod*/
audio "sit-batatk.ogg" oneshot 100 1800 /*Battery Under Attack*/
audio "sit-batcomp.ogg" oneshot 100 1800 /*Battery Completed*/
audio "sit-cmdatk.ogg" oneshot 100 1800 /*Commander under attack*/
audio "sit-cbcomp.ogg" oneshot 100 1800 /*Counter Battery Radar Completed*/
audio "sit-lasactiv.ogg" oneshot 100 1800 /*Laser Satellite Activated*/
audio "sit-lascomp.ogg" oneshot 100 1800 /*Laser Satellite Completed*/
audio "sit-scavfirst.ogg" oneshot 100 1800 /*Scavs approaching, defend, destroy*/
audio "sit-scavraid.ogg" oneshot 100 1800 /*Scavs approaching*/ |
For more information on configuring this file, see audio.cfg.
Image Modified audio.wrf (download)
This is one of Warzone's Config files (Stats) - it defines the location of the custom audio files included in the mod using their relative folder path from the mod's "Enhanced_SitRep_Mod" folder:
No Format |
---|
directory "audio/sitrepmod"
file WAV "sit-batatk.ogg"
file WAV "sit-batcomp.ogg"
file WAV "sit-cbcomp.ogg"
file WAV "sit-cmdatk.ogg"
file WAV "sit-lasactiv.ogg"
file WAV "sit-lascomp.ogg"
file WAV "sit-scavfirst.ogg"
file WAV "sit-scavraid.ogg" |
For more information on configuring this file, see audio.wrf.
Image Modified rules.js (download)
This is one of Warzone's Config files (Stats) - it initialises players when the game starts, checks victory conditions and a bunch of other stuff.
In true modding style, it was decided to rewrite rules.js from scratch. Here's the version of the file at the time of writing this guide for reference: rules.js
To interact with Warzone, the script uses the Warzone Javascript API and various standard Javascript Coding techniques. If you've developed Javascript for web browsers, then you pretty much know what to expect.
Includes
To avoid the file getting too big it was decided to split out key chunks of functionality in to external .js files. At the start of the file, the include() function is used to include the three resulting files (which are described later on this page).
Constants
Next, a few constants are set-up - these are read-only variables that can't be changed after they've been defined. Note that the constants don't follow the usual convention of using ALL_UPPERCASE - not sure why. You can find some coding conventions on the JS API's Introduction page.
The "teams" constant keeps track of whether the game is running in "Fixed Teams" alliance mode - while it's a simple check, using the alliancesType global and ALLIANCES_TEAMS constant, it's going to be done regularly (in the checkPlayers() function described later) hence us storing the result in a constant.
The "humanPlayer" constant is set to selectedPlayer to remember which player ID corresponds to the human player that rules.js is monitoring. It's impossible for the human player to switch to another player ID at this point in the game (while the game is still initialising) so this can't be circumvented. Knowing this helps when it comes to checking events relating to the construction and destruction of the HQ.
Player initialisation
The eventGameInit() event is then used to initialise all the players, The event is called once at the start of the game, as soon as the game environment is ready for interaction with scripts.
When altering player settings, you need to first hackNetOff() and then later hackNetOn() to avoid desynch between players. A loop goes through each player in turn and initialises them by calling functions that are in the rules.js.init.js file. Because structure limits have been defined, the applyLimitSet() function is called to merge them with the default structure limits.
Next we enable or disable the design mode (setDesign()) and mini map (setMiniMap()) depending on whether the player has (enumStruct()) a HQ or not. This is just the standard rule with Warzone and you'll get shouted at if you change it without good reason! The enableTemplate() function is used to ensure that the player can produce construction trucks regardless of whether the unit designer is enabled or not.
Backwards while loops
I'm addicted to backwards "while" loops - you'll see them regularly in any script that I work on!
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
// assuming "whatever" is an array...
var num = whatever.length;
while (-1<--num) {
// do stuff with whatever[num]
} |
This will iterate from "length-1" to "0", so it's obviously only useful if you don't care about iterating backwards through the array. There's no real benefit to doing this - you could use a "for" loop or several other approaches. I just thought I'd mention the backwards while loop as many people haven't seen it before for some reason?!
Game initialisation
Because we want to keep track of player statuses, so we can work out when they are defeated or revived, a "playerLiving" array is set up - it will be initialised later.
It's really important to define as few globals as possible and keep their contents simple due to the way that Warzone saves games - for more information, see Saved game files and Common Mistakes.
The isPlayerAlive() function works out if a player is still alive or defeated. In standard Warzone game rules, a player is considered dead if the don't have any factories or units left - because at that point they can't really engage in war any more.
The eventStartLevel() event is used is then used to initialise the game, it's called just once when the game starts. In this event:
- We initialise the playerLiving array by looping through all players (maxPlayers) and checking if they are alive
- A timer is set (setTimer()) that periodically checks player states via the checkPlayers() function
- The reporting API (in rules.report.js) is called to welcome the player to the game
Victory conditions
As mentioned above, the checkPlayers() function is called periodically to determine if the game is won or lost. In standard Warzone game rules:
- The player wins if they have no enemies left
- The player loses if they are dead, unless they are part of a fixed team in which case they only lose when all of their team is also dead
The checkPlayers() function goes through each player in turn to work out who's alive and who's dead. It keeps track of how many allies, team members and enemies are alive with respect to the player. The allianceExistsBetween() function determines if two players are allied with each other.
Using the playerLiving array, it's possible to detect when a player dies or gets revived (by an ally giving them a truck or other unit) and thus report on the situation.
After checking each player status and tallying the number of living allies, team mates and enemies, the victory conditions are then checked at the bottom of the checkPlayers() function. the gameOverMessage() function is called if the game is won or lost, and the "checkPlayers" timer is removed (removeTimer()) to prevent further calls to checkPlayers().
HQ monitoring
As mentioned earlier, the design tool and mini map features are toggled on or off based on the existence of a HQ structure. This means the script has to keep track of when the HQ gets built and destroyed - it does this using eventStructureBuilt() and eventDestroyed().
The game's debug menu (also known as cheat mode) allows a player to switch to other players at which point rules.js starts to operate as the player they've selected. To avoid confusion, the "humanPlayer" constant we defined earlier is used to make sure the event was triggered in relation to that player ID.
The events are passed a Structure object that defines what structure was built or destroyed, but they can also be triggered for other things (such as droids/units being destroyed and even map features) so it's useful to check that the object type is STRUCTURE before checking that it's a HQ - this is because only structure objects have a .stattype property: if we tried accessing that property on any other type of object it would cause an error.
Situation reporting
Now we finally get to the situation reporting - it's what this mod is about after all!
This is achieved by listening to a bunch of game Events & Timers and then relaying them on to the reporting API in rules.report.js.
Image Modified rules.init.js (download)
This script contains all the player initialisation code and data that gets called from eventGameInit() in rules.js.
Settings & config data
An empty init() function is created as a namespace to store all the data associated with player initialisation - this prevents all that stuff finding its way on to the global scope.
The properties are named so it's clear what their contents are used for, and the functions that process them follow a similar naming convention. By putting all these settings and config data at the top of the script, it's easy to change them without worrying about breaking any of the code lower down the script.
The first few properties are arrays of IDs relating to structures, components and technologies. You can find the ID's for these things in the game's Config files (Stats) (or alternatively use the online guide – click on an item to view it's detail page and you'll see it's ID at the top). Towards the end of the settings, in the "baseTypes" bit, a lot of the JS API's Constants are used.
Initialisation functions
There's a function to deal with each config setting property defined at the top of the script. The functions have the same name as the property with a "For" tagged on the end so that the code in rules.js is really easy to read:
Code Block | ||||
---|---|---|---|---|
|
...
| ||
init.enableStructuresFor(player);
init.enableComponentsFor(player);
init.enableTechnologiesFor(player);
init.setLimitsFor(player);
init.applyBaseTypeFor(player); |
It's pretty obvious what's going on there!
The functions are pretty much self explanatory and use a lot of the constants, globals and functions that are documented with examples in the Javascript API.
You'll notice that the native Javascript Array object's forEach() and some() functions are used quite a lot - these make it easy to iterate through arrays, calling a function on each item in the array, without needing to define custom variables and loops. While they might look a bit odd at first, I highly recommend them as they're really quick and easy to use once you get used to them.
Image Modified rules.report.js (download)
This file is much too big to describe in detail, but we'll take a look at a few things...
constants
The JavaScript API defines a number of Constants, however depending on which version of the JS API is being used some or all of them might be missing. So, the first block of code checks whether required constants are defined, and if not it creates them.
closures
Because the script contains dozens of functions, it was decided to use a closure to keep them from getting on to the global scope. For more information on closures, see Scopes & Closures.
The basic format used is as follows:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
var report = (function() {
// lots of stuff
return thingYouWantToAssignToReport;
})(); |
Here, we're creating an anonymous self-running function. When you wrap a function definition in (brackets like this)() you run the function and it's return value is assigned to "report".
Object classification
This code will probably come in useful for other mods, You pass classify() a "game object" (which can be any of the standard Warzone object types – see Objects) and it returns a string ID that classifies what that object is, for example if you pass it a VTOL Factory structure object, the returned string will be something like "base.factory.vtol".
This might seem like overkill, especially when you consider object properties like .stattype and .droidType which tell you fairly accurately what something is. But as you look in closer detail you'll see that this classification abstracts us away from lots of crufty object classification code and version-specific API features. It also goes beyond what the JS API provides because it can classify features and different types of weapons, etc.
report() function
This is responsible for taking an object classification string and finding an associated object defined in rules.report.msg.js. What's interesting here is that the object classification will be "reduced" until a matching object is found, or not. For more details on how that works, take a look at the extensive code comment in rules.report.msg.js.
is*() functions
At the bottom of rules.report.js, there's a plethora of functions that check whether a passed in object meets some specific criteria - for example, isTransport() checks to see if the passed in object is a transporter.
These are all easy to do without having functions, but I find that putting all this stuff in to functions makes code elsewhere a lot more readable, like this:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
// custom attacked reports... report.attacked.custom = function(obj, attacker) { if (obj.type != DROID) return; if (isFixVTOL(obj)) { // custom: vtols attacked while fleeing the battlefield |
...
if (!!attacker && isAntiAir(attacker)) return "custom.abort"; if (isRepairing(obj)) return "custom.rearm"; if (isRetreating(obj)) return "custom.return"; } else { // custom: non-vtol droids attacked while fleeing the battlefield if (isRepairing(obj)) return "custom.repairs"; if (isRetreating(obj)) return "custom.retreat"; } } |
Image Modified rules.report.msg.js (download)
This script is really just a huge object definition - it works as a look-up table between a game object's classification string (generated by code in rules.report.js) and an object that defines what should happen in relation to it.
There's extensive code comments at the start of the file that explain it in detail.
Div | ||
---|---|---|
| ||
This plugin was originally developed by Shadow Wolf TJC. For more information see Enhance SitRep Mod in the Warzone forums. |
Div | ||
---|---|---|
| ||
Developer LinksAudio resources:
Customising game rules:
Scipting:
|