Device Events
This is the full list of events a BattleCore tagger emits to your script, and the payload each one carries. For how event handlers are written and how states and modules nest, see States, Modules and Events.
Every payload field is read from evt.data, so a field listed here as playerId is accessed as evt.data.playerId. A payload shown as empty carries no fields at all.
Handler builder
Pick a state, module and event to generate a ready-to-paste handler.
state "IN_GAME" {
module "IR" {
event "IN" (EventData evt) => {
// evt.data.sensorId, evt.data.playerId, evt.data.teamId,
// evt.data.bulletTypeId, evt.data.hitValue, evt.data.isCritical
}
}
}State, module and event names are plain strings the runtime matches, so this snippet works on its own. The example scripts elsewhere use enum aliases (StateEnum.IN_GAME, ModuleEnum.IR, EventEnum.IN) for readability — define those enums if you prefer that style.
FSM — entering and leaving states
The FSM module reports state transitions. This is where most scripts do their setup work, since ENTER fires every time the device moves into that state.
ENTER | The device entered this state. |
EXIT | The device is leaving this state. |
Both carry evt.data.oldState and evt.data.newState, plus any fields the code that triggered the transition chose to pass along. A transition into DEAD, for example, carries the playerId of whoever landed the kill.
state StateEnum.DEAD {
module ModuleEnum.FSM {
event EventEnum.ENTER (EventData evt) => {
battlecore::screens.setScreen("DEAD");
battlecore::net.send(EventEnum.PLAYER_COMMAND_KILL_CONFIRMED, {"byId": evt.data.playerId});
}
}
}Buttons
A tagger has three buttons, each its own module: INPUT_TRIGGER, INPUT_RELOAD and INPUT_AUX. All three emit the same events.
DOWN | The button was pressed (after a 5ms debounce). |
UP | The button was released. |
HOLD | Fired once, 1 second after DOWN, while the button is still held. It does not repeat. |
PRESS | A short press: released before the 1 second hold threshold, in the same state the press began in. |
A press long enough to fire HOLD never produces a PRESS, so the two are safe to handle on the same button without both firing. PRESS also requires the release to happen in the same state as the press, which stops a button that changes state from firing again in the state it just moved to. When both fire, UP always arrives before PRESS.
A connected phone app can inject these same button events, so a handler may run without anyone touching the physical device.
IR — being hit
The IR module emits a single IN event each time this device is hit, whether the shot was picked up by the tagger itself or reported by a paired headset.
sensorId | Which sensor detected the hit. |
playerId | The player id of whoever fired the shot. |
teamId | The team id of whoever fired the shot. |
bulletTypeId | The type of bullet or weapon that was fired. |
hitValue | The magnitude of the hit, used as damage or healing depending on bullet type. |
isCritical | Set when the shot was a critical hit. |
Hits are not filtered before they reach your script. Shooting yourself, or a team mate shooting you, both arrive as ordinary IN events, so your script decides what counts.
module ModuleEnum.IR {
event EventEnum.IN (EventData evt) => {
// Ignore friendly fire in team games
if (battlecore::game.getIsTeamBased() == true && evt.data.teamId == battlecore::player.getTeamId()) {
return;
}
battlecore::player.takeDamage(evt.data.hitValue);
}
}Hits reported by a headset may omit any field except sensorId, so check a field exists before relying on it if your game supports headsets.
P2P — messages from other devices
The P2P module carries everything that arrives from other devices over the mesh: lobby discovery, game setup, and in game player events. The event name is the message type.
Every P2P event carries these fields in addition to the ones listed per event:
senderMac | The 6 byte hardware address of the device that sent the message. |
rssi | Signal strength of the received message, useful for estimating distance. |
messageType | 1 = command, 2 = request, 3 = response, 4 = mesh broadcast. |
commandId | The numeric id behind the event name. |
senderPlayerId | On mesh broadcasts, the player id the message originated from. |
Events
ACKNOWLEDGEMENT | gameId, ackCommandId |
CLIENT_LOBBY_PING | — |
HOST_LOBBY_BEACON | gameId, playerCount, time, name |
HOST_LOBBY_DESTROYED | gameId |
CLIENT_REQUEST_JOIN_LOBBY | name |
HOST_RESPONSE_JOIN_LOBBY | result (1 = joined), id |
CLIENT_RESPONSE_JOINED_LOBBY | gameId, id, name |
CLIENT_COMMAND_SIGNAL_READY_STATE | gameId, id, state (1 = ready) |
CLIENT_COMMAND_LEAVE_LOBBY | gameId, id |
HOST_COMMAND_LEAVE_LOBBY | reason |
HOST_COMMAND_PLAYER_LEFT_LOBBY | gameId, id |
HOST_COMMAND_GAME_SETTINGS_UPDATE | gameId, bstId, gameName, isTeamBased, gameDurationMins, radarType, mapType, playerLives |
HOST_COMMAND_GAME_PRE_START | gameId, eventTime, countdownSecs |
CLIENT_GAME_PRE_START_COMPLETE | — |
HOST_COMMAND_GAME_PRE_START_CANCEL | gameId |
HOST_COMMAND_GAME_START | gameId |
HOST_COMMAND_GAME_PAUSED_STATE | gameId, state (1 = paused) |
CLIENT_COMMAND_GAME_PAUSE | gameId |
HOST_COMMAND_GAME_ENDED | gameId, endType (0 score, 1 time, 2 condition, 3 forced) |
PLAYER_COMMAND_HIT_CONFIRMED | gameId, type (0 damage, 1 heal), amount, byId |
PLAYER_COMMAND_DOWN_CONFIRMED | gameId, byId |
PLAYER_COMMAND_REVIVE_CONFIRMED | gameId, byId |
PLAYER_COMMAND_KILL_CONFIRMED | gameId, byId |
PLAYER_COMMAND_RESPAWNED | gameId |
PLAYER_COMMAND_PERMA_DEATH | gameId |
HOST_BROADCAST_PLAYER_LIST | gameId, playerCount |
HOST_BROADCAST_PLAYER_UPDATE | gameId, playerId, macAddress, playerName, teamId, livesRemaining, isReady, isConnected, killCount, deathCount, points, lastSeenTimestamp |
MESH_TEST_PING | pingSeq |
HOME_HELLO | — |
UPDATE_CHECK | groupHash |
GAME_FOUND | Same keys as HOST_LOBBY_BEACON. Emitted the first time a game is discovered while joining. |
GAME_LOST | gameId. Emitted when a discovered game shuts its lobby down. |
Use battlecore::net to send these messages to other devices.
Device state changes
Every value the device tracks emits a CHANGE event when it changes, and the module name is the value's own name. So to react to ammo changing you handle CHANGE on the WEAPON_AMMO module. The new value arrives as evt.data.value.
module ModuleEnum.PLAYER_SHIELD {
event EventEnum.CHANGE (EventData evt) => {
if (evt.data.value == 0) {
battlecore::audio.groupStart(AudioGroupEnum.SHIELD_DOWN);
}
}
}A CHANGE only fires when the value actually differs from what it was, so setting a value to what it already holds emits nothing.
Player
PLAYER_ID | This player’s id. |
PLAYER_TEAM_ID | This player’s team id. |
PLAYER_NAME | This player’s display name. |
PLAYER_READY | Whether the player has signalled ready in the lobby. |
PLAYER_SHIELD | Current shield value. |
PLAYER_SHIELD_MAX | Maximum shield value. |
PLAYER_SHIELD_INITIAL | Shield value the player starts with. |
PLAYER_SHIELD_FULL_RECHARGE_TIME | Milliseconds for a full shield recharge. 0 means the shield is not recharging. |
PLAYER_ARMOUR | Current armour value. |
PLAYER_ARMOUR_MAX | Maximum armour value. |
PLAYER_ARMOUR_INITIAL | Armour value the player starts with. |
PLAYER_LIVES | Lives remaining. |
PLAYER_LIVES_MAX | Maximum lives. |
PLAYER_LIVES_INITIAL | Lives the player starts with. |
PLAYER_POINTS | Score. May be negative. |
PLAYER_KILL_COUNT | Number of kills. |
PLAYER_DEATH_COUNT | Number of deaths. |
PLAYER_IS_INVULNERABLE | Whether the player currently cannot be damaged. |
PLAYER_KILLED_BY_ID | Player id of whoever last killed this player. |
PLAYER_KILLED_BY_NAME | Name of whoever last killed this player. Empty when they are not in the roster. |
COUNTDOWN_SECS | Seconds remaining on the current countdown, such as respawn. |
Weapon
WEAPON_AMMO | Rounds currently loaded. |
WEAPON_AMMO_MAX | Magazine capacity. |
WEAPON_SHOTS_FIRED | Total shots fired this game. |
WEAPON_SHOT_POWER | Damage carried by each shot. |
WEAPON_SHOT_TYPE | The bullet type being fired. |
WEAPON_SHOT_INTERVAL_MS | Minimum milliseconds between shots. |
WEAPON_SHOT_DELAY_MS | Delay before a shot leaves the weapon. |
WEAPON_SHOT_CHARGE_MIN_MS | Minimum charge time for a charge based weapon. |
WEAPON_SHOT_CHARGE_MAX_MS | Charge time at which the weapon is fully charged. |
WEAPON_SHOT_CHARGE_AUTO_FIRE | Whether a full charge fires automatically rather than on release. |
WEAPON_IS_CHARGE_BASED | Whether the weapon charges before firing. |
WEAPON_IS_CHARGING | Whether the weapon is charging right now. |
WEAPON_RELOAD_DELAY_MS | Milliseconds a reload takes. |
WEAPON_BUSY_COUNT | How many actions are currently making the weapon busy. This is a count, not a flag, so values above 1 are normal when actions overlap. |
Game
GAME_CONNECTED | Whether this device is connected to a game. |
GAME_PLAYER_COUNT | Number of players in the game. |
GAME_HOST_MAC | Hardware address of the hosting device. |
GAME_DISPLAY_NAME | The game’s display name. |
GAME_SCRIPT_ID | Id of the game script in use. |
GAME_SCRIPT_LABEL | Human readable label for the game script. |
GAME_IS_TEAM_BASED | Whether the game is team based. |
GAME_TIME_MAX_MINS | Game duration in minutes. |
GAME_RESPAWN_MODE | How respawning works. 0 allows player initiated respawns. |
GAME_RADAR_TYPE | 0 off, 1 movement based, 2 permanent. |
GAME_MAP_TYPE | 0 unlimited, 1 limited. |
NFC
NFC_TAG | The id of the tag currently held against the reader. Empty when no tag is present, so this changing is how you detect a tag arriving or leaving. |
NFC_DATA | Text or link stored on the last tag read. Set just before NFC_TAG, and deliberately not cleared when the tag is removed. |
GPS
GPS_LATITUDE | Current latitude. Only updated once the fix is valid. |
GPS_LONGITUDE | Current longitude. Only updated once the fix is valid. |
GPS_SATELLITES | Number of satellites currently locked on. |
Device
DEVICE_ROLE | Whether this device is hosting, joining, or acting as an operator. |
DEVICE_WIFI_STATUS | 0 disconnected, 1 connecting, 2 connected. |
DEVICE_BLE_MAC | This device’s Bluetooth address. |
DEVICE_BLE_COUNT | How many Bluetooth devices are connected. |
DEVICE_APP_CONNECTED | Whether a phone app is connected. |
AUDIO_PACK | The audio pack currently in use. |
WIFI
The WIFI module reports connection progress. Unlike other modules its payload is a plain message string rather than a set of fields, read as evt.data on its own.
CONNECTING | Connection attempt started. The message names the network. |
CONNECTED | Associated with the network. The message is the network name. |
GOT_IP | An IP address was assigned. The message is the IP address. |
CONNECTION_FAILED | The attempt failed. The message explains why. |
CONNECTION_LOST | An established connection dropped. |
RECONNECTING | Retrying a dropped connection. The message is the network name. |
DISCONNECTED_INTENTIONAL | Disconnected on purpose rather than by failure. |
NOT_CONNECTED | No connection is currently established. |
WIFI_DISCOVERED | A network was found during a scan. The message is its name. |
SCAN_DONE | A scan finished. |
WIFI_SCAN_TIMEOUT | A scan timed out before completing. |
STA_START | The WiFi station interface started. |
STA_STOP | The WiFi station interface stopped. |
Bluetooth and the app
BLE / CONNECT | A Bluetooth device connected. No payload. |
BLE / DISCONNECT | A Bluetooth device disconnected. No payload. |
APP_KEYBOARD / VALUE | The app sent typed text. The text is the payload, read as evt.data. |
APP / CHECK_UPDATE | The app asked the device to check for a firmware update. evt.data.broadcast is set when every device in the group should check, rather than just this one. |
Firmware updates
Update progress arrives on four modules: VERSION and UPDATE for the firmware itself, FS_VERSION and FS_UPDATE for the data it ships with. Each payload is a plain message string read as evt.data.
STATUS | Progress text while the check runs. Emitted by VERSION and FS_VERSION. |
NEW | A newer version is available. The payload is the version. |
CURRENT | Already up to date. The payload is the version that was checked against. |
SUCCESS | The update finished. Emitted by FS_UPDATE only. |
FAILED | The check or update failed. The payload explains why. |
A successful firmware update restarts the device immediately, so there is no SUCCESS event on UPDATE to handle.
Related Topics
- States, Modules and Events — how handlers are written and matched.
- battlecore::fsm — reading and changing the current state.
- battlecore::net — sending P2P messages to other devices.
- Enums — declaring the module and event names your handlers bind to.