Discord.js While loop not executing the messsage sending in it

157 views Asked by At

If started to work on an rpg bot recently.

I was tryng to implement a turned based combat system.

But during the process I've find out that my while loop which is supposed to let the combat run till someone wins, won't send any message which will make the player able to play (console.log comments works but not the message sending via the discord api).

I think it isn't able to resolve itself for some reason.

Here is the code I'm using.

    let winner = false;
    let filter = m => m.author.id === message.author.id;
    message.channel.send("A battle is about to begin !");
      do {
         message.channel.send(`What attack do you wanna use ?`).then(() => {
         message.channel.awaitMessages(filter, {
                   max: 1,
                   time: 30000,
                   errors: ['time']
            }).then(message => {
                   message = message.first()
          if (message.content.toUpperCase() == 'Fireball' || message.content.toUpperCase() == 'fireball') {
              message.channel.send(`Fireball has been used !`)
          } else {
              message.channel.send(`Terminated: Invalid Response`)
          }
          }).catch(collected => {
                message.channel.send('Timeout');
            });
          })       
} while (battleStats[0]["CurrentHp"] != 0);

Note: the value of battleStats[0]["CurrentHp"] is 100 and contain en Int value

2

There are 2 answers

0
HotTeaPot On BEST ANSWER

Okay so after some thinking, I've decided to get rid of the while loop which was the source of the problem. I've taken inspiration from this post. It made me realize that making a while loop to create a turned based combat isn't necessary at all.

So in order to get over this problem, I've exported an object containing all my player and opponent data by using the module.exports module.

By requesting it in an other command, we will be able to stock the data and modify it for the turned based combat system.

In case if you were wandering the code I'm using here it is.

Starting the battle command which initiate the data collection about the player and the ennemy. (note that I'm now using an object to store the data and note an Array anymore.

database.execute(
                        'SELECT * FROM `tstats`, `tMstats` WHERE playerId = ? and monsterStatsId = ?',
                        [`${message.author.id}`, utility.randomIntFromInterval(1, 2)]
                        //the randomIntFromInterval function is just here to select a random ennemy from id
                        , function (err, result, fields) {
                            if (err) throw err;

                            Stats.MaxHp = parseInt(result[0]['playerMaxHp']);
                            Stats.CurrentHp = parseInt(result[0]['playerCurrentHp']);
                            Stats.MaxMana = parseInt(result[0]['playerMaxMana']);
                            Stats.CurrentMana = parseInt(result[0]['playerCurrentMana']);
                            Stats.PhysicalDefence = parseInt(result[0]['playerPhysicalDefence']);
                            Stats.MagicalDefence = parseInt(result[0]['playerMagicalDefence']);
                            Stats.Speed = parseInt(result[0]['playerSpeed']);
                            Stats.Level = parseInt(result[0]['playerLevel']);
                            Stats.Xp = parseInt(result[0]['playerXp']);
                            Stats.Evasion = parseInt(result[0]['playerEvasion']);

                            MStats.name = result[0]['monsterName']
                            MStats.MaxHp = parseInt(result[0]['monsterMaxHp']);
                            MStats.CurrentHp = parseInt(result[0]['monsterCurrentHp']);
                            MStats.MaxMana = parseInt(result[0]['monsterMaxMana']);
                            MStats.CurrentMana = parseInt(result[0]['monsterCurrentMana']);
                            MStats.PhysicalDefence = parseInt(result[0]['monsterPhysicalDefence']);
                            MStats.MagicalDefence = parseInt(result[0]['monsterMagicalDefence']);
                            MStats.Speed = parseInt(result[0]['monsterSpeed']);
                            MStats.Level = parseInt(result[0]['monsterLevel']);
                            MStats.Evasion = parseInt(result[0]['monsterEvasion']);

                            let battle = combat.initiateBattle(message.author.id, MStats.name);
                            utility.addBattle(battle);

                            message.channel.send("A battle is about to begin !");

                            module.exports = { Stats, MStats };
                        });

Here is my utility file which contain a set of function necessary for a battle logging system in JSON.

const fs = require("fs");
const logs = require('../database/battleLog.json')
let data = JSON.parse(fs.readFileSync('/home/username/Desktop/Dev perso/Nazarick/database/battleLog.json'));

function setIndex(nombre) {

    data["index"] = nombre
    fs.writeFile('/home/username/Desktop/Dev perso/Nazarick/database/battleLog.json', JSON.stringify(data), (err) => {
        if (err) console.log(err);
    });
}

function addBattle(battle) {

    data["battle"].push({
        id: battle["battle"]["id"],
        current_turn: {
            owner: battle["battle"]["current_turn"]["owner"],
            number: battle["battle"]["current_turn"]["number"]
        }
    });

    fs.writeFile('/home/username/Desktop/Dev perso/Nazarick/database/battleLog.json', JSON.stringify(data), (err) => {
        if (err) console.log(err);
    });
}

function randomIntFromInterval(min, max) { // min and max included 
    return Math.floor(Math.random() * (max - min + 1) + min)
}

function generateId(prefix, start) {
    start = data["index"];
    var i = start+1 || 1;
    return function () {
        setIndex(i)
        return prefix + i++;
    }
}

var id = generateId("battle_", 1);

module.exports = {
    randomIntFromInterval,
    id,
    addBattle
};

Finally the battle function file to initiate the fight

const utility = require('./utility.js');

class Battle {
    constructor(attacker, target) {
        this.attacker = attacker;
        this.target = target;
    }
};

globalBattlesList = new Set();

// Starts a Battle -- could throw an exception if either combatant is already in combat.
function initiateBattle(attacker, target) {
    var battle = new Battle(attacker, target);
    return {
        battle: {
            id: utility.id(),
            current_turn: {
                owner: attacker,
                number: 1,
            }

        }
        
    };
}

// Send an attack in a battle
function attack(battle, attacker, target) {
    if (battle.current_turn.owner != attack) {
        return { result: "error", message: "It's not your turn!" };
    }

    target.HP -= attacker.ATK;

    if (target.HP <= 0) {

        game.end_battle(battle);
        return {
            status: "OK",
            winner: attacker,
            message: "${attacker.name} wins in ${battle.current_turn.number} turns!"
        };
    }

    // change turn
    battle.current_turn = { owner: target, number: battle.current_turn.number + 1 };

    // does the AI have a delay?
    setTimeout(function () {
        // do_enemy_turn will choose an action for the AI 
        // and set battle.current_turn back to 
        do_enemy_turn(battle, target, attacker);
    }, target.attack_delay);

    return {
        result: "continue",
        message: `target is at ${target.HP} HP`
    };
}

module.exports = { initiateBattle, attack };

Note: The attack function isn't adjust for this setup.

1
wyndmill On

String.prototype.toUpperCase() makes the entire string uppercase, not just the first letter. As well as this, you are not able to assign a a variable if there is already one with that name, like you did with message. To fix this, make the .then() something like this. It may also be a problem somewhere else, if there are any errors you didn't specify.

.then(messages => {
    let response = messages.first()
    if (response.content.toLowerCase() === "fireball") { 
        message.channel.send(`Fireball has been used!`);
        /* change hp here */
    } else {
        message.channel.send(`Terminated: Invalid Response`);
        break // to leave the while loop
    }
}).catch(error => {
    message.channel.send('Timeout');
    break // also to leave the while loop
});