Time 30
Every laser tag system operates in slightly different ways, depending on the priorities of the designer. When creating our laser tag guns, we have the option to either start from scratch in terms of game specifications or choose to make our guns compatible with another system. In this case, I 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:
- Shot packet
- Message packed
- Cloning Signal
While there is much to implement, the first step is to add all the variables, which can then be programmed to become functional at a later date. The Miles Tag protocol also specifies player names and team names.
In this tutorial we will:
- Declare all the Miles Tag 2 protocol variables in our program
- 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.
First of all, make an existing copy of the code from the previous tutorial, saving it as: NodeMCU_LaserTag_S04
Declaring the Game Variables
The variables are listed in the order of the Cloning Data signal, which is part of the Miles Tag specifications. This signal determines how the guns perform in the game and allows for easy modifications to change their behavior.
You can simply cut and paste this code into your main program. You will notice that the list of variables has significantly increased compared to the previous version of your program.
These variables should be placed under your teamID and playerID variables.
// 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
// Milestag GameMode Settings
bool zombieMode = 0;
bool friendlyFire = 0;
bool unlimitedAmmo = 0;
bool respawnFlash = 1;
bool flagFlash = 1;
bool gameBoxRoR = 0;
bool gameBoxStay = 1;
bool bodyArmour = 0;
bool zombieFlash = 0;
bool nearMiss = 1;
bool flagEnd = 1;
bool AmmoRoR = 1;
Adding the player and team names
It is important that each gun refers to the same player name, given a playerID. To achieve this, we will create a function that allows us to input the playerID as a number and returns the playerName as a string.
- Create a new tab called MilesTagMapping
- 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.
- Go to the WebActions tab in your Arduino software
- We will be adding two additional placeholders. PLACEHOLDER_PlayerName and PLACEHOLDER_TeamName. The return strings should be playerName(playerID) and teamName(teamID) respectively.
- Your code for the String processor in WebActions should now resemble the following:
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();
}
- Go to indexPage.h tab in Arduino
- 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 on your NodeMCU board and upload the saved binary through the web interface: http://[nodeMCU IP address]/update.
You should now see the player name and team colour change when you modify the variables through the web interface.
Notice the error
We allow the user to enter up to 99 playerIDs through the web interface. However, we should limit this to 50 to ensure that the gun name is not set to an unknown player or a different type of game object. Please try to solve this issue on your own. As a hint, you will need to make changes in the indexPage.h tab.
Milestag mapped variables
Milestag aims to minimize data by reducing the length of the shot pulses. One approach to achieving this is through a process referred to as mapping, as described in the Milestag document.
In the table below, you can find examples of mapped variables, such as Damage per shot.
Value | Damage Dealt |
---|---|
0x00 | 1 |
0x01 | 2 |
0x02 | 4 |
0x03 | 5 |
0x04 | 7 |
0x05 | 10 |
0x06 | 15 |
0x07 | 17 |
0x08 | 20 |
0x09 | 25 |
0x0A | 30 |
0x0B | 35 |
0x0C | 40 |
0x0D | 50 |
0x0E | 75 |
0x0F | 100 |
Sometimes, there are straightforward patterns in the mappings that can be utilised to reduce the code by implementing loops and if statements. However, when the mapping is random, it becomes necessary to use switch and case statements. The following code should be placed 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 the MilesTag values need to be changed, modifications must be made in the program, followed by recompiling and uploading the program. This process can be time-consuming, right? A simpler solution would be to modify the variables directly through the web interface.
- 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.
- 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"
- 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);
});
- 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.
Video of the coding aspects:
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 that everyone understands is essential for effective communication. When we talk about the Miles Tag 2 protocol, we are referring to a standardized language that laser tag guns use. This protocol specifies important information such as the meaning of each number in a shot packet and the association between a player ID and a player name. If guns with different protocols are introduced into the game, they won’t be able to understand each other, resulting in a failed game. In such a scenario, shooting would be pointless as the IR signals would be unintelligible. It would be as if you were shooting into thin air, rendering game goals useless and reducing your guns to nothing more than cheap light blasters.
It’s unfortunate that not all laser tag guns use the same protocol, making it challenging to add guns from different brands or sources to the game. However, our guns are compatible with the Miles Tag 2 system, and if you learn programming, you may be able to adapt the code to work with other systems.
In this passage, the Bible refers to people speaking different languages, whether it be Greek, Japanese, or even angelic tongues. Paul’s point is that in the church, understanding between individuals is crucial. Otherwise, as stated in verse 9, speaking becomes meaningless. A church cannot function effectively if its members cannot understand each other. Therefore, it is important to ensure that communication is clear and comprehensible.
Churches vary greatly, and even experienced churchgoers can feel like outsiders when entering an unfamiliar church. Without proper explanation, it can be difficult to comprehend the purpose of certain practices. Some churches excel at ensuring everyone understands, while others assume prior knowledge, leaving many things shrouded in mystery for extended periods of time.
To facilitate understanding, churches implement various strategies such as:
- Offering children’s programs that use simpler language to help young ones comprehend.
- Conducting Bible classes before church for individuals whose second language is English, allowing them to familiarize themselves with the passage before the sermon.
- Organizing classes for those exploring the faith, where they can ask questions for clarification.
- Hosting Bible studies that encourage discussion and questions about the sermon.
Consider whether there are individuals in your church who would benefit from someone helping them understand the messages conveyed during church gatherings. As Paul said, let us strive to build up the church.
The conclusion of 1 Corinthians 14 emphasizes the importance of eagerly desiring the gift of prophecy. While not everyone may possess this spiritual gift, most Christians can read God’s word and assist others in understanding it. In this way, we serve as mouthpieces for God, acting like prophets.
Communication is important. It’s needed for:
- Laser tag guns to communicate with each other for an effective game
- For people in a church to be able to communicate with each other to have an healthy church.