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
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.