Laser Tag S04 – Variables and Miles Tag 2 Protocol

Love Jesus, Love Code

Time 30

Every laser tag system behaves in slightly different ways, depending on what the designer thought was important. When we create our laser tag guns, we could start from scratch in terms of game specifications, or choose to make our guns compatible with another system. In this case, we have decided to make our guns compatible with the Miles Tag 2 protocol.

A reference file for the protocol can be found at https://openlasertag.org/download/miles-ii-ir-protocol-pdf/
or can be downloaded here

The Miles Tag protocol covers the following IR signals:

  1. Shot packet
  2. Message packed
  3. Cloning Signal

While there is much to implement, the first step is to add in all the variables, we can then program them to become functional at a later date. The Miles Tag protocol also specifies player names and teams names.

In this tutorial we will:

  1. Declare all the Miles Tag 2 protocol variables in our program
  2. Show how to display player names and team names instead of player ID numbers and team ID numbers. We will start to do this through the web interface.

Make an existing copy of the code from the last tutorial, saving it as: NodeMCU_LaserTag_S04

Declaring the Game Variables

The variables are listed in order of the Cloning Data signal. The cloning signal is part of the Miles Tag specifications that deals with how the guns perform in the game. It allows you to easily make changes to the guns to change how they behave in the game.

This code can be cut and pasted into your main program. You will notice the list of variables has significantly increased from your previous version of your program.

These variables go under your teamID and playerID variable.

// Game variables unique to Gun (later to be stored in memory)
int teamID = 4; // 0-4  0 = red, 1 = blue, 2 = yellow, 3 = green, 4 = unspecified
int playerID = 99; // 0-99 Each gun needs a unique player ID

// Game variables in order of Cloning Data (Extra details regarding Cloning data)
int volume = 0x1E; //volume is from 0-30 for the jq6500 module. (this is currently not changed by cloning data signal
int fieldID = 0x00; // 0x00 = A, 0x01 = B
int killLed = 0x3C; // Kill LED timeout in seconds
int soundSet = 0x00; // 0=Military, 1 = Sci-Fi, 2 = Silenced
int SRKDamage = 0x0F; // mapped
int SRKRange = 0x02; // mapped
int flag = 0x00; // FlagView ENABLE = 0x01 FlagRept ENABLE = 0x02 Team Display MILITARY = 0x08 Main Display PLAYER = 0x10
int myGunDamage = 0x05; //Mapped
int magSize = 0x63; // 255=unlimited
int magazines = 0x63; //202= unlimited
int fireSelect = 0x02; // 0=semi-auto, 1=Burst, 2=Full Auto
int burstSize = 0x03; // RESERVED bite, assume used for burst size. Default = 3
int roundsMin = 0x04; // Mapped // 0=250, 1=300, 2=350,..., 12 =800;
int reloadDelay = 0x03; // seconds
int IRPowerMode = 0x01; // (in/out) // 0=indoor, 1=outdoor
int range = 0x06; // Assume 6 is maximum range
int muzFlash = 0x09; // ENABLE = 0x10 Short Range Kill ENABLE = 0x02 Hit Flash ENABLE = 0x08
int respawnHealth = 0x24; // Mapped (life) // 1=1, 2=2,... 20=20, 21=25,..., 36=100 ,  increments of 5 to 200, increments of 50 to 72=999
int bodyArmourMin = 0x01 ; 
int bodyArmourMax = 0x32;
int gameMode1 = 0xB4; //Zombie Mode ENABLE = 0x02 Friendly Fire ENABLE = 0x04 Unlimited Ammo ENABLE = 0x08 Respawn Flash ENABLE = 0x10 Flag Flash ENABLE = 0x20 Game Box RoR ENABLE = 0x40 Game Box Stay ENABLE = 0x80
int gameMode2 = 0x58; // Body Armour ENABLE = 0x02 Zombie Flash ENABLE = 0x08 Near Miss ENABLE = 0x10 Flag End ENABLE = 0x20 Ammo RoR ENABLE = 0x40
int hitDelay = 0; // Seconds
int startDelay = 0; // Seconds (may also be respawn delay)
int bleedOut = 0; // Seconds
int gameLength = 0x0C; // Minutes 0x0C = 12
int zombieLife = 0x3A; // Mapped
int zombieDamage = 8; // Mapped
int bodyArmourHeal = 2; // pts/sec
int medicBoxHealth = 0x32; // raw value
int ammoBoxClips = 0x05; // raw value
int armourBoxPoints = 0x0A; // raw value
int gameOptions = 0x7F; // Weapon RoR ENABLE = 0x08 Zombie Sounds = 0x40 Dual Muzzle ENABLE = 0x80

