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.

ENTERThe device entered this state.
EXITThe 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.

DOWNThe button was pressed (after a 5ms debounce).
UPThe button was released.
HOLDFired once, 1 second after DOWN, while the button is still held. It does not repeat.
PRESSA 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.

sensorIdWhich sensor detected the hit.
playerIdThe player id of whoever fired the shot.
teamIdThe team id of whoever fired the shot.
bulletTypeIdThe type of bullet or weapon that was fired.
hitValueThe magnitude of the hit, used as damage or healing depending on bullet type.
isCriticalSet 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:

senderMacThe 6 byte hardware address of the device that sent the message.
rssiSignal strength of the received message, useful for estimating distance.
messageType1 = command, 2 = request, 3 = response, 4 = mesh broadcast.
commandIdThe numeric id behind the event name.
senderPlayerIdOn mesh broadcasts, the player id the message originated from.

Events

ACKNOWLEDGEMENTgameId, ackCommandId
CLIENT_LOBBY_PING
HOST_LOBBY_BEACONgameId, playerCount, time, name
HOST_LOBBY_DESTROYEDgameId
CLIENT_REQUEST_JOIN_LOBBYname
HOST_RESPONSE_JOIN_LOBBYresult (1 = joined), id
CLIENT_RESPONSE_JOINED_LOBBYgameId, id, name
CLIENT_COMMAND_SIGNAL_READY_STATEgameId, id, state (1 = ready)
CLIENT_COMMAND_LEAVE_LOBBYgameId, id
HOST_COMMAND_LEAVE_LOBBYreason
HOST_COMMAND_PLAYER_LEFT_LOBBYgameId, id
HOST_COMMAND_GAME_SETTINGS_UPDATEgameId, bstId, gameName, isTeamBased, gameDurationMins, radarType, mapType, playerLives
HOST_COMMAND_GAME_PRE_STARTgameId, eventTime, countdownSecs
CLIENT_GAME_PRE_START_COMPLETE
HOST_COMMAND_GAME_PRE_START_CANCELgameId
HOST_COMMAND_GAME_STARTgameId
HOST_COMMAND_GAME_PAUSED_STATEgameId, state (1 = paused)
CLIENT_COMMAND_GAME_PAUSEgameId
HOST_COMMAND_GAME_ENDEDgameId, endType (0 score, 1 time, 2 condition, 3 forced)
PLAYER_COMMAND_HIT_CONFIRMEDgameId, type (0 damage, 1 heal), amount, byId
PLAYER_COMMAND_DOWN_CONFIRMEDgameId, byId
PLAYER_COMMAND_REVIVE_CONFIRMEDgameId, byId
PLAYER_COMMAND_KILL_CONFIRMEDgameId, byId
PLAYER_COMMAND_RESPAWNEDgameId
PLAYER_COMMAND_PERMA_DEATHgameId
HOST_BROADCAST_PLAYER_LISTgameId, playerCount
HOST_BROADCAST_PLAYER_UPDATEgameId, playerId, macAddress, playerName, teamId, livesRemaining, isReady, isConnected, killCount, deathCount, points, lastSeenTimestamp
MESH_TEST_PINGpingSeq
HOME_HELLO
UPDATE_CHECKgroupHash
GAME_FOUNDSame keys as HOST_LOBBY_BEACON. Emitted the first time a game is discovered while joining.
GAME_LOSTgameId. 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_IDThis player’s id.
PLAYER_TEAM_IDThis player’s team id.
PLAYER_NAMEThis player’s display name.
PLAYER_READYWhether the player has signalled ready in the lobby.
PLAYER_SHIELDCurrent shield value.
PLAYER_SHIELD_MAXMaximum shield value.
PLAYER_SHIELD_INITIALShield value the player starts with.
PLAYER_SHIELD_FULL_RECHARGE_TIMEMilliseconds for a full shield recharge. 0 means the shield is not recharging.
PLAYER_ARMOURCurrent armour value.
PLAYER_ARMOUR_MAXMaximum armour value.
PLAYER_ARMOUR_INITIALArmour value the player starts with.
PLAYER_LIVESLives remaining.
PLAYER_LIVES_MAXMaximum lives.
PLAYER_LIVES_INITIALLives the player starts with.
PLAYER_POINTSScore. May be negative.
PLAYER_KILL_COUNTNumber of kills.
PLAYER_DEATH_COUNTNumber of deaths.
PLAYER_IS_INVULNERABLEWhether the player currently cannot be damaged.
PLAYER_KILLED_BY_IDPlayer id of whoever last killed this player.
PLAYER_KILLED_BY_NAMEName of whoever last killed this player. Empty when they are not in the roster.
COUNTDOWN_SECSSeconds remaining on the current countdown, such as respawn.

