Learn how to create an interactive chatbot plugin that responds to your in-game messages! This tutorial will teach you how to listen for chat messages, process commands, and send responses back to the game chat.
By the end of this tutorial, you'll have created a chatbot plugin that:
!hello
, !help
, !time
)Before starting, you should have:
The DeadZone API provides the OnChatMessage
event that fires whenever a chat message appears in-game. This includes:
We'll use this event to detect commands and respond accordingly.
Simple Chatbot
A chatbot that responds to commands in chat
Utility
Open the main.js tab and start with this basic structure:
// ============================================
// Simple Chatbot Plugin
// Responds to chat commands with custom messages
// ============================================
// Store plugin state
var isRunning = false;
function OnStart() {
isRunning = true;
Game.sendGameMessage("Chatbot is now active! Type !help for commands.", "Chatbot");
}
function OnShutdown() {
isRunning = false;
Game.sendGameMessage("Chatbot has been stopped.", "Chatbot");
}
function OnGameTick() {
// Main logic can go here if needed
}
What's happening:
isRunning
to track if the bot is activeGame.sendGameMessage()
sendGameMessage()
is the prefix shown in brackets: [Chatbot] Message here
Now add the chat message event handler. Add this function below the OnGameTick function:
/**
* @param {ChatMessage} event
*/
function OnChatMessage(event) {
// Check if the bot is running
if (!isRunning) {
return;
}
// Get the message that was sent
var message = event.getMessage();
var sender = event.getName();
var messageType = event.getType();
// Only respond to your own messages
var localPlayer = Client.getLocalPlayer();
var myName = localPlayer.getName();
if (sender !== myName) {
return; // Ignore messages from other players
}
// Debug: Print the message to console
Utility.print("You said: " + message);
// Process commands
processCommand(message);
}
What's happening:
@param {ChatMessage} event
comment helps with autocompleteprocessCommand()
function to handle the logicAdd this function to handle different commands:
function processCommand(message) {
// Convert message to lowercase for easier matching
var command = message.toLowerCase().trim();
// Check for different commands
if (command === "!hello" || command === "!hi") {
respondToHello();
}
else if (command === "!help") {
respondToHelp();
}
else if (command === "!time") {
respondToTime();
}
else if (command === "!stats") {
respondToStats();
}
else if (command.startsWith("!echo ")) {
respondToEcho(message);
}
else if (command.startsWith("!")) {
// Unknown command
Game.sendGameMessage("Unknown command. Type !help for available commands.", "Chatbot");
}
}
What's happening:
startsWith()
lets us detect commands with parameters (like !echo Hello World
)!
get a helpful error messageNow create the individual response functions:
function respondToHello() {
Game.sendGameMessage("Hello there! How can I help you today?", "Chatbot");
}
function respondToHelp() {
Game.sendGameMessage("Available commands:", "Chatbot");
Game.sendGameMessage("!hello - Greet the bot", "Chatbot");
Game.sendGameMessage("!time - Get current time", "Chatbot");
Game.sendGameMessage("!stats - Show your combat level", "Chatbot");
Game.sendGameMessage("!echo <message> - Repeat your message", "Chatbot");
}
function respondToTime() {
// JavaScript Date object for current time
var now = new Date();
var timeString = now.toLocaleTimeString();
Game.sendGameMessage("Current time is: " + timeString, "Chatbot");
}
function respondToStats() {
var player = Client.getLocalPlayer();
var combatLevel = player.getCombatLevel();
var totalLevel = Client.getTotalLevel();
Game.sendGameMessage("Combat Level: " + combatLevel, "Chatbot");
Game.sendGameMessage("Total Level: " + totalLevel, "Chatbot");
}
function respondToEcho(message) {
// Extract the text after "!echo "
var echoText = message.substring(6); // Remove "!echo " (6 characters)
Game.sendGameMessage("You said: " + echoText, "Chatbot");
}
What's happening:
Game.sendGameMessage()
respondToTime()
uses JavaScript's Date objectrespondToStats()
uses the DeadZone API to get player informationrespondToEcho()
extracts text after the command using substring()
Open the config.js tab and add these configuration items:
const config = {
enableBot: ConfigItem.createBoolean(
"enableBot",
"General",
"Enable Chatbot",
"Toggle the chatbot on/off",
true
),
commandPrefix: ConfigItem.createString(
"commandPrefix",
"General",
"Command Prefix",
"Character(s) used to trigger commands (default: !)",
"!"
),
botName: ConfigItem.createString(
"botName",
"General",
"Bot Name",
"Name shown in chat messages",
"Chatbot"
),
respondToOthers: ConfigItem.createBoolean(
"respondToOthers",
"Advanced",
"Respond to Others",
"Allow bot to respond to other players' messages",
false
),
debugMode: ConfigItem.createBoolean(
"debugMode",
"Debug",
"Debug Mode",
"Print debug messages to console",
false
)
};
const overlay = {
// We'll add overlay items in the next tutorial
};
Update your main.js to use the configuration:
Replace the hard-coded values with config values:
function OnStart() {
isRunning = true;
var botName = config.botName.getValue();
Game.sendGameMessage("Chatbot is now active! Type !help for commands.", botName);
}
function OnShutdown() {
isRunning = false;
var botName = config.botName.getValue();
Game.sendGameMessage("Chatbot has been stopped.", botName);
}
Update the chat event handler to check the config:
function OnChatMessage(event) {
// Check if bot is enabled in config
if (!isRunning || !config.enableBot.getValue()) {
return;
}
var message = event.getMessage();
var sender = event.getName();
var localPlayer = Client.getLocalPlayer();
var myName = localPlayer.getName();
// Check if we should respond to this message
var respondToOthers = config.respondToOthers.getValue();
if (!respondToOthers && sender !== myName) {
return;
}
// Debug logging
if (config.debugMode.getValue()) {
Utility.print("[Chatbot] Processing message: " + message);
}
processCommand(message);
}
Update the command processor to use the config prefix:
function processCommand(message) {
var prefix = config.commandPrefix.getValue();
var command = message.toLowerCase().trim();
// Check if message starts with the command prefix
if (!command.startsWith(prefix)) {
return; // Not a command
}
// Remove prefix for easier matching
var cleanCommand = command.substring(prefix.length);
if (cleanCommand === "hello" || cleanCommand === "hi") {
respondToHello();
}
else if (cleanCommand === "help") {
respondToHelp();
}
else if (cleanCommand === "time") {
respondToTime();
}
else if (cleanCommand === "stats") {
respondToStats();
}
else if (cleanCommand.startsWith("echo ")) {
respondToEcho(message);
}
else {
var botName = config.botName.getValue();
Game.sendGameMessage("Unknown command. Type " + prefix + "help for commands.", botName);
}
}
!help
- Should list all commands!hello
- Should greet you!time
- Should show current time!stats
- Should show your stats!echo Testing 123
- Should repeat "Testing 123"Let's add some more interesting commands. Add these functions:
function respondToLocation() {
var player = Client.getLocalPlayer();
var worldPoint = player.getWorldLocation();
var x = worldPoint.getX();
var y = worldPoint.getY();
var z = worldPoint.getPlane();
var botName = config.botName.getValue();
Game.sendGameMessage("Your location: (" + x + ", " + y + ", " + z + ")", botName);
}
function respondToInventory() {
var items = Game.info.inventory.getItems();
var count = 0;
for (var i = 0; i < items.length; i++) {
if (items[i] != null) {
count++;
}
}
var botName = config.botName.getValue();
Game.sendGameMessage("You have " + count + " items in your inventory.", botName);
}
function respondToHP() {
var currentHP = Client.getBoostedSkillLevels(Skill.HITPOINTS);
var maxHP = Client.getRealSkillLevels(Skill.HITPOINTS);
var botName = config.botName.getValue();
Game.sendGameMessage("HP: " + currentHP + "/" + maxHP, botName);
}
Then add them to your command processor:
function processCommand(message) {
var prefix = config.commandPrefix.getValue();
var command = message.toLowerCase().trim();
if (!command.startsWith(prefix)) {
return;
}
var cleanCommand = command.substring(prefix.length);
if (cleanCommand === "hello" || cleanCommand === "hi") {
respondToHello();
}
else if (cleanCommand === "help") {
respondToHelp();
}
else if (cleanCommand === "time") {
respondToTime();
}
else if (cleanCommand === "stats") {
respondToStats();
}
else if (cleanCommand === "location" || cleanCommand === "loc") {
respondToLocation();
}
else if (cleanCommand === "inventory" || cleanCommand === "inv") {
respondToInventory();
}
else if (cleanCommand === "hp" || cleanCommand === "health") {
respondToHP();
}
else if (cleanCommand.startsWith("echo ")) {
respondToEcho(message);
}
else {
var botName = config.botName.getValue();
Game.sendGameMessage("Unknown command. Type " + prefix + "help for commands.", botName);
}
}
Don't forget to update the help command:
function respondToHelp() {
var prefix = config.commandPrefix.getValue();
var botName = config.botName.getValue();
Game.sendGameMessage("Available commands:", botName);
Game.sendGameMessage(prefix + "hello - Greet the bot", botName);
Game.sendGameMessage(prefix + "time - Get current time", botName);
Game.sendGameMessage(prefix + "stats - Show your combat level", botName);
Game.sendGameMessage(prefix + "location - Show your coordinates", botName);
Game.sendGameMessage(prefix + "inventory - Count inventory items", botName);
Game.sendGameMessage(prefix + "hp - Check your hitpoints", botName);
Game.sendGameMessage(prefix + "echo <msg> - Repeat your message", botName);
}
Prevent spam by adding a cooldown:
var lastCommandTime = 0;
var COMMAND_COOLDOWN_MS = 1000; // 1 second cooldown
function processCommand(message) {
var prefix = config.commandPrefix.getValue();
var command = message.toLowerCase().trim();
if (!command.startsWith(prefix)) {
return;
}
// Check cooldown
var now = Date.now();
if (now - lastCommandTime < COMMAND_COOLDOWN_MS) {
var botName = config.botName.getValue();
Game.sendGameMessage("Please wait before using another command.", botName);
return;
}
lastCommandTime = now;
// Rest of the command processing...
}
Allow multiple ways to trigger the same command:
var commandAliases = {
"h": "help",
"?": "help",
"hi": "hello",
"hey": "hello",
"loc": "location",
"pos": "location",
"inv": "inventory",
"health": "hp"
};
function processCommand(message) {
var prefix = config.commandPrefix.getValue();
var command = message.toLowerCase().trim();
if (!command.startsWith(prefix)) {
return;
}
var cleanCommand = command.substring(prefix.length);
// Check for aliases
if (commandAliases[cleanCommand]) {
cleanCommand = commandAliases[cleanCommand];
}
// Rest of processing...
}
Handle commands with spaces:
else if (cleanCommand.startsWith("say ")) {
var text = cleanCommand.substring(4);
Game.typeMessage(text); // Types the message in chat
}
else if (cleanCommand.startsWith("search ")) {
var searchTerm = cleanCommand.substring(7);
respondToSearch(searchTerm);
}
The event.getType()
returns different types of messages:
function OnChatMessage(event) {
var messageType = event.getType();
// Different message types:
// ChatMessageType.PUBLICCHAT - Public chat messages
// ChatMessageType.MODCHAT - Moderator chat
// ChatMessageType.PRIVATECHAT - Private messages
// ChatMessageType.PRIVATECHATOUT - Outgoing private messages
// ChatMessageType.FRIENDSCHAT - Clan chat
// ChatMessageType.GAMEMESSAGE - Game messages
if (messageType === ChatMessageType.PUBLICCHAT) {
// Only process public chat
processCommand(event.getMessage());
}
}
Here's the full main.js for your chatbot:
// ============================================
// Simple Chatbot Plugin
// Responds to chat commands with custom messages
// ============================================
var isRunning = false;
var lastCommandTime = 0;
var COMMAND_COOLDOWN_MS = 1000;
function OnStart() {
isRunning = true;
var botName = config.botName.getValue();
Game.sendGameMessage("Chatbot is now active! Type !help for commands.", botName);
}
function OnShutdown() {
isRunning = false;
var botName = config.botName.getValue();
Game.sendGameMessage("Chatbot has been stopped.", botName);
}
function OnGameTick() {
// Main tick logic (if needed)
}
/**
* @param {ChatMessage} event
*/
function OnChatMessage(event) {
if (!isRunning || !config.enableBot.getValue()) {
return;
}
var message = event.getMessage();
var sender = event.getName();
var localPlayer = Client.getLocalPlayer();
var myName = localPlayer.getName();
var respondToOthers = config.respondToOthers.getValue();
if (!respondToOthers && sender !== myName) {
return;
}
if (config.debugMode.getValue()) {
Utility.print("[Chatbot] Processing: " + message);
}
processCommand(message);
}
function processCommand(message) {
var prefix = config.commandPrefix.getValue();
var command = message.toLowerCase().trim();
if (!command.startsWith(prefix)) {
return;
}
var now = Date.now();
if (now - lastCommandTime < COMMAND_COOLDOWN_MS) {
return;
}
lastCommandTime = now;
var cleanCommand = command.substring(prefix.length);
if (cleanCommand === "hello" || cleanCommand === "hi") {
respondToHello();
}
else if (cleanCommand === "help") {
respondToHelp();
}
else if (cleanCommand === "time") {
respondToTime();
}
else if (cleanCommand === "stats") {
respondToStats();
}
else if (cleanCommand === "location" || cleanCommand === "loc") {
respondToLocation();
}
else if (cleanCommand === "inventory" || cleanCommand === "inv") {
respondToInventory();
}
else if (cleanCommand === "hp") {
respondToHP();
}
else if (cleanCommand.startsWith("echo ")) {
respondToEcho(message);
}
else {
var botName = config.botName.getValue();
Game.sendGameMessage("Unknown command. Type " + prefix + "help for commands.", botName);
}
}
// Response functions
function respondToHello() {
var botName = config.botName.getValue();
Game.sendGameMessage("Hello there! How can I help you today?", botName);
}
function respondToHelp() {
var prefix = config.commandPrefix.getValue();
var botName = config.botName.getValue();
Game.sendGameMessage("Available commands:", botName);
Game.sendGameMessage(prefix + "hello - Greet the bot", botName);
Game.sendGameMessage(prefix + "help - Show this help", botName);
Game.sendGameMessage(prefix + "time - Get current time", botName);
Game.sendGameMessage(prefix + "stats - Show your levels", botName);
Game.sendGameMessage(prefix + "location - Your coordinates", botName);
Game.sendGameMessage(prefix + "inventory - Item count", botName);
Game.sendGameMessage(prefix + "hp - Your hitpoints", botName);
Game.sendGameMessage(prefix + "echo <msg> - Repeat message", botName);
}
function respondToTime() {
var now = new Date();
var timeString = now.toLocaleTimeString();
var botName = config.botName.getValue();
Game.sendGameMessage("Current time: " + timeString, botName);
}
function respondToStats() {
var player = Client.getLocalPlayer();
var combatLevel = player.getCombatLevel();
var totalLevel = Client.getTotalLevel();
var botName = config.botName.getValue();
Game.sendGameMessage("Combat: " + combatLevel + " | Total: " + totalLevel, botName);
}
function respondToLocation() {
var player = Client.getLocalPlayer();
var worldPoint = player.getWorldLocation();
var x = worldPoint.getX();
var y = worldPoint.getY();
var z = worldPoint.getPlane();
var botName = config.botName.getValue();
Game.sendGameMessage("Location: (" + x + ", " + y + ", " + z + ")", botName);
}
function respondToInventory() {
var items = Game.info.inventory.getItems();
var count = 0;
for (var i = 0; i < items.length; i++) {
if (items[i] != null) {
count++;
}
}
var botName = config.botName.getValue();
Game.sendGameMessage("Inventory: " + count + "/28 items", botName);
}
function respondToHP() {
var currentHP = Client.getBoostedSkillLevels(Skill.HITPOINTS);
var maxHP = Client.getRealSkillLevels(Skill.HITPOINTS);
var botName = config.botName.getValue();
Game.sendGameMessage("HP: " + currentHP + "/" + maxHP, botName);
}
function respondToEcho(message) {
var prefix = config.commandPrefix.getValue();
var echoText = message.substring(prefix.length + 5);
var botName = config.botName.getValue();
Game.sendGameMessage("Echo: " + echoText, botName);
}
Problem: Bot doesn't respond to commands
Solutions:
config.enableBot
is trueProblem: Bot responds to other players' messages
Solutions:
config.respondToOthers
is falseProblem: Can't use commands frequently enough
Solutions:
COMMAND_COOLDOWN_MS
valueYou've created a fully functional chatbot plugin! You've learned:
Now that you have a chatbot working:
Ready to visualize data? Continue to How to Use 2D/3D Overlay to add visual displays!