Adding the player and team names

It is important that each gun refers to the same player name, given a playerID. For this, we will create a function that will allow us to enter in the playerID as a number, and it will return the playerName as a string.

  1. Create a new tab called MilesTagMapping
  2. Enter the following code
String playerName(int playerID){
  switch (playerID){
    case 0: return "Eagle"; break;
    case 1: return "Joker"; break;
    case 2: return "Raven"; break;
    case 3: return "Sarge"; break;
    case 4: return "Angel"; break;
    case 5: return "Cosmo"; break;
    case 6: return "Gecko"; break;
    case 7: return "Blaze"; break;
    case 8: return "Camo"; break;
    case 9: return "Fury"; break;
    case 10: return "Flash"; break;
    case 11: return "Gizmo"; break;
    case 12: return "Homer"; break;
    case 13: return "Storm"; break;
    case 14: return "Habit"; break;
    case 15: return "Click"; break;
    case 16: return "Ronin"; break;
    case 17: return "Lucky"; break;
    case 18: return "Radar"; break;
    case 19: return "Blade"; break;
    case 20: return "Ninja"; break;
    case 21: return "Magic"; break;
    case 22: return "Gonzo"; break;
    case 23: return "Cobra"; break;
    case 24: return "Pappy"; break;
    case 25: return "Rambo"; break;
    case 26: return "Snake"; break;
    case 27: return "Audie"; break;
    case 28: return "Sting"; break;
    case 29: return "Zeena"; break;
    case 30: return "Bugsy"; break;
    case 31: return "Viper"; break;
    case 32: return "Jewel"; break;
    case 33: return "Genie"; break;
    case 34: return "Logan"; break;
    case 35: return "Razor"; break;
    case 36: return "Slick"; break;
    case 37: return "Venom"; break;
    case 38: return "Rocky"; break;
    case 39: return "Saber"; break;
    case 40: return "Crush"; break;
    case 41: return "Titan"; break;
    case 42: return "Orbit"; break;
    case 43: return "Vixen"; break;
    case 44: return "Tank"; break;
    case 45: return "Rogue"; break;
    case 46: return "Sheik"; break;
    case 47: return "Gizmo"; break;
    case 48: return "Siren"; break;
    case 49: return "Dozer"; break;
    case 50: return "Micro"; break;
    case 51: return "LgtMG"; break;
    case 52: return "HvyMG"; break;
    case 53: return "ZOOKA"; break;
    case 54: return "ROCKET"; break;
    case 55: return "GRNDE"; break;
    case 56: return "CLYMR"; break;
    case 57: return "MINE"; break;
    case 58: return "BOMB"; break;
    case 59: return "NUKE"; break;
    default: return "Uknown"; break;
  }
  
}

String teamName(int teamID){
  switch (teamID){
    case 0: return "red"; break;
    case 1: return "blue"; break;
    case 2: return "yellow"; break;
    case 3: return "green"; break; 
    default: return "Unknown"; break;
  }
}

String weaponName(int myFire){
  if (myFire==0) return "Semi";
  if (myFire==1) return "Burst";
  if (myFire==2) return "Full";
  else return "Null";
}

The web interface

Instead of using the team number and player number, we now want to display more meaningful information, such as the team colour and the player name.

  1. Go to the WebActions tab in your Arduino software
  2. We will be adding two more placeholders. PLACEHOLDER_PlayerName and PLACEHOLDER_TeamName. The return strings will be playerName(playerID) and teamName(teamID) respectfully.
  3. Your code for the String processor in WebActions should now look like:
String processor(const String& var){

  if(var == "PLACEHOLDER_PlayerID"){
    return String(playerID);
  }
  else if(var == "PLACEHOLDER_PlayerName"){
    return playerName(playerID);
  }
  else if(var == "PLACEHOLDER_TeamID"){
  return String(teamID);
  }
  else if(var == "PLACEHOLDER_TeamName"){
  return teamName(teamID);
  }
 
  return String();
}
  1. Go to indexPage.h tab in Arduino
  2. Between the H1 tags, Replace PLACEHOLDER_PlayerID with PLACEHOLDER_PlayerName
<H1> Player: %PLACEHOLDER_PlayerName% Team: %PLACEHOLDER_TeamName% </H1>

Compile and test

Go to sketch –> Export Compiled Binary

Turn your NodeMCU board on and upload the saved binary through the web interface. http://[nodeMCU IP address]/update

You should now see the player name change and team colour change as you modify the variables through the web interface.

Notice the error

We allow the user to enter in up to 99 playerID through the web interface. We should limit this to 50, so we can’t set the gun name to an unknown player, or to a different type of game object. See if you can work this one out yourself. Hint, you will need to change something in the indexPage.h tab.

Milestag mapped variables

Milestag aims to minimise data so that the shot pulses are shorter. One way to minimise the data is to use what the milestag document calls mapping.

Some examples of mapped variables are Damage per shot as shown below in the table

ValueDamage Dealt
0x001
0x012
0x024
0x035
0x047
0x0510
0x0615
0x0717
0x0820
0x0925
0x0A30
0x0B35
0x0C40
0x0D50
0x0E75
0x0F100
MilesTag Reference 2.3.3 Byte 17 – Damage per shot

Sometimes there are simple patterns in the mappings which mean we can use loops and if statements to minimise code. Sometimes the mapping is so random that using switch and case statements is necessary. Place the following code at the end of the Miles Tag Mapping tab.

int damageMapped(int damage){
  switch (damage){
    case 0: return 1; break;
    case 1: return 2; break;
    case 2: return 4; break;
    case 3: return 5; break;
    case 4: return 7; break;
    case 5: return 10; break;
    case 6: return 15; break;
    case 7: return 17; break;
    case 8: return 20; break;
    case 9: return 25; break;
    case 10: return 30; break;
    case 11: return 35; break;
    case 12: return 40; break;
    case 13: return 50; break;
    case 14: return 75; break;
    case 15: return 100; break;
    default: return 0;
  }
}

int healthMapped(int health){
  if (health<=20){
    return health; 
  } 
  else if (health<=200){
    health -= 20;
    return ((health * 5) + 20);
  }
  else{
    health -= 56;
    return ((health * 50) + 200);
  }
}

This code will be called upon at a later point

Edit MilesTags values on new web page

Every time we want to change any of the MilesTag values, we need to modify the program, then recompile and upload it. A simpler way would be to change the variables through the web interface.

  1. Create a new tab called milesTagPage.h
//use a header to store html document
#ifndef MILESTAGPAGE_H
#define MILESTAGPAGE_H

const char milestag_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head><title>LaserTag MilesTag Settings</title></head>
<style>
  table {
  border-collapse: collapse;
}

th, td {
  text-align: left;
  padding: 8px;
}

th {
  background-color: #999999;
}