Weapon

WEAPON_AMMORounds currently loaded.
WEAPON_AMMO_MAXMagazine capacity.
WEAPON_SHOTS_FIREDTotal shots fired this game.
WEAPON_SHOT_POWERDamage carried by each shot.
WEAPON_SHOT_TYPEThe bullet type being fired.
WEAPON_SHOT_INTERVAL_MSMinimum milliseconds between shots.
WEAPON_SHOT_DELAY_MSDelay before a shot leaves the weapon.
WEAPON_SHOT_CHARGE_MIN_MSMinimum charge time for a charge based weapon.
WEAPON_SHOT_CHARGE_MAX_MSCharge time at which the weapon is fully charged.
WEAPON_SHOT_CHARGE_AUTO_FIREWhether a full charge fires automatically rather than on release.
WEAPON_IS_CHARGE_BASEDWhether the weapon charges before firing.
WEAPON_IS_CHARGINGWhether the weapon is charging right now.
WEAPON_RELOAD_DELAY_MSMilliseconds a reload takes.
WEAPON_BUSY_COUNTHow 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_CONNECTEDWhether this device is connected to a game.
GAME_PLAYER_COUNTNumber of players in the game.
GAME_HOST_MACHardware address of the hosting device.
GAME_DISPLAY_NAMEThe game’s display name.
GAME_SCRIPT_IDId of the game script in use.
GAME_SCRIPT_LABELHuman readable label for the game script.
GAME_IS_TEAM_BASEDWhether the game is team based.
GAME_TIME_MAX_MINSGame duration in minutes.
GAME_RESPAWN_MODEHow respawning works. 0 allows player initiated respawns.
GAME_RADAR_TYPE0 off, 1 movement based, 2 permanent.
GAME_MAP_TYPE0 unlimited, 1 limited.

NFC

NFC_TAGThe 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_DATAText or link stored on the last tag read. Set just before NFC_TAG, and deliberately not cleared when the tag is removed.

GPS

GPS_LATITUDECurrent latitude. Only updated once the fix is valid.
GPS_LONGITUDECurrent longitude. Only updated once the fix is valid.
GPS_SATELLITESNumber of satellites currently locked on.

Device

DEVICE_ROLEWhether this device is hosting, joining, or acting as an operator.
DEVICE_WIFI_STATUS0 disconnected, 1 connecting, 2 connected.
DEVICE_BLE_MACThis device’s Bluetooth address.
DEVICE_BLE_COUNTHow many Bluetooth devices are connected.
DEVICE_APP_CONNECTEDWhether a phone app is connected.
AUDIO_PACKThe 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.

CONNECTINGConnection attempt started. The message names the network.
CONNECTEDAssociated with the network. The message is the network name.
GOT_IPAn IP address was assigned. The message is the IP address.
CONNECTION_FAILEDThe attempt failed. The message explains why.
CONNECTION_LOSTAn established connection dropped.
RECONNECTINGRetrying a dropped connection. The message is the network name.
DISCONNECTED_INTENTIONALDisconnected on purpose rather than by failure.
NOT_CONNECTEDNo connection is currently established.
WIFI_DISCOVEREDA network was found during a scan. The message is its name.
SCAN_DONEA scan finished.
WIFI_SCAN_TIMEOUTA scan timed out before completing.
STA_STARTThe WiFi station interface started.
STA_STOPThe WiFi station interface stopped.

Bluetooth and the app

BLE / CONNECTA Bluetooth device connected. No payload.
BLE / DISCONNECTA Bluetooth device disconnected. No payload.
APP_KEYBOARD / VALUEThe app sent typed text. The text is the payload, read as evt.data.
APP / CHECK_UPDATEThe 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.

STATUSProgress text while the check runs. Emitted by VERSION and FS_VERSION.
NEWA newer version is available. The payload is the version.
CURRENTAlready up to date. The payload is the version that was checked against.
SUCCESSThe update finished. Emitted by FS_UPDATE only.
FAILEDThe 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