DeadZone Community Packages
    Preparing search index...

    How to Make a Chatbot Plugin

    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:

    • Listens to chat messages you type in-game
    • Responds to specific commands (like !hello, !help, !time)
    • Sends custom messages to the game chat
    • Can be extended with your own commands

    Before starting, you should have:

    • Completed the "Getting Started" and "Creating Your First Plugin" tutorials
    • Access to deadzone.dev with a package ready to edit
    • Basic understanding of the package lifecycle (OnStart, OnGameTick, OnShutdown)

    The DeadZone API provides the OnChatMessage event that fires whenever a chat message appears in-game. This includes:

    • Public chat from other players
    • Private messages
    • Clan chat
    • Game messages
    • Your own typed messages

    We'll use this event to detect commands and respond accordingly.

    1. Log into https://deadzone.dev
    2. Click "Create New Package"
    3. Fill in the details:
      • Name: Simple Chatbot
      • Description: A chatbot that responds to commands in chat
      • Category: Utility
    4. Click "Create"

    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:

    • We create a variable isRunning to track if the bot is active
    • OnStart sends a welcome message using Game.sendGameMessage()
    • OnShutdown sends a goodbye message
    • The second parameter of 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:

    • The @param {ChatMessage} event comment helps with autocomplete
    • We get the message text, sender name, and message type from the event
    • We check if the sender is ourselves (comparing names)
    • We only process our own messages to avoid spam
    • We call a processCommand() function to handle the logic

    Add 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:

    • We convert the message to lowercase for case-insensitive matching
    • We check if the message matches specific commands
    • Each command calls a dedicated response function
    • startsWith() lets us detect commands with parameters (like !echo Hello World)
    • Unknown commands starting with ! get a helpful error message

    Now 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:

    • Each function sends a custom response using Game.sendGameMessage()
    • respondToTime() uses JavaScript's Date object
    • respondToStats() uses the DeadZone API to get player information
    • respondToEcho() 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);
    }
    }
    1. Save your code in api.deadzone.dev
    2. Start the plugin
    3. In OSRS, open the public chat
    4. Type these commands:
      • !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);
    }
    • [ ] Bot starts and shows welcome message
    • [ ] !help command lists all commands
    • [ ] All commands work correctly
    • [ ] Configuration options work
    • [ ] Rate limiting prevents spam
    • [ ] Bot stops cleanly with goodbye message
    • [ ] Debug mode shows messages in console

    Problem: Bot doesn't respond to commands

    Solutions:

    • Check that config.enableBot is true
    • Verify the command prefix matches what you're typing
    • Make sure you're typing in public chat
    • Check Console for errors

    Problem: Bot responds to other players' messages

    Solutions:

    • Check that config.respondToOthers is false
    • Verify the name comparison logic is correct

    Problem: Can't use commands frequently enough

    Solutions:

    • Reduce COMMAND_COOLDOWN_MS value
    • Add a config option for cooldown time
    • Calculator: Add math evaluation commands
    • Reminders: Set timers and get notifications
    • Skill Tracker: Track XP gains and display progress
    • Item Lookup: Query item prices or stats
    • Quest Helper: Show quest requirements or guides
    • Minigame Info: Display minigame stats or timers

    You've created a fully functional chatbot plugin! You've learned:

    • ✅ How to listen for chat events
    • ✅ How to process commands
    • ✅ How to send messages to chat
    • ✅ How to use configuration options
    • ✅ How to access player information

    Now that you have a chatbot working:

    1. Add Overlays - Follow the "How to Use 2D/3D Overlay" guide to display info on-screen
    2. Expand Commands - Add more interesting commands

    Ready to visualize data? Continue to How to Use 2D/3D Overlay to add visual displays!