tr:nth-child(even) {
  background-color: #cccccc;
}
</style>
<body>
 <H1>LaserTag MilesTag Settings</H1>
  <p>Player: %PLACEHOLDER_PlayerName% | Team</td><td> %PLACEHOLDER_TeamName% </p>
  <form action="/getMiles" target="hidden-form" onsubmit="setTimeout(function(){window.location.reload();},10);">
  <table>
  <thead><tr><th>Item</th><th>Curent Value</th><th>Value Range</th><th>Update Value</th></tr>
  </thead>
  <tbody>
    
    <tr><td> Volume </td><td> %PLACEHOLDER_volume% </td><td> 0-30 </td><td> <input type="number" name="inputVolume" value=%PLACEHOLDER_volume% min="0" max="30" step="1" pattern="\d+"></td></tr>
    <tr><td> Field ID </td><td> %PLACEHOLDER_fieldID% </td><td> 0-1 </td><td> <input type="number" name="inputFieldID" value=%PLACEHOLDER_fieldID% min="0" max="1" step="1" pattern="\d+"></td></tr>
    <tr><td> kill Led </td><td> %PLACEHOLDER_killLed% </td><td> 0-60 </td><td> <input type="number" name="inputKillLed" value=%PLACEHOLDER_killLed% min="0" max="60" step="1" pattern="\d+"></td></tr>  
    <tr><td> Sound Set </td><td> %PLACEHOLDER_soundSet% </td><td> 0-2 </td><td> <input type="number" name="inputSoundSet" value=%PLACEHOLDER_soundSet% min="0" max="2" step="1" pattern="\d+"></td></tr>
    <tr><td> SRK Damage </td><td> %PLACEHOLDER_SRKDamage% </td><td> 0-255 </td><td> <input type="number" name="inputSRKDamage" value=%PLACEHOLDER_SRKDamage% min="0" max="255" step="1" pattern="\d+"></td></tr>
    <tr><td> SRK Range </td><td> %PLACEHOLDER_SRKRange% </td><td> 0-255 </td><td> <input type="number" name="inputSRKRange" value=%PLACEHOLDER_SRKRange% min="0" max="255" step="1" pattern="\d+"></td></tr>
    <tr><td> Flag </td><td> %PLACEHOLDER_flag% </td><td> 1=Enable, 2=Team display, 8=Military, 16= Player</td><td> <input type="number" name="inputFlag" value=%PLACEHOLDER_flag% min="0" max="16" step="1" pattern="\d+"></td></tr>
    <tr><td> My Gun Damage </td><td> %PLACEHOLDER_myGunDamage% </td><td> 0-255 </td><td> <input type="number" name="inputMyGunDamage" value=%PLACEHOLDER_myGunDamage% min="0" max="255" step="1" pattern="\d+"></td></tr>
    <tr><td> Mag Size </td><td> %PLACEHOLDER_magSize% </td><td> 0-255 </td><td> <input type="number" name="inputMagSize" value=%PLACEHOLDER_magSize% min="0" max="255" step="1" pattern="\d+"></td></tr>
    <tr><td> Magazines </td><td> %PLACEHOLDER_magazines% </td><td> 0-202 </td><td> <input type="number" name="inputMagazines" value=%PLACEHOLDER_magazines% min="0" max="202" step="1" pattern="\d+"></td></tr>
    <tr><td> Fire Select </td><td> %PLACEHOLDER_fireSelect% </td><td> 0=semi-auto, 1=Burst, 2=Full Auto </td><td> <input type="number" name="inputFireSelect" value=%PLACEHOLDER_fireSelect% min="0" max="1" step="1" pattern="\d+"></td></tr>
    <tr><td> Burst Size </td><td> %PLACEHOLDER_burstSize% </td><td> 0-255, Default=3 </td><td> <input type="number" name="inputBurstSize" value=%PLACEHOLDER_burstSize% min="0" max="255" step="1" pattern="\d+"></td></tr>
    <tr><td> Rounds Min </td><td> %PLACEHOLDER_roundsMin% </td><td> 0-12, 0=250, 1= 300, 2=350 ,.., 12=800 </td><td> <input type="number" name="inputRoundsMin" value=%PLACEHOLDER_roundsMin% min="0" max="12" step="1" pattern="\d+"></td></tr>
    <tr><td> Reload Delay </td><td> %PLACEHOLDER_reloadDelay% </td><td> 0-255, default=3 </td><td> <input type="number" name="inputReloadDelay" value=%PLACEHOLDER_reloadDelay% min="0" max="255" step="1" pattern="\d+"></td></tr>
    <tr><td> IR Power Mode </td><td> %PLACEHOLDER_IRPowerMode% </td><td> 0=indoor, 1=outdoor </td><td> <input type="number" name="inputIRPowerMode" value=%PLACEHOLDER_IRPowerMode% min="0" max="1" step="1" pattern="\d+"></td></tr>
    <tr><td> Range </td><td> %PLACEHOLDER_range% </td><td> 0-6, 6=max range </td><td> <input type="number" name="inputRange" value=%PLACEHOLDER_range% min="0" max="6" step="1" pattern="\d+"></td></tr>
    <tr><td> Muzzle Flash </td><td> %PLACEHOLDER_muzFlash% </td><td> 0-1, 1=on</td><td> <input type="number" name="inputMuzFlash" value=%PLACEHOLDER_muzFlash% min="0" max="1" step="1" pattern="\d+"></td></tr>
    <tr><td> respawnHealth </td><td> %PLACEHOLDER_respawnHealth% </td><td> 0-72 (mapped, 36=100, 72=999) </td><td> <input type="number" name="inputRespawnHealth" value=%PLACEHOLDER_respawnHealth% min="0" max="72" step="1" pattern="\d+"></td></tr>
    <tr><td> Body Armour Min </td><td> %PLACEHOLDER_bodyArmourMin% </td><td> 1-100 (Minimum damage to penetrate armour) </td><td> <input type="number" name="inputBodyArmourMin" value=%PLACEHOLDER_bodyArmourMin% min="1" max="100" step="1" pattern="\d+"></td></tr>
    <tr><td> Body Armour Max </td><td> %PLACEHOLDER_bodyArmourMax% </td><td> 0-255 </td><td> <input type="number" name="inputBodyArmourMax" value=%PLACEHOLDER_bodyArmourMax% min="0" max="255" step="1" pattern="\d+"></td></tr>
    <tr><td> Game Mode 1 </td><td> %PLACEHOLDER_gameMode1% </td><td> 0-255* </td><td> <input type="number" name="inputGameMode1" value=%PLACEHOLDER_gameMode1% min="0" max="255" step="1" pattern="\d+"></td></tr>
    <tr><td> Game Mode 2 </td><td> %PLACEHOLDER_gameMode2% </td><td> 0-255^ </td><td> <input type="number" name="inputGameMode2" value=%PLACEHOLDER_gameMode2% min="0" max="255" step="1" pattern="\d+"></td></tr>
    <tr><td> Hit Delay </td><td> %PLACEHOLDER_hitDelay% </td><td> 0-255 </td><td> <input type="number" name="inputHitDelay" value=%PLACEHOLDER_hitDelay% min="0" max="1" step="255" pattern="\d+"></td></tr>
    <tr><td> Start Delay (respawn delay) </td><td> %PLACEHOLDER_startDelay% </td><td> 0-255 </td><td> <input type="number" name="inputStartDelay" value=%PLACEHOLDER_startDelay% min="0" max="1" step="255" pattern="\d+"></td></tr>
    <tr><td> Bleed Out </td><td> %PLACEHOLDER_bleedOut% </td><td> 0-255 (After being tagged out [killed] you can still be healed during this time) </td><td> <input type="number" name="inputBleedOut" value=%PLACEHOLDER_bleedOut% min="0" max="1" step="1" pattern="\d+"></td></tr>
    <tr><td> Game Length </td><td> %PLACEHOLDER_gameLength% </td><td> 0-120 Game time in minutes, 0=No Time Limit </td><td> <input type="number" name="inputGameLength" value=%PLACEHOLDER_gameLength% min="0" max="120" step="1" pattern="\d+"></td></tr>
    <tr><td> Zombie Life </td><td> %PLACEHOLDER_zombieLife% </td><td> 1-72 (Mapped) 36=100, 58 = 300, 72=999</td><td> <input type="number" name="inputZombieLife" value=%PLACEHOLDER_zombieLife% min="1" max="72" step="1" pattern="\d+"></td></tr>
    <tr><td> Zombie Damage </td><td> %PLACEHOLDER_zombieDamage% </td><td> 0-16 (Mapped) 0=1, 13=50, 16=100 </td><td> <input type="number" name="inputZombieDamage" value=%PLACEHOLDER_zombieDamage% min="0" max="16" step="1" pattern="\d+"></td></tr>
    <tr><td> Body Armour Heal </td><td> %PLACEHOLDER_bodyArmourHeal% </td><td> 0-100 points/second </td><td> <input type="number" name="inputBodyArmourHeal" value=%PLACEHOLDER_bodyArmourHeal% min="0" max="100" step="1" pattern="\d+"></td></tr>
    <tr><td> Medic Box Health </td><td> %PLACEHOLDER_medicBoxHealth% </td><td> 0-100 </td><td> <input type="number" name="inputMedicBoxHealth" value=%PLACEHOLDER_medicBoxHealth% min="0" max="100" step="1" pattern="\d+"></td></tr>
    <tr><td> ammoBoxClips </td><td> %PLACEHOLDER_ammoBoxClips% </td><td> 0-30 </td><td> <input type="number" name="inputAmmoBoxClips" value=%PLACEHOLDER_ammoBoxClips% min="0" max="30" step="1" pattern="\d+"></td></tr>
    <tr><td> armourBoxPoints </td><td> %PLACEHOLDER_armourBoxPoints% </td><td> 0-100 </td><td> <input type="number" name="inputArmourBoxPoints" value=%PLACEHOLDER_armourBoxPoints% min="0" max="100" step="1" pattern="\d+"></td></tr>
    <tr><td> Game Options </td><td> %PLACEHOLDER_gameOptions% </td><td> 0-255 Weapon RoR ENABLE (+8) Zombie Sounds (+64) Dual Muzzle ENABLE (+128) </td><td> <input type="number" name="inputGameOptions" value=%PLACEHOLDER_gameOptions% min="0" max="255" step="1" pattern="\d+"></td></tr>
  </tbody></table>
    <input type="submit" value="Submit" onclick="submitMessage()">
  </form><br>
  <p> * Game Mode 1: Zombie Mode ENABLE (+2) Friendly Fire ENABLE (+4) Unlimited Ammo ENABLE (+8) Respawn Flash ENABLE (+16) Flag Flash ENABLE (+32) Game Box RoR ENABLE (+64) Game Box Stay ENABLE (+128) </p>
  <p> ^ Game Mode 2: Body Armour ENABLE (+2) Zombie Flash ENABLE (+4) Near Miss ENABLE (+16) Flag End ENABLE (+32) Ammo RoR ENABLE (+64)
  
  <iframe style="display:none" name="hidden-form"></iframe>
