Remote control / Metagame interface

This page is work in progress, at this point working just as an info dump.

In general, anything stated below may change at any point during game development, there's certainly some room for cleanup/consistency improvements in there. The information on this page is representative of 1.65. Note that parts of the examples below haven't specifically been tested, so there may be typos in there.

## Script flows and interactions

### Campaign game modes

The `package_config.xml` file in the root folder of a game mod references the *campaign\_entry\_script*, which can be an angel script file of your choosing. Scripts load as follows (each script *#includes* the next):

1. `scripts/start_campaign.as` This is the default *campaign\_entry\_script*, which links to your mod's source folder and script files, if any.
2. `scripts/my_gamemode.as` Imports standard RWR game mechanics and introduces the ability to extend the game's behaviours. This script includes numerous other scripts:
	1. `scripts/gamemodes/campaign/gamemode_campaign.as` Specifies general functions like load and save. Also loads `scripts/gamemodes/invasion/gamemode_invasion.as`, which is given its own section, below.
	2. `scripts/my_stage_configurator.as` Sets faction names, links to faction config files, and specifies faction colours on the game hud and map.
	3. `scripts/my_item_delivery_configurator.as` Lists weapons that are given as rewards for drop off missions and weapons that are tracked on drop off to armouries for the purpose of unlocking them for the player's faction
	4. `scripts/my_vehicle_delivery_configurator.as` Similar to the item delivery configurator, lists rewards that will be randomly chosen when tracked vehicles are dropped off at a friendly armoury.

**IMPORTANT** if your mod's folder structure doesn't contain these .as files, the ones in `vanilla/scripts` will be used instead. To simplify things — and save you losing your work when the game's scripts are updated — you may want to copy the entire scripts folder from vanilla into your mod's script folder, remove the include reference to the vanilla scripts folder from `start_campaign.as` (or replace it with the path to your mod's scripts folder) and then go ahead modifying scripts within your mod, only.

#### Important files

* `scripts/gamemodes/invasion/gamemode_invasion.as`

- of particular note in this file is the method *postBeginMatch()*, which includes various *addTracker()* calls. If you add any Classes that extend the *abstract class Tracker* (`scripts/internal/tracker.as`), you will need to reference them here as well as ensuring you `#include` the associated .as file here as well.
* `scripts/internal/tracker.as` starts with an *update* method, which is constantly triggered by the game engine. The float *time* value passed to this method is the time that has passed since *update* was last called. Functions found inside the update method can use this value to manage timed events; indeed, the functions stored here — `handle*Event()` — are the entry point to many of the other script files used in the game.

- Use a *find files containing ...* search of the `vanilla/scripts` folder (or your mod's scripts folder if you've copied the vanilla scripts into your mod's folder structure) to see how these functions of the `scripts/internal/tracker.as` *update* method operate.
- It's also a very good time to note that game *events* will generally be logged in `rwr_game.log`. For finer detail about what methods of what classes are being called as various game events trigger, add your own `_log("my text here", 1);` inside the functions you're working with. When you've found your way and are starting to script more confidently, you'll be creating your own variables through scripts and will move onto doing things like `_log("the value of myVariable is: " + myVariable, 1);` or `_log(bombCount + " artillery rounds were fired by faction " + factionID + "'s " + vehName + " and hit " + hitVeh + "at " + pos1, 1);`.
## Metagame Interface

A quick intro to how game scripts work in RWR can be seen by entering the lobby/training mission and typing */\_test* in chat. That will attempt to launch `media/packages/(mod|vanilla)/scripts/start_tester.as`, which enables `trackers/basic_command_handler.as`, a simple chat command listener. Try tailing the `rwr_game.log` file to see how this all fits together.

* Linux: `tail -f ~/.running_with_rifles/rwr_game.log`
* Windows: `get-content "$env:APPDATA\running with rifles\rwr_game.log" -wait`
* Mac: `tail -f '/Users/<username>/Library/Application Support/RunningWithRifles/rwr_game.log'`

When the *basic\_command\_handler* angel script is operating, you can issue numerous commands to it via text chat. For example, typing */test* will result in the commander chat saying "test yourself", while typing */\_m29* will spawn a magnum revolver near the player. Take a look through the file to see the other commands the listener is programmed to respond to and give them a shot in the game chat.

* *Important note*: When the **/\_test** system is executed, it replaces the active metagame (i.e. the scripts from your mod) and enables a new metagame, under which the basic command handler script inputs and outputs occur. Any other scripts that were running at this point may stop working until you restart. Again, you can tail the `rwr_game.log` to see this happening.

## Commands, i.e. inputs to RWR

The sections below detail XML commands or **metagame** calls that can be executed in one or more of the following methods:

* From an *Angel Script* `(*.as)` file found in the **scripts** folder of the mod, e.g.:

```
string command = "<command class='value' key1='value1' key2='value2' />";
m_metagame.getComms().send(command);

```

* With `init_match.xml`, usually in a map folder, to run a number of commands at the start of a match
* When a radio call is made, if the call supplies *<command>*s inside its *<round>*s
* As a *<result class="xml\_command"><command ... /></result>* in events in grenade or vehicle specifications
* As a local player by typing **/\_execute file.xml** with file.xml in RWR root folder, the file consisting of a *<command />* or *<commands><command>...</commands>*
* From server console by typing **execute file.xml**, like above

#### start\_game

```
<command
  class="start_game"
  vehicles="1"
  soldier_capacity_model="variable"
  soldier_capacity_variance="0.3"
  max_soldiers="100"
  player_ai_compensation="0"
  player_ai_reduction="0"
  xp_multiplier="1.0"
  rp_multiplier="1.0"
  initial_xp="0.1"
  initial_rp="200"
  randomize_respawn_items="0"
  base_capture_system="any"
  clear_profiles_at_start="0"
  team_kills_as_score="0"
  defense_win_time="-1"
  friendly_fire="0">

  <faction initial_occupied_bases="2" initial_over_capacity="0" ai_accuracy="0.94" capacity_multiplier="1.0" capacity_offset="10" />
  <faction initial_occupied_bases="-1" initial_over_capacity="0" ai_accuracy="0.94" capacity_multiplier="1.0" capacity_offset="10" />
</command>

```

#### restart\_game

* takes same parameters as start\_game, with undefined values from the current game

#### change\_game\_settings

* takes same parameters as start\_game
* currently can affect player\_ai\_compensation, player\_ai\_reduction, max\_soldiers, base\_capture\_system and faction settings

#### change\_map

```
<command
  class="change_map"
  map="media/packages/vanilla/maps/map5">

  <overlay path="media/overlays/mod1" />
  <overlay path="media/overlays/mod2" />
  <overlay path="media/overlays/mod3" />

  <map_config>
  <faction file="green.xml" />
  <faction file="grey.xml" />
  <weapon file="all_weapons.xml" />
  <projectile file="all_throwables.xml" />
  <call file="all_calls.xml" />
  <vehicle file="all_vehicles.xml" />
  <carry_item file="all_carry_items.xml" />
  </map_config>
</command>

```

* map config can be omitted, will use the map\_config.xml provided by the map

#### start\_server

```
<command
  class="start_server"
  server_name="dedicated"
  server_port="1238"
  register_in_serverlist="0"
  client_faction_index="-1"
  persistency="forever"
  url="http://runningwithrifles.com"
  comment="halp me" >
</command>

```

#### set\_game\_timer

```
<command
  class="set_game_timer"
  time="600"
  faction_id="0" >
</command>
```

```
 <command
   class="set_game_timer"
   time="-1" >
 </command>

```

#### update\_score\_display

```
<command
  class="update_score_display"
  id="0"                            // this is the faction_id
  text="123" >
</command>
```

#### commander\_ai

```
<command
  class="commander_ai"
  faction="1"
  base_defense="0.8"
  border_defense="0.2"
  active="1">
</command>

```

#### soldier\_ai

```
<command
  class="soldier_ai"
  faction="1">
        <parameter class="willingness_to_charge" value="1.0" />
</command>
```

#### make\_query

```
<command
  class="make_query"
  id="my_query_tag1">

  <!-- generally, you should query as little data as possible, this is just a test -->

  <data class="factions" />
  <data class="bases" />

  <data class="players" />
  <data class="characters" faction_id="0" />
  <data class="characters" faction_id="1" />

  <data class="vehicles" faction_id="1" key="cargo_truck.vehicle" />
  <data class="vehicles" type_id="42" />
  <!-- a vehicle's 'type_id' is determined by its line position in all_vehicles.xml. The first vehicle type referenced receives type_id '0' -->
  <!-- note a gotcha here is multiple 'special_crate' vehicles are defined in one file, and each vehicle key receives its own type_id... thus the type_id count is thrown out by .xml files in the /vehicles folder where multiple <vehicle> definitions are included. -->

  <data class="hitboxes" faction_id="0" />

  <!-- info about specific character, you need to find out id from elsewhere, like characters-query or from incoming events -->
  <!-- <data class="character" id="0" /> -->
  <!-- <data class="vehicle" id="0" /> -->
</command>

```

* data classes available
	+ general
	+ faction
	+ factions
	+ bases
	+ players
	+ characters
	+ character
	+ vehicles
	+ vehicle
	+ hitboxes
	+ item\_containers
	+ resources
	+ saved\_data

In most cases it is not necessary to create queries yourself. The file `scripts/internal/query_helpers.as` contains utility functions for the most common queries.

#### xp\_reward

```
<command
  class="xp_reward"
  character_id="1"
  reward="5.0">

  <!-- 1.0000 equals 10000 XP -->
  <!-- 0.0001 equals 1 XP -->
  <!-- 0.1000 equals 1000 XP, one full rank step -->

</command>

```

#### rp\_reward

```
<command
  class="rp_reward"
  character_id="1"
  reward="10000">
</command>

```

#### add\_custom\_stat

```
<command
  class="add_custom_stat"
  character_id="1"
  tag="??">
</command>

```

This appears to be used when applying an achievement to a character (e.g. blow up 15 barbecues --> "burninator")

#### kick\_player

```
<command
  class="kick_player"
  player_id="0">
</command>

```

#### update\_player

```
<command
  class="update_player"
  player_id="0"
  color="#FF0000"
  faction_id="1">
</command>

```

#### add\_hitbox\_check

```
<command
  class="add_hitbox_check"
  id="item_supply2_weapon_rack"
  instance_type="vehicle"
  instance_id="1" >
</command>

```

```
<command
  class="add_hitbox_check"
  id="item_supply2_weapon_rack"
  instance_type="character"
  instance_id="1" >
</command>

```

#### remove\_hitbox\_check

```
<command
  class="remove_hitbox_check"
  id="item_supply2_weapon_rack"
  instance_type="vehicle"
  instance_id="1" >
</command>

```

#### update\_vehicle

```
<command
  class="update_vehicle"
  id="0"
  locked="1"
  health="0.5">
</command>

```

#### remove\_vehicle

```
<command
  class="remove_vehicle"
  id="0">
</command>

```

#### chat

```
<command
  class="chat"
  text="hello world!"
  faction_id="-1"
  player_id="-1"
  position="512 0 512">
</command>

```

```
<command
  class="chat"
  key="map start with completed map"
  faction_id="-1"
  player_id="-1"
  position="512 0 512">
</command>

```

```
<command class='chat'
  key='loot objective'
  priority='1'
  faction_id='0'>
<replacement key='%base_name' text='Ranch' />
<replacement key='%map_name' text='Keepsake Bay' />
<replacement key='%number_of_bases' text='0' />
</command>

```

#### notify

```
<command
  class="notify"
  text="hello world!">
</command>
```

#### set\_world\_situation

```
<command
  class="set_world_situation">
  <faction id="0" name="Green" color="0 1 0" />
  <faction id="1" name="Grey" color="0.5 0.5 0.5" />
  <faction id="2" name="Brown" color="1 1 0" />
  <faction id="3" name="Blue" color="0 0 1" />

  <region id='0' name='map1' position='240.318 118.728' size='339.76 297.573' texture_rect='0.00279018 0.00111607 0.317383 0.276646'>
    <occupant id="0" value="1.0"/>
  </region>
  <region id='1' name='map2' position='332.227 172.969' size='587.612 372.154' texture_rect='0.351562 0.317104 0.895647 0.661691'>
    <occupant id="0" value="0.5"/>
    <occupant id="1" value="0.5"/>
  </region>
  <region id='2' name='map3' position='253.878 391.44' size='376.674 247.852' texture_rect='0.00279017 0.317104 0.351563 0.546596'>
    <occupant id="2" value="0.8"/>
    <occupant id="3" value="0.2"/>
  </region>
  <region id='3' name='map4' position='595.898 432.874' size='314.146 360.854' texture_rect='0.351563 0.661691 0.642439 0.995815'>
    <occupant id="2" value="1.0"/>
  </region>
  <region id='4' name='map5' position='383.454 584.297' size='311.886 252.372' texture_rect='0.00279018 0.661691 0.291574 0.895368'>
    <occupant id="1" value="1.0"/>
  </region>
  <region id='5' name='map6' position='176.283 539.096' size='328.46 341.267' texture_rect='0.351562 0.00111608 0.655692 0.317104'>
    <occupant id="3" value="1.0"/>
  </region>
</command>

```

#### faction\_resources

```
<command
  class="faction_resources"
  faction_id="0"
  clear_weapons="1">
  <weapon key="ak47.weapon" />
</command>

```

```
<command
  class="faction_resources"
  faction_id="0"
  soldier_group_name="miniboss">
  <projectile key="hand_grenade.projectile" enabled="0" />
</command>

```

```
<command
  class="faction_resources"
  faction_id="0"
  clear_calls="1">
  <call key="tank_drop.call"/>
</command>

```

```
<command
  class="faction_resources"
  faction_id="0">
  <carry_item key="vest2.carry_item" enabled="0" />
</command>

```

#### set\_marker

```
<command
  class="set_marker"
  faction_id="0"
  id="0"
  enabled="1"
  atlas_index="0"
  text="squad alpha rally point"
  position="512 0 512"
  color="#ff0000"
  range="10.0">
</command>

```

#### set\_match\_status

```
<command
  class="set_match_status"
  faction_id="0"
  lose="1">
</command>

```

```
<command
  class="set_match_status"
  faction_id="1"
  win="1">
</command>

```

#### set\_metagame\_event

```
<command
 class='set_metagame_event'
 name='character_kill'
 enabled='1' />

```

Enable the character kill method `handleCharacterKillEvent` to be processed through `scripts/tracker.as`

#### set\_spotting

```
<command
  class="set_spotting"
  vehicle_id="1"
  faction_id="0">
</command>

```

Show the vehicle with id '1' on the mini-map for faction '0'.

#### create\_instance

```
<command
  class="create_instance"
  faction_id="0"
  position="512 0 512"
  offset="0 0 0"
  character_id="0"
  instance_class="carry_item"
  instance_key="suitcase.carry_item" >
</command>

```

```
<command
  class="create_instance"
  faction_id="0"
  position="512 0 512"
  instance_class="character"
  instance_key="default" />
</command>

```

#### update\_static\_object

```
<command
  class="update_static_object"
  key="wall_door"
  destroyed="1" >
</command>
```

#### create\_call

```
<command
  class="create_call"
  faction_id="0"
  position="512 0 512"
  key="cover_drop.call">
</command>

```

#### update\_inventory

```
<command
  class="update_inventory"
  character_id="0"
  container_type_class="stash"
  add="1"
  instance_class="carry_item"
  instance_key="painting.carry_item">
</command>

```

```
<command
 class='update_inventory'
 character_id='0'
 container_type_class='backpack'>
 <item class='carry_item' key='painting.carry_item' />
</command>

```

#### update\_character

```
<command
  class="update_character"
  id="123"
  dead="1" />
</command>

```

#### update\_camera

```
<command
  class="update_camera"
  position="512 0 512"
  look_at="??" />
</command>

```

#### set\_comms

```
<command
  class="set_comms"
  faction_id="1"
  enabled="0">
</command>

```

#### set\_soldier\_spawn

```
<command
  class="set_soldier_spawn"
  faction_id="1"
  enabled="0">
</command>

```

#### set\_soundtrack

```
<command
  class="set_soundtrack"
  enabled="1"
  filename="mysound.wav">
</command>

```

#### save\_data

```
<command
  class="save_data">
  <root>
  <foo bar="0" />
  </root>
</command>

```

## Events, i.e. outputs from RWR

- Don't forget to tail the `rwr_game.log` file to see these events being output as they occur
#### match\_result

```
<match_result>
  <win_condition type="map_capture" faction_id="0" faction_name="Greenbelts" />
</match_result>

```

#### faction\_lost

```
<faction_lost>
  <lose_condition type="time_expired" faction_id="1" faction_name="Graycollars" />
</faction_lost>

```

#### comms\_change\_event

```
<comms_change_event
  faction_id="0"
  state="0" />

```

#### vehicle\_holder\_change\_event

```
<vehicle_holder_change_event
  vehicle_id="0"
  holder_id="0"
  owner_id="1" />

```

#### vehicle\_destroyed\_event

```
<vehicle_destroyed_event
  vehicle_id="0"
  character_id="0" />

```

#### base\_owner\_change\_event

```
<base_owner_change_event
  base_id="0"
  owner_id="0" />

```

#### chat\_event

```
<chat_event
  player_id="0"
  player_name="pasik"
  message="OMG JEEP"
  global="1" />

```

#### player\_connect\_event

```
<player_connect_event>
  <player
  name="pasik"
  player_id="0"
  faction_id="0"
  profile_hash="........."
  ip="192.168.1.5"
  port="43243"
  character_id="123" />
</player_connect_event>

```

#### player\_disconnect\_event

```
<player_disconnect_event>
  <player
  name="pasik"
  player_id="0"
  faction_id="0"
  profile_hash="........."
  ip="192.168.1.5"
  port="43243"
  character_id="123" />
</player_disconnect_event>

```

#### player\_kill

```
<player_kill>
  <killer
  name="pasik"
  player_id="0"
  faction_id="0"
  profile_hash="........."
  ip="192.168.1.5"
  port="43243"
  character_id="123" />
  <target
  name="JackMayol"
  player_id="1"
  faction_id="1"
  profile_hash="........."
  ip="xxx.xxx.xxx.xxx"
  port="43221"
  character_id="124" />
</player_kill>

```

#### player\_die

```
<player_die>
  <target
  name="JackMayol"
  player_id="1"
  faction_id="1"
  profile_hash="........."
  ip="xxx.xxx.xxx.xxx"
  port="43221"
  character_id="124" />
</player_die>

```

#### player\_spawn

```
<player_spawn>
  <player
  name="JackMayol"
  player_id="1"
  faction_id="1"
  profile_hash="........."
  ip="xxx.xxx.xxx.xxx"
  port="43221"
  character_id="125" />
</player_spawn>

```

#### hitbox\_event

```
<hitbox_event hitbox_id="blahblah" instance_type="character" instance_id="125" />

```

```
<hitbox_event hitbox_id="blahblah" instance_type="vehicle" instance_id="125" />

```

#### item\_drop\_event

```
<item_drop_event
  character_id="0"
  item_class="0"
  item_type_id="0"
  target_container_type_id="0"
  item_key="ak47.weapon"
  position="512 0 512"
  player_id="0" />

```

#### call\_request\_event

```
<call_request_event
  character_id="0"
  faction_id="0"
  call_id="0"
  call_key="cover_drop.call"
  target_position="968.851 16.7647 400.99"
  player_id="0" />

```

This event is only emitted when the call has the attribute notify\_metagame set to "1" like

```
<call key="cover_drop.call" notify_metagame="1">
  <!-- defition goes here -->
</call>

```

#### user\_quit\_event

```
<user_quit_event />

```

## Troubleshooting / bug smashing

#### `rwr_game.log` error messages

```
loading faction resources in <mod_folder_path>/factions/<file_name>
<some_text>
CHECK: characters or character element not found
execution halted

```

This error indicates you have made reference to a non-existent character file in `factions/<faction>.xml`.

Ensure the file exists in the **factions** folder, is spelled correctly, matches the case and launch the game again.

```
loading faction resources <mod_folder_path>/factions/common.resources
loading faction resources in <mod_folder_path>/factions/<another_file>.resources
loading faction resources in
CHECK: resources element not found
execution halted

```

This error indicates you have made reference to a non-existent resources file. The actual file causing the error (typo, doesn't exist, or trying to load a non-existent resource) will be the file loaded after `<another_file>.resources` is listed in `factions/<faction>.xml`.

```
loading calls in <mod_folder_path>/calls/<call_name>
loading calls in
CHECK: calls or call element not found
execution halted

```

Similar to the error above, this error indicates you have made reference to a non-existent call file in `calls/all_calls.xml`. Calls are generally processed in the order they are listed in `all_calls.xml`, so check which call was the last to load before the error occurred and the error will most likely be to do with the next referenced file.

```
<filename.as> (line_num, col) : ERR  : No matching signatures to '<text>'

```

Does `<filename>.as` include the file that contains the class, constructor, method, etc. referenced in *text*?

#### Issues that don't show up in `rwr_game.log`

* Commander briefing at start of mission fails to appear

- This generally indicates you have made a syntax error early on in `/languages/en/default_shared.character`, such as a missing forward slash '/' at the end of a `<comment key="blah" text="blah blah" />` tag. Every line after the one(s) with a syntax issue will fail to be read at start time, resulting in the comment keys used in the commander briefing failing to appear.
- You may also notice unprivileged calls (xp < 1000) don't result in a text bubble advising "I don't have a radio yet" or other text string appropriate to the `<comment key="no radio equipment"... />`. These comment tags start from line 110, so your syntax error is going to be before this line.

## Creating your own Class

### Extending the Tracker Class

1. Create a new file within the `scripts/trackers` folder named something like `myClass.as`
2. `#include` the .as scripts your class relies on (e.g. calls to *\_log()* require `log.as` or another file that includes it to be listed here).
3. Define your class with `class MyClass : Tracker { ... }`
4. Specify its constants and variables e.g. `protected Metagame@ m_metagame;`
5. Add the constructor e.g. `MyClass(Metagame@ metagame) { @m_metagame = @metagame; }`
6. Add your custom methods `protected void doSomethingMethod(const XmlElement@ block) { ... }`
7. Finally, add common class methods:

```
/* These first two are often commented out, but are left in here as a reference, should you choose to use them
// --------------------------------------------
void init() {
}

// --------------------------------------------
void start() {
}
End comment*/

// --------------------------------------------
bool hasEnded() const {
	// always on
	return false;
}
// --------------------------------------------
bool hasStarted() const {
	// always on
	return true;
}
// --------------------------------------------
void update(float time) {
	// add your custom update scripts in here like:
	// incrementing or decrementing counters
	// testing for something based on the counter value e.g. <= 0
	// writing something to the log (warning! will spam the log - update methods are called multiple times per second)
}
// ----------------------------------------------------

```