</body>
</html>
)rawliteral";

#endif

The above code draws a table that will allow all the MilesTag variables to be modified.

  1. In the main program tab, find the section called //code for web page. This code must be put after the web server libraries (under the ElegantOTA section). Put in the following code
//code for web page
#include "indexPage.h"
#include "milesTagPage.h"
  1. In the WebActions.ino tab, in the setupWebActions() subroutine, add the following code under the server.on(“/”, HTTP_GET, ….){…} section, add another section:
// Send Miles Tag page with input fields to client
  server.on("/milestag", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", milestag_html, processor);
  });
  1. Go to the WebActions.ino tab. In the setupWebActions() subroutine, add the following code after the server.on(“/get”, HTTP_GET…){…} section. Be careful with brackets.
// Send a GET request for the milestag form ---------------------------------------------------------------
  server.on("/getMiles", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage;
    // GET volume from web form
    if (request->hasParam("inputVolume")) {
      inputMessage = request->getParam("inputVolume")->value();
      volume = inputMessage.toInt(); 
    }
    // GET fieldID from web form
    if (request->hasParam("inputFieldID")) {
      inputMessage = request->getParam("inputFieldID")->value();
      fieldID = inputMessage.toInt(); 
    }
    // GET killLed from web form
    if (request->hasParam("inputKillLed")) {
      inputMessage = request->getParam("inputKillLed")->value();
      killLed = inputMessage.toInt(); 
    }
    // GET SRKDamage from web form
    if (request->hasParam("inputSRKDamage")) {
      inputMessage = request->getParam("inputSRKDamage")->value();
      SRKDamage = inputMessage.toInt(); 
    }
    // GET SRKRange from web form
    if (request->hasParam("inputSRKRange")) {
      inputMessage = request->getParam("inputSRKRange")->value();
      SRKRange = inputMessage.toInt(); 
    }
    // GET flag from web form
    if (request->hasParam("inputFlag")) {
      inputMessage = request->getParam("inputFlag")->value();
      flag = inputMessage.toInt(); 
    }
    // GET myGunDamage from web form
    if (request->hasParam("inputMyGunDamage")) {
      inputMessage = request->getParam("inputMyGunDamage")->value();
      myGunDamage = inputMessage.toInt(); 
    }
    // GET magSize from web form
    if (request->hasParam("inputMagSize")) {
      inputMessage = request->getParam("inputMagSize")->value();
      magSize = inputMessage.toInt(); 
    }
    // GET magazines from web form
    if (request->hasParam("inputMagazines")) {
      inputMessage = request->getParam("inputMagazines")->value();
      magazines = inputMessage.toInt(); 
    }
    // GET fireSelect from web form
    if (request->hasParam("inputFireSelect")) {
      inputMessage = request->getParam("inputFireSelect")->value();
      fireSelect = inputMessage.toInt(); 
    }
    // GET burstSize from web form
    if (request->hasParam("inputBurstSize")) {
      inputMessage = request->getParam("inputBurstSize")->value();
      burstSize = inputMessage.toInt(); 
    }
    // GET roundsMin from web form
    if (request->hasParam("inputRoundsMin")) {
      inputMessage = request->getParam("inputRoundsMin")->value();
      roundsMin = inputMessage.toInt(); 
    }
    // GET reloadDelay from web form
    if (request->hasParam("inputReloadDelay")) {
      inputMessage = request->getParam("inputReloadDelay")->value();
      reloadDelay = inputMessage.toInt(); 
    }
    // GET IRPowerMode from web form
    if (request->hasParam("IRPowerMode")) {
      inputMessage = request->getParam("IRPowerMode")->value();
      IRPowerMode = inputMessage.toInt(); 
    }
    // GET range from web form
    if (request->hasParam("inputRange")) {
      inputMessage = request->getParam("inputRange")->value();
      range = inputMessage.toInt(); 
    }
    // GET muzFlash from web form
    if (request->hasParam("inputMuzFlash")) {
      inputMessage = request->getParam("inputMuzFlash")->value();
      muzFlash = inputMessage.toInt(); 
    }
    // GET respawnHealth from web form
    if (request->hasParam("inputRespawnHealth")) {
      inputMessage = request->getParam("inputRespawnHealth")->value();
      respawnHealth = inputMessage.toInt(); 
    }
    // GET bodyArmourMin from web form
    if (request->hasParam("inputBodyArmourMin")) {
      inputMessage = request->getParam("inputBodyArmourMin")->value();
      bodyArmourMin = inputMessage.toInt(); 
    }
    // GET bodyArmourMax from web form
    if (request->hasParam("inputBodyArmourMax")) {
      inputMessage = request->getParam("inputBodyArmourMax")->value();
      bodyArmourMax = inputMessage.toInt(); 
    }
    // GET gameMode1 from web form
    if (request->hasParam("inputGameMode1")) {
      inputMessage = request->getParam("inputGameMode1")->value();
      gameMode1 = inputMessage.toInt(); 
    }
    // GET gameMode2 from web form
    if (request->hasParam("inputGameMode2")) {
      inputMessage = request->getParam("inputGameMode2")->value();
      gameMode2 = inputMessage.toInt(); 
    }
    // GET hitDelay from web form
    if (request->hasParam("inputHitDelay")) {
      inputMessage = request->getParam("inputHitDelay")->value();
      hitDelay = inputMessage.toInt(); 
    }
    // GET startDelay from web form
    if (request->hasParam("inputStartDelay")) {
      inputMessage = request->getParam("inputStartDelay")->value();
      startDelay = inputMessage.toInt(); 
    }
    // GET bleedOut from web form
    if (request->hasParam("inputBleedOut")) {
      inputMessage = request->getParam("inputBleedOut")->value();
      bleedOut = inputMessage.toInt(); 
    }
    // GET gameLength from web form
    if (request->hasParam("inputGameLength")) {
      inputMessage = request->getParam("inputGameLength")->value();
      gameLength = inputMessage.toInt(); 
    }
    // GET zombieLife from web form
    if (request->hasParam("inputZombieLife")) {
      inputMessage = request->getParam("inputZombieLife")->value();
      zombieLife = inputMessage.toInt(); 
    }
    // GET zombieDamage from web form
    if (request->hasParam("inputZombieDamage")) {
      inputMessage = request->getParam("inputZombieDamage")->value();
      zombieDamage = inputMessage.toInt(); 
    }
    // GET bodyArmourHeal from web form
    if (request->hasParam("inputBodyArmourHeal")) {
      inputMessage = request->getParam("inputBodyArmourHeal")->value();
      bodyArmourHeal = inputMessage.toInt(); 
    }
    // GET medicBoxHealth from web form
    if (request->hasParam("inputMedicBoxHealth")) {
      inputMessage = request->getParam("inputMedicBoxHealth")->value();
      medicBoxHealth = inputMessage.toInt(); 
    }
    // GET ammoBoxClips from web form
    if (request->hasParam("inputAmmoBoxClips")) {
      inputMessage = request->getParam("inputAmmoBoxClips")->value();
      ammoBoxClips = inputMessage.toInt(); 
    }
    // GET armourBoxPoints from web form
    if (request->hasParam("inputArmourBoxPoints")) {
      inputMessage = request->getParam("inputArmourBoxPoints")->value();
      armourBoxPoints = inputMessage.toInt(); 
    }
    // GET gameOptions from web form
    if (request->hasParam("inputGameOptions")) {
      inputMessage = request->getParam("inputGameOptions")->value();
      gameOptions = inputMessage.toInt(); 
    }
  });
// End of code for send a GET request for the form ---------------------------------------------------------------

Note: Once the variable is updated, it will only take effect when the program calls the changed variable.

Christian Content

1 Corinthians 14:6–12 (HCSB)
6 But now, brothers, if I come to you speaking in other languages, how will I benefit you unless I speak to you with a revelation or knowledge or prophecy or teaching? 7 Even inanimate things that produce sounds—whether flute or harp —if they don’t make a distinction in the notes, how will what is played on the flute or harp be recognised? 8 In fact, if the trumpet makes an unclear sound, who will prepare for battle? 9 In the same way, unless you use your tongue for intelligible speech, how will what is spoken be known? For you will be speaking into the air. 10 There are doubtless many different kinds of languages in the world, and all have meaning. 11 Therefore, if I do not know the meaning of the language, I will be a foreigner to the speaker, and the speaker will be a foreigner to me. 12 So also you—since you are zealous for spiritual gifts, seek to excel in building up the church.

A common language where everyone understands each other is great. You can say something, and it can be understood clearly. Language and protocol are very similar. When we talk about the Miles Tag 2 protocol we are talking about a common language that the guns use. It specifies things such as what each number in a shot packet refers to, and things like if the shot signal had a playerID of 10, every gun would understand the player name is “Flash”. If we introduce guns into the game using a different protocol, they cannot understand each other and the game fails. You may be able to shoot, but no one would get any damage, because the IR signals become unintelligible. You might as well just be shooting into the air. Any game goals would become useless, and your guns would become just like a cheap light blaster.

You may feel it is a shame that not all laser tag guns use the same protocol, and that you could just easily add more laser tag guns into the game, regardless of their brand or where you purchased it. At least with our guns they are compatible with the Miles Tag 2 system, and potentially when you learn to program you will be able to reinterpret the code to work with other systems.

The Bible in this passage refers to people that speak different languages. It could be a language like Greek or Japanese, or even the tongues of angels. Regardless of the language spoke, Paul’s point is that in the church, we need people to be able to understand each other, otherwise as in verse 9 – you will be speaking into the air. The Church cannot perform well when we cannot understand each other. For this reason, we need to ensure we are speaking in a way that can be understood.

Churches vary so much, and sometimes even for an experienced churchgoer, entering an unfamiliar church can feel like entering a foreign land. If the practices are not explained well, it can be difficult to know what is happening, or why certain things are being done. Some churches are very good at ensuring everyone understands, while other churches simply assume you should know what is happening, and things can remain a mystery for a long time.

Some good things that churches do to help people understand are:

  1. Having children’s programs which use simpler language to help children to understand.
  2. Having before church Bible classes for people who’s 2nd language is English, in this setting people can often get familiar with the passage before the preacher speaks.
  3. Classes for people investigating the faith, where they can ask clarifying questions.
  4. Bible studies that allow people to discuss and ask questions about what was said during the Bible Talk on Sunday.

I wonder if there is anyone in your church who could benefit from having someone help them to understand what is being communicated during church. As Paul said – seek to excel in building up the church.

The conclusion to 1 cor 14 is to be eager to prophesy. You may not have the spiritual gift of prophesy, but most Christians can read God’s word, and help others to understand it. In this way we act like prophets who are the mouthpiece of God.

Communication is important. It’s needed for:

  1. Laser tag guns to communicate with each other for an effective game
  2. For people at church to be able to communicate with each other in order to have an effective church.

Leave a Reply