├── .gitignore ├── LICENSE ├── README.md ├── database ├── database.mwb ├── database.mwb.bak └── sql.sql ├── index.js ├── install.js ├── objects ├── armor.js ├── enemy.js ├── food.js ├── game.js ├── item.js ├── player.js └── weapon.js ├── package-lock.json ├── package.json └── tokens_default.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # discord tokens.json file 61 | tokens.json 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rpgBot 2 | an discord bot(discord.js) with rpg game 3 | 4 | ## installation 5 | 6 | ### database installation 7 | run your database, go to phpmyadmin or something and import the sql.sql file in the database folder 8 | 9 | ### bot installation 10 | ```sh 11 | #use the install script to install the bot 12 | node install.js 13 | ``` 14 | 15 | ## updates 16 | you can just update by typing git pull in the server's folder 17 | ```sh 18 | git pull 19 | ``` 20 | if it doesn't work after an update try using node install.js to reinstall it completely. 21 | -------------------------------------------------------------------------------- /database/database.mwb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leon3110l/rpgBot/8f97c1aad39050e8cf7474c3817029d673566521/database/database.mwb -------------------------------------------------------------------------------- /database/database.mwb.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leon3110l/rpgBot/8f97c1aad39050e8cf7474c3817029d673566521/database/database.mwb.bak -------------------------------------------------------------------------------- /database/sql.sql: -------------------------------------------------------------------------------- 1 | -- MySQL Script generated by MySQL Workbench 2 | -- Mon 05 Jun 2017 07:45:48 PM CEST 3 | -- Model: New Model Version: 1.0 4 | -- MySQL Workbench Forward Engineering 5 | 6 | SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; 7 | SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; 8 | SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES'; 9 | 10 | -- ----------------------------------------------------- 11 | -- Schema rpgBot 12 | -- ----------------------------------------------------- 13 | DROP SCHEMA IF EXISTS `rpgBot` ; 14 | 15 | -- ----------------------------------------------------- 16 | -- Schema rpgBot 17 | -- ----------------------------------------------------- 18 | CREATE SCHEMA IF NOT EXISTS `rpgBot` DEFAULT CHARACTER SET utf8 ; 19 | USE `rpgBot` ; 20 | 21 | -- ----------------------------------------------------- 22 | -- Table `rpgBot`.`guild` 23 | -- ----------------------------------------------------- 24 | DROP TABLE IF EXISTS `rpgBot`.`guild` ; 25 | 26 | CREATE TABLE IF NOT EXISTS `rpgBot`.`guild` ( 27 | `id` CHAR(18) NOT NULL, 28 | `name` VARCHAR(200) NOT NULL, 29 | PRIMARY KEY (`id`)) 30 | ENGINE = InnoDB; 31 | 32 | 33 | -- ----------------------------------------------------- 34 | -- Table `rpgBot`.`weapon` 35 | -- ----------------------------------------------------- 36 | DROP TABLE IF EXISTS `rpgBot`.`weapon` ; 37 | 38 | CREATE TABLE IF NOT EXISTS `rpgBot`.`weapon` ( 39 | `id` INT NOT NULL AUTO_INCREMENT, 40 | `lvl` INT NOT NULL DEFAULT 0, 41 | `attackPower` INT NOT NULL DEFAULT 0, 42 | `name` VARCHAR(45) NOT NULL, 43 | PRIMARY KEY (`id`)) 44 | ENGINE = InnoDB; 45 | 46 | 47 | -- ----------------------------------------------------- 48 | -- Table `rpgBot`.`user` 49 | -- ----------------------------------------------------- 50 | DROP TABLE IF EXISTS `rpgBot`.`user` ; 51 | 52 | CREATE TABLE IF NOT EXISTS `rpgBot`.`user` ( 53 | `id` CHAR(18) NOT NULL, 54 | `weapon_id` INT NULL, 55 | `name` VARCHAR(200) NOT NULL, 56 | `lvl` INT NULL DEFAULT 0, 57 | `xp` INT NULL DEFAULT 0, 58 | `hp` INT NULL DEFAULT 50, 59 | `maxHp` INT NULL DEFAULT 50, 60 | `maxItems` INT NULL DEFAULT 50, 61 | `attackPower` INT NULL DEFAULT 5, 62 | `defense` INT NULL DEFAULT 5, 63 | PRIMARY KEY (`id`), 64 | INDEX `fk_user_weapon1_idx` (`weapon_id` ASC), 65 | CONSTRAINT `fk_user_weapon1` 66 | FOREIGN KEY (`weapon_id`) 67 | REFERENCES `rpgBot`.`weapon` (`id`) 68 | ON DELETE NO ACTION 69 | ON UPDATE NO ACTION) 70 | ENGINE = InnoDB; 71 | 72 | 73 | -- ----------------------------------------------------- 74 | -- Table `rpgBot`.`guild_has_user` 75 | -- ----------------------------------------------------- 76 | DROP TABLE IF EXISTS `rpgBot`.`guild_has_user` ; 77 | 78 | CREATE TABLE IF NOT EXISTS `rpgBot`.`guild_has_user` ( 79 | `guild_id` CHAR(18) NOT NULL, 80 | `user_id` CHAR(18) NOT NULL, 81 | PRIMARY KEY (`guild_id`, `user_id`), 82 | INDEX `fk_guild_has_user_user1_idx` (`user_id` ASC), 83 | INDEX `fk_guild_has_user_guild_idx` (`guild_id` ASC), 84 | CONSTRAINT `fk_guild_has_user_guild` 85 | FOREIGN KEY (`guild_id`) 86 | REFERENCES `rpgBot`.`guild` (`id`) 87 | ON DELETE NO ACTION 88 | ON UPDATE NO ACTION, 89 | CONSTRAINT `fk_guild_has_user_user1` 90 | FOREIGN KEY (`user_id`) 91 | REFERENCES `rpgBot`.`user` (`id`) 92 | ON DELETE NO ACTION 93 | ON UPDATE NO ACTION) 94 | ENGINE = InnoDB; 95 | 96 | 97 | -- ----------------------------------------------------- 98 | -- Table `rpgBot`.`armor` 99 | -- ----------------------------------------------------- 100 | DROP TABLE IF EXISTS `rpgBot`.`armor` ; 101 | 102 | CREATE TABLE IF NOT EXISTS `rpgBot`.`armor` ( 103 | `id` INT NOT NULL AUTO_INCREMENT, 104 | `lvl` INT NOT NULL DEFAULT 0, 105 | `defense` INT NOT NULL DEFAULT 0, 106 | `name` VARCHAR(45) NOT NULL, 107 | `armorType` VARCHAR(45) NOT NULL, 108 | PRIMARY KEY (`id`)) 109 | ENGINE = InnoDB; 110 | 111 | 112 | -- ----------------------------------------------------- 113 | -- Table `rpgBot`.`user_has_armor` 114 | -- ----------------------------------------------------- 115 | DROP TABLE IF EXISTS `rpgBot`.`user_has_armor` ; 116 | 117 | CREATE TABLE IF NOT EXISTS `rpgBot`.`user_has_armor` ( 118 | `user_id` CHAR(18) NOT NULL, 119 | `armor_id` INT NOT NULL, 120 | PRIMARY KEY (`user_id`, `armor_id`), 121 | INDEX `fk_user_has_armor_armor1_idx` (`armor_id` ASC), 122 | INDEX `fk_user_has_armor_user1_idx` (`user_id` ASC), 123 | CONSTRAINT `fk_user_has_armor_user1` 124 | FOREIGN KEY (`user_id`) 125 | REFERENCES `rpgBot`.`user` (`id`) 126 | ON DELETE NO ACTION 127 | ON UPDATE NO ACTION, 128 | CONSTRAINT `fk_user_has_armor_armor1` 129 | FOREIGN KEY (`armor_id`) 130 | REFERENCES `rpgBot`.`armor` (`id`) 131 | ON DELETE NO ACTION 132 | ON UPDATE NO ACTION) 133 | ENGINE = InnoDB; 134 | 135 | 136 | -- ----------------------------------------------------- 137 | -- Table `rpgBot`.`item` 138 | -- ----------------------------------------------------- 139 | DROP TABLE IF EXISTS `rpgBot`.`item` ; 140 | 141 | CREATE TABLE IF NOT EXISTS `rpgBot`.`item` ( 142 | `id` INT NOT NULL AUTO_INCREMENT, 143 | `type` VARCHAR(45) NOT NULL, 144 | `lvl` INT NOT NULL DEFAULT 0, 145 | `hp` INT NULL, 146 | `defense` INT NULL, 147 | `attackPower` INT NULL, 148 | `armorType` VARCHAR(45) NULL, 149 | `name` VARCHAR(45) NOT NULL, 150 | PRIMARY KEY (`id`)) 151 | ENGINE = InnoDB; 152 | 153 | 154 | -- ----------------------------------------------------- 155 | -- Table `rpgBot`.`user_has_item` 156 | -- ----------------------------------------------------- 157 | DROP TABLE IF EXISTS `rpgBot`.`user_has_item` ; 158 | 159 | CREATE TABLE IF NOT EXISTS `rpgBot`.`user_has_item` ( 160 | `user_id` CHAR(18) NOT NULL, 161 | `item_id` INT NOT NULL, 162 | PRIMARY KEY (`user_id`, `item_id`), 163 | INDEX `fk_user_has_item_item1_idx` (`item_id` ASC), 164 | INDEX `fk_user_has_item_user1_idx` (`user_id` ASC), 165 | CONSTRAINT `fk_user_has_item_user1` 166 | FOREIGN KEY (`user_id`) 167 | REFERENCES `rpgBot`.`user` (`id`) 168 | ON DELETE NO ACTION 169 | ON UPDATE NO ACTION, 170 | CONSTRAINT `fk_user_has_item_item1` 171 | FOREIGN KEY (`item_id`) 172 | REFERENCES `rpgBot`.`item` (`id`) 173 | ON DELETE NO ACTION 174 | ON UPDATE NO ACTION) 175 | ENGINE = InnoDB; 176 | 177 | 178 | SET SQL_MODE=@OLD_SQL_MODE; 179 | SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; 180 | SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS; 181 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require("console-stamp")(console); // display the date and time of the console.logs, for easier debugging 2 | const Discord = require("discord.js"); 3 | const client = new Discord.Client(); 4 | const tokens = require("./tokens"); 5 | const prefix = tokens.prefix; 6 | const mysql = require("mysql"); 7 | 8 | // game components 9 | const game = require("./objects/game.js"); 10 | const Player = require("./objects/player.js"); 11 | const Enemy = require("./objects/enemy.js"); 12 | var battles = []; // an array with battle objects 13 | 14 | // create mysql pool 15 | var pool = mysql.createPool({ 16 | connectionLimit: 50, // to be on the safe side 17 | host: tokens.DBhost || "localhost", 18 | user: tokens.DBusername || "rpgBot", 19 | password: tokens.DBpassword || "rpgBot", 20 | database: tokens.DBname || "rpgBot" 21 | }); 22 | 23 | client.on('ready', () => { 24 | console.log(`Logged in as ${client.user.username}!`); 25 | syncDB(); // update all the members and guilds 26 | }); 27 | 28 | client.on('message', msg => { 29 | // check if the prefix is used if not return(don't go further) and if it is a bot return 30 | if (msg.content.indexOf(prefix) != 0 || !client.user.bot) { 31 | return 32 | } 33 | msg.content = msg.content.substring(1, msg.content.length).trim(); // remove the prefix from the msg.content and trim it in case the user used a space 34 | // write code after this 35 | if (startsWith(msg.content, "battle")) { 36 | // find the battle 37 | var battle = battles.find(x => x.player.id === msg.author.id); 38 | // if there is no battle start a new one 39 | if (!battle) { 40 | // create a battle 41 | getPlayer(msg.author.id, player => { 42 | // create new battle 43 | battle = { 44 | player: player, 45 | enemy: new Enemy(null, player.lvl), 46 | startTime: new Date(), 47 | status: 0 48 | }; 49 | battles.push(battle); // add the battle to the battles array 50 | msg.reply("battle started!"); 51 | battleHandler(battle, msg); 52 | }); 53 | } else { 54 | battleHandler(battle, msg); 55 | } 56 | } 57 | if (msg.content === "invite") { 58 | client.generateInvite() 59 | .then(link => { 60 | msg.channel.send("invite link: "+link); 61 | }); 62 | } 63 | }); 64 | 65 | client.login(tokens.discord); 66 | 67 | function battleHandler(battle, msg) { 68 | var percentageBarOptions = {empty: ":broken_heart:", full: ":heart:"}; // the options all the percentageBar calls should have 69 | switch (battle.status) { 70 | case 0: // start 71 | start(); 72 | break; 73 | case 1: //attack 74 | attack(); 75 | break; 76 | case 2: //item 77 | item(); 78 | break; 79 | case 3: 80 | stats(); 81 | break; 82 | // 999 run/escape/stop 83 | } 84 | // the start menu 85 | function start() { 86 | if (msg.content === "battle") { 87 | var reply = "\n" + battle.player.name + ":\t\t"; 88 | reply += battle.player.hp + "/" + battle.player.maxHp + " HP " + percentageBar((battle.player.hp/battle.player.maxHp), 14, percentageBarOptions)+"\t\t\t\t\t\t"; 89 | reply += battle.enemy.name + ":\t\t"; 90 | reply += battle.enemy.hp + "/" + battle.enemy.maxHp + " HP " + percentageBar((battle.enemy.hp/battle.enemy.maxHp), 14, percentageBarOptions)+"\n\n"; 91 | reply += "0. attack \t\t\t\t\t\t 1. item \t\t\t\t\t\t 2. stats \t\t\t\t\t\t 3. run"; 92 | msg.reply(reply); 93 | } else { 94 | if (msg.content === "battle 0") { 95 | // goto attack menu 96 | battle.status = 1; 97 | } else if (msg.content === "battle 1") { 98 | // goto item menu 99 | battle.status = 2; 100 | } else if (msg.content === "battle 2") { 101 | battle.status = 3; 102 | } else if (msg.content === "battle 3") { 103 | // stop battle 104 | msg.reply("you ran away"); 105 | battle.status = 999; 106 | } 107 | msg.content = "battle"; // added to prevent a loop 108 | if (battle.status != 999) { 109 | battleHandler(battle, msg); 110 | } 111 | } 112 | } 113 | // the attack menu 114 | function attack() { 115 | var actions = battle.player.getWeaponActions(); 116 | if (msg.content === "battle") { 117 | var reply = "what would you like to do?\n\n"; 118 | for (var i = 0; i < actions.length; i++) { 119 | reply += i+". " + battle.player.equipedWeapon.name + " " + actions[i].name + ", " + Math.round(actions[i].attackPowerMultiplier * battle.player.equipedWeapon.attackPower + battle.player.attackPower) + " power\n"; 120 | } 121 | reply += actions.length +". back"; 122 | msg.reply(reply); 123 | } else { 124 | for (var i = 0; i < actions.length; i++) { 125 | if (msg.content === "battle "+i) { // some attack 126 | var opponentStats = battle.player.attack(battle.enemy, battle.player.equipedWeapon, i); 127 | if (opponentStats.miss) { 128 | msg.reply("you missed!"); 129 | } else { 130 | if (opponentStats.crit) { 131 | msg.reply("it was a critical hit!"); 132 | } 133 | msg.reply("you used " + actions[i].name + " with your " + battle.player.equipedWeapon.name + " and did " + opponentStats.dmg + " damage!"); 134 | } 135 | if (opponentStats.hp === 0) { 136 | msg.reply("you won!"); 137 | for (var j = 0; j < battle.enemy.dropItems.length; j++) { 138 | if (battle.player.addItem(battle.enemy.dropItems[j])) { 139 | msg.reply("you got a " + battle.enemy.dropItems[j].name); 140 | } else { 141 | // TODO: make something that askes what item to drop 142 | } 143 | } 144 | battle.player.addXp(battle.enemy); 145 | battle.status = 999; // exit the game 146 | } else { 147 | battle.status = 0; // go back to the first screen 148 | } 149 | } 150 | } 151 | if (msg.content === "battle "+actions.length) { // the back button 152 | battle.status = 0; // go back to the start 153 | } 154 | msg.content = "battle"; // added to prevent a loop 155 | battleHandler(battle, msg); 156 | } 157 | } 158 | // the item menu 159 | function item() { 160 | var items = battle.player.items; 161 | if (msg.content === "battle") { 162 | var reply = "inventory: \n"; 163 | for (var i = 0; i < items.length; i++) { 164 | reply += i+". " + items[i].name + "\t\t\t"; 165 | if ((i % 3) === 0) { 166 | reply += "\n"; 167 | } 168 | } 169 | reply += items.length + ". back"; 170 | msg.reply(reply); 171 | } else { 172 | for (var i = 0; i < items.length; i++) { 173 | if (msg.content === "battle "+i) { 174 | // TODO: use item 175 | } 176 | } 177 | if (msg.content === "battle "+items.length) { 178 | battle.status = 0; // go back to the start 179 | } 180 | msg.content = "battle"; // added to prevent a loop 181 | battleHandler(battle, msg); 182 | } 183 | } 184 | // gets current stats from the battle 185 | function stats() { 186 | var player = battle.player; 187 | var enemy = battle.enemy; 188 | var reply = "stats\n"; 189 | var info = []; 190 | if (!battle.enemy.equipedWeapon) { 191 | var enemyWeapon = "nothing"; 192 | var enemyWeaponAP = 0; 193 | } else { 194 | var enemyWeapon = battle.enemy.equipedWeapon.name; 195 | var enemyWeaponAP = battle.enemy.equipedWeapon.attackPower; 196 | } 197 | if (!battle.player.equipedWeapon) { 198 | var playerWeapon = "nothing"; 199 | var playerWeaponAP = 0; 200 | } else { 201 | var playerWeapon = battle.player.equipedWeapon.name; 202 | var playerWeaponAP = battle.player.equipedWeapon.attackPower; 203 | } 204 | var totalDEFplayer = player.defense; 205 | for (var armor in player.equipedArmor) { 206 | if (player.equipedArmor.hasOwnProperty(armor) && player.equipedArmor[armor]) { 207 | totalDEFplayer += player.equipedArmor[armor].defense; 208 | } 209 | } 210 | var totalDEFenemy = enemy.defense; 211 | for (var armor in enemy.equipedArmor) { 212 | if (enemy.equipedArmor.hasOwnProperty(armor) && enemy.equipedArmor[armor]) { 213 | totalDEFenemy += enemy.equipedArmor[armor].defense; 214 | } 215 | } 216 | // add all the rows to the array 217 | info.push(["name", player.name, enemy.name]); // push names 218 | info.push(["lvl", player.lvl.toString(), enemy.lvl.toString()]); // push lvl 219 | info.push(["DEF", player.defense.toString(), enemy.defense.toString()]); // defense 220 | info.push(["AP", player.attackPower.toString(), enemy.attackPower.toString()+"\n"]); // attack power 221 | info.push(["weapon", playerWeapon, enemyWeapon]); // weapon name 222 | info.push(["weapon AP", playerWeaponAP.toString(), enemyWeaponAP.toString()+"\n"]); // weapon attackPower 223 | info.push(["total AP", (player.attackPower + playerWeaponAP).toString(), (enemy.attackPower + enemyWeaponAP).toString()]); // total AP the person has 224 | info.push(["total DEF", totalDEFplayer.toString(), totalDEFenemy.toString()]); // total defense points 225 | 226 | reply += textGrid(info); 227 | msg.reply("```"+reply+"```"); // add it to a code block to get the monospaced font 228 | msg.content = "battle"; 229 | battle.status = 0; 230 | battleHandler(battle, msg); 231 | } 232 | battles.splice(battles.indexOf(battle), 1); // remove battle from battles array 233 | // statuscode 999 is escape code(remove from battles array and update player) 234 | if (battle.status != 999) { 235 | battles.push(battle); // push the updated battle to the battles array 236 | } else { 237 | setPlayer(battle.player); // upload player to the DB 238 | } 239 | } 240 | 241 | 242 | 243 | // input array needs to be a two dimensional array 244 | // discord font is not monospaced 245 | // in the options put every character with a different width to accomadate for non monospaced fonts 246 | // options should look like this {m: -1, l: 1} difference from normal width, the more width the more you need to subtract and vise versa 247 | // options is unneeded, because code block uses a monospaced font 248 | function textGrid(array, options) { 249 | var text = ""; 250 | // get biggest word for every row; 251 | var wordlengths = {}; 252 | // get lengths 253 | for (var i = 0; i < array.length; i++) { 254 | for (var j = 0; j < array[i].length; j++) { 255 | var length = 0; 256 | for (var char in options) { 257 | if (options.hasOwnProperty(char)) { 258 | var offset = 0; 259 | while (array[i][j].indexOf(char, offset) != -1) { 260 | length += options[char]; 261 | offset = array[i][j].indexOf(char, offset)+1; 262 | } 263 | } 264 | } 265 | length += array[i][j].length; 266 | if (length > wordlengths["col"+j] || !wordlengths["col"+j]) { 267 | wordlengths["col"+j] = length; 268 | } 269 | } 270 | } 271 | // generate text 272 | for (var i = 0; i < array.length; i++) { 273 | for (var j = 0; j < array[i].length; j++) { 274 | text += array[i][j] + " "; 275 | for (var k = 0; k < (wordlengths["col"+j] - array[i][j].length); k++) { 276 | text += " "; 277 | } 278 | } 279 | text += "\n"; 280 | } 281 | return text 282 | } 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | // gets a user from the database and adds all the items 299 | // example/test 300 | // getPlayer("253555759038726145", (player) => { 301 | // console.log(player); 302 | // }); 303 | function getPlayer(userId, callback) { 304 | pool.getConnection((err, conn) => { 305 | if (err) { 306 | console.log(err); 307 | return 308 | } 309 | conn.query("SELECT item.id, item.type, item.lvl AS targetLvl, item.hp, item.defense, item.attackPower, item.armorType, item.name FROM user_has_item LEFT JOIN item ON item.id = item_id WHERE user_id = ?", [userId], (error, results, fields) => { 310 | if (error) { 311 | console.log(error); 312 | conn.destroy(); 313 | return 314 | } 315 | var items = []; 316 | for (var i = 0; i < results.length; i++) { 317 | items.push(game.create(results[i].type, results[i].name, results[i].armorType, results[i])); //should create the item and push it in the items 318 | } 319 | conn.query("SELECT armor.id, armor.lvl AS targetLvl, armor.defense, armor.name, armor.armorType FROM user_has_armor LEFT JOIN armor ON armor.id = armor_id WHERE user_id = ?", [userId], (error, results, fields) => { 320 | if (error) { 321 | console.log(error); 322 | conn.destroy(); 323 | return 324 | } 325 | var armor = {}; 326 | for (var i = 0; i < results.length; i++) { 327 | var tmp = game.create("armor", results[i].name, results[i].armorType, results[i]); //should create the item 328 | armor[tmp.armorType] = tmp; // adds the armor 329 | } 330 | conn.query("SELECT user.name AS username, weapon_id, user.lvl AS userLvl, user.xp AS userXp, user.hp AS userHp, user.maxHp AS userMaxHp, user.maxItems AS userMaxItems, user.attackPower AS userAttackPower, user.defense AS userDefense, weapon.lvl AS weaponLvl, weapon.attackPower AS weaponAttackPower, weapon.name AS weaponName FROM user LEFT JOIN weapon ON weapon.id = weapon_id WHERE user.id = ?", [userId], (error, results, fields) => { 331 | if (error) { 332 | console.log(error); 333 | conn.destroy(); 334 | return 335 | } 336 | if (!results[0].weapon_id) { 337 | var weapon = null; 338 | } else { 339 | var weapon = game.create("weapon", results[0].weaponName, results[0].armorType, {targetLvl: results[0].weaponLvl, attackPower: results[0].weaponAttackPower}); 340 | } 341 | // returns a player with all of those things 342 | var player = new Player(userId, results[0].username, results[0].userXp, results[0].userLvl, results[0].userHp, results[0].userDefense, results[0].userAttackPower, results[0].userMaxHp, armor, weapon, results[0].userMaxItems, items); 343 | conn.destroy(); // remove conn from pool to prevent crashes and to make an connection available 344 | callback(player); 345 | }); 346 | }); 347 | }); 348 | }); 349 | } 350 | 351 | // updates the player on the database 352 | function setPlayer(player) { 353 | // weapon and user connection 354 | pool.getConnection((err, conn) => { 355 | // add user and weapon to the database 356 | conn.query("SELECT weapon_id FROM user WHERE user.id = ?", [player.id], (error, results, fields) => { 357 | if (error) { 358 | console.log(error); 359 | conn.destroy(); 360 | return 361 | } 362 | if (results[0]) { 363 | weaponId = results[0].weapon_id; 364 | } else { 365 | weaponId = null; 366 | } 367 | // update weapon if there is a weapon 368 | if (weaponId) { 369 | conn.query("UPDATE weapon SET lvl = ?, attackPower = ?, name = ? WHERE id = ?", [player.equipedWeapon.lvl, player.equipedWeapon.attackPower, player.equipedWeapon.name, weaponId], (error, results, fields) => { 370 | if (error) { 371 | console.log(error); 372 | conn.destroy(); 373 | return 374 | } 375 | updateUser(); 376 | }); 377 | } 378 | if (weaponId === null) { 379 | conn.query("INSERT INTO weapon(lvl, attackPower, name) VALUES (?, ?, ?)", [player.equipedWeapon.lvl, player.equipedWeapon.attackPower, player.equipedWeapon.name], (error, results, fields) => { 380 | if (error) { 381 | console.log(error); 382 | conn.destroy(); 383 | return 384 | } 385 | weaponId = results.insertId; 386 | updateUser(); 387 | }); 388 | } 389 | function updateUser() { 390 | conn.query("UPDATE user SET lvl = ?, xp = ?, hp = ?, maxHp = ?, maxItems = ?, attackPower = ?, defense = ?, weapon_id = ? WHERE user.id = ?", [player.lvl, player.xp, player.hp, player.maxHp, player.maxItems, player.attackPower, player.defense, weaponId, player.id], (error, results, fields) => { 391 | if (error) { 392 | console.log(error); 393 | conn.destroy(); 394 | return 395 | } 396 | conn.destroy(); 397 | }); 398 | } 399 | }); 400 | }); 401 | 402 | // item connection 403 | pool.getConnection((err, conn) => { 404 | // add items to the database 405 | conn.query("SELECT * FROM user_has_item WHERE user_id = ?", [player.id], (error, results, fields) => { 406 | if (error) { 407 | console.log(error); 408 | conn.destroy(); 409 | return 410 | } 411 | if (player.items.length === 0 && results.length === 0) { 412 | conn.destroy(); 413 | } 414 | // reuse old items in the database for optimal use, because of this I don't need to add them to user_has_item 415 | for (var i = 0; i < results.length; i++) { 416 | (function(itemId, item){ 417 | conn.query("UPDATE item SET type = ?, lvl = ?, hp = ?, defense = ?, attackPower = ?, armorType = ?, name = ? WHERE id = ?", [item.type, item.lvl, item.hp, item.defense, item.attackPower, item.armorType, item.name, itemId], (error, results, fields) => { 418 | if (error) { 419 | console.log(error); 420 | conn.destroy(); 421 | return 422 | } 423 | if (item === player.items[player.items.length-1]) { 424 | conn.destroy(); 425 | } 426 | }); 427 | }(results[i].item_id, player.items[i])); 428 | } 429 | // add items if needed 430 | var offset = results.length-1; 431 | if (offset < 0) { 432 | offset = 0; 433 | } 434 | for (var i = offset; i < player.items.length; i++) { 435 | (function(item) { 436 | conn.query("INSERT INTO item(type, lvl, hp, defense, attackPower, armorType, name) VALUES(?, ?, ?, ?, ?, ?, ?)", [item.type, item.lvl, item.hp, item.defense, item.attackPower, item.armorType, item.name], (error, results, fields) => { 437 | if (error) { 438 | console.log(error); 439 | conn.destroy(); 440 | return 441 | } 442 | conn.query("INSERT INTO user_has_item(user_id, item_id) VALUES (?, ?)", [player.id, results.insertId], (error, results, fields) => { 443 | if (error) { 444 | console.log(error); 445 | conn.destroy(); 446 | return 447 | } 448 | if (item === player.items[player.items.length-1]) { 449 | conn.destroy(); 450 | } 451 | }); 452 | }); 453 | }(player.items[i])); 454 | } 455 | }); 456 | }); 457 | // armor connection 458 | pool.getConnection((err, conn) => { 459 | // add armor to the database 460 | conn.query("SELECT * FROM user_has_armor INNER JOIN armor ON armor_id = armor.id WHERE user_id = ?", [player.id], (error, results, fields) => { 461 | if (error) { 462 | console.log(error); 463 | conn.destroy(); 464 | return 465 | } 466 | var found = false; 467 | for (var armor in player.equipedArmor) { 468 | if (player.equipedArmor.hasOwnProperty(armor)) { 469 | if (player.equipedArmor[armor] && results.length === 0) { 470 | found = true; 471 | } 472 | } 473 | } 474 | if (!found) { 475 | conn.destroy(); 476 | return 477 | } 478 | // reuse old items in the database for optimal use, because of this I don't need to add them to user_has_item 479 | for (var i = 0; i < results.length; i++) { 480 | (function(armorId, armor){ 481 | conn.query("UPDATE armor SET lvl = ?, defense = ?, name = ? WHERE id = ?", [armor.lvl, armor.defense, armor.name, armorId], (error, results, fields) => { 482 | if (error) { 483 | console.log(error); 484 | conn.destroy(); 485 | return 486 | } 487 | // if armor is the last armor piece, destroy connection 488 | var armorArray = player.equipedArmor.keys().map(key => obj[key]); 489 | if (armor === armorArray[armorArray.length-1]) { 490 | conn.destroy(); 491 | } 492 | }); 493 | }(results[i].armor_id, player.equipedArmor[results[i].armorType])); 494 | } 495 | // add items if needed 496 | for (var armor in player.equipedArmor) { 497 | // if there is no armor of that type already and he has it equiped 498 | if (player.equipedArmor.hasOwnProperty(armor) && player.equipedArmor[armor] && !results.find(result => result.armorType === armor)) { 499 | // add armor to the database 500 | (function(armor) { 501 | conn.query("INSERT INTO item(lvl, defense, name, armorType) VALUES(?, ?, ?, ?)", [armor.lvl, armor.defense, armor.name, armor.armorType], (error, results, fields) => { 502 | if (error) { 503 | console.log(error); 504 | conn.destroy(); 505 | return 506 | } 507 | conn.query("INSERT INTO user_has_armor(user_id, armor_id) VALUES (?, ?)", [player.id, results.insertId], (error, results, fields) => { 508 | if (error) { 509 | console.log(error); 510 | conn.destroy(); 511 | return 512 | } 513 | // if armor is the last armor piece, destroy connection 514 | var armorArray = player.equipedArmor.keys().map(key => obj[key]); 515 | if (armor === armorArray[armorArray.length-1]) { 516 | conn.destroy(); 517 | } 518 | }); 519 | }); 520 | }(player.equipedArmor[armor])); 521 | } 522 | } 523 | }); 524 | }); 525 | } 526 | 527 | // adds new members and new guilds 528 | function syncDB(callback) { 529 | pool.getConnection((err, conn) => { 530 | if (err) { 531 | console.log(err); 532 | conn.destroy(); 533 | return 534 | } 535 | var guilds = client.guilds.array(); 536 | for (var i = 0; i < guilds.length; i++) { 537 | (function(guild) { 538 | conn.query("SELECT id FROM guild WHERE id = ?", [guild.id], (error, results, fields) => { 539 | if (error) { 540 | console.log(error); 541 | conn.destroy(); 542 | return 543 | } 544 | if (!results[0]) { 545 | conn.query("INSERT INTO guild(id, name) VALUES (?, ?)", [guild.id, guild.name], (error, results, fields) => { 546 | if (error) { 547 | console.log(error); 548 | conn.destroy(); 549 | return 550 | } 551 | addMembers(guild); 552 | }); 553 | } else { 554 | addMembers(guild); 555 | } 556 | function addMembers(guild) { 557 | var members = guild.members.array(); 558 | for (var i = 0; i < members.length; i++) { 559 | // use anonymous function to handle with the asynchronous stuff with a for loop 560 | (function(member, guild) { 561 | // use ? and [] to remove drop database stuff 562 | conn.query("SELECT id FROM user WHERE id = ?", [member.id], (error, results, fields) => { 563 | if (error) { 564 | console.log(error); 565 | conn.destroy(); 566 | return 567 | } 568 | if (!results[0]) { 569 | // de user niet gevonden dus maak hem aan 570 | conn.query("INSERT INTO user(id, name) VALUES (?, ?)", [member.id, member.user.username], (error, results, fields) => { 571 | if (error) { 572 | console.log(error); 573 | conn.destroy(); 574 | return 575 | } 576 | conn.query("INSERT INTO guild_has_user(user_id, guild_id) VALUES(?, ?)", [member.id, guild.id], (error, results, fields) => { 577 | if (error) { 578 | console.log(error); 579 | conn.destroy(); 580 | return 581 | } 582 | // if its at the last user and the last guild 583 | if(member.id === members[members.length-1].id && guild.id === guilds[guilds.length-1].id) { 584 | // destroy connection to DB 585 | conn.destroy(); 586 | if (callback) { 587 | callback(); // call the callback 588 | } 589 | } 590 | }); 591 | }); 592 | } else { 593 | // if its at the last user and the last guild 594 | if(member.id === members[members.length-1].id && guild.id === guilds[guilds.length-1].id) { 595 | // destroy connection to DB 596 | conn.destroy(); 597 | if (callback) { 598 | callback(); // call the callback 599 | } 600 | } 601 | } 602 | }); 603 | }(members[i], guild)); 604 | } 605 | } 606 | }); 607 | }(guilds[i])); 608 | } 609 | }); 610 | } 611 | 612 | // example 613 | // console.log(percentageBar(0.75, 14, {caps: "()"})); 614 | // percentage from 0 to 1 and width in character length, the options are {caps: "[]", full: "#", empty: "-"} 615 | function percentageBar(percentage, width, options) { 616 | if (!options) { 617 | options = {}; 618 | } 619 | if (!options.caps) { 620 | options.caps = "[]"; 621 | } 622 | if (!options.full) { 623 | options.full = "#"; 624 | } 625 | if (!options.empty) { 626 | options.empty = "-"; 627 | } 628 | if (!width) { 629 | width = 14; 630 | } 631 | var bar = options.caps.substring(0, 1); 632 | var hashAmount = Math.round(width*percentage); 633 | var dashAmount = width - hashAmount; 634 | for (var i = 0; i < (hashAmount + dashAmount); i++) { 635 | if (i < hashAmount) { 636 | bar+= options.full; 637 | } else { 638 | bar+= options.empty; 639 | } 640 | } 641 | bar += options.caps.substring(1, 2); 642 | return bar 643 | } 644 | 645 | function startsWith(str, word) { 646 | str = str.trim(); 647 | if (str.indexOf(word) === 0) { 648 | return true 649 | } else { 650 | return false 651 | } 652 | } 653 | -------------------------------------------------------------------------------- /install.js: -------------------------------------------------------------------------------- 1 | // discordBot install script 2 | var fs = require("fs"); 3 | var child = require("child_process"); 4 | var data = require("./tokens_default"); 5 | 6 | // used to get user input 7 | function prompt(question, callback) { 8 | var stdin = process.stdin, 9 | stdout = process.stdout; 10 | 11 | stdin.resume(); 12 | stdout.write(question); 13 | 14 | stdin.once('data', function (data) { 15 | callback(data.toString().trim()); 16 | }); 17 | } 18 | 19 | if (!fs.existsSync("node_modules")) { 20 | install(); 21 | } else { 22 | prompt("do you want to do a completely reinstall y/n ", (input) => { 23 | if (input == "y") { 24 | if (deleteRecursive("node_modules")) { 25 | console.log("done deleting old files"); 26 | install(); 27 | } else { 28 | throw "something went wrong!"; 29 | } 30 | } else if(input == "n") { 31 | createToken(); 32 | } 33 | }); 34 | } 35 | 36 | function deleteRecursive(path) { 37 | if (fs.existsSync(path)) { 38 | files = fs.readdirSync(path); 39 | if (!files.length == 0) { 40 | files.forEach((file, index) => { 41 | var current = path+"/"+file; 42 | if (fs.lstatSync(current).isDirectory()) { 43 | deleteRecursive(current); 44 | } else { 45 | fs.unlinkSync(current); 46 | } 47 | }); 48 | } 49 | fs.rmdirSync(path); 50 | return true 51 | } else { 52 | return false 53 | } 54 | } 55 | 56 | function install() { 57 | const spawn = child.spawn; 58 | const ls = spawn('npm', ['install']); 59 | 60 | ls.stdout.on('data', (data) => { 61 | process.stdout.write(data.toString()); 62 | }); 63 | 64 | ls.stderr.on('data', (data) => { 65 | process.stdout.write(data.toString()); 66 | }); 67 | 68 | ls.on('close', (code) => { 69 | createToken(); 70 | }); 71 | } 72 | 73 | function createToken() { 74 | if (fs.existsSync("tokens.json")) { 75 | fs.unlink("tokens.json", (err) => { 76 | if (err) { 77 | console.error("couldn't delete tokens.json"); 78 | } 79 | }); 80 | } 81 | 82 | prompt("paste your discord token\n", (input) => { 83 | data.discord = input; 84 | prompt("what prefix would you like, default: $ ($)", (input) => { 85 | if (input) { 86 | data.prefix = input; 87 | } 88 | prompt("the defaults are\nDBhost: "+data.DBhost+"\nDBusername: "+data.DBusername+"\nDBpassword: "+data.DBpassword+"\ndo you want to change your DB login? y/n ", (input) => { 89 | if (input.toLowerCase() == "n") { 90 | writeTokens(); 91 | } else if (input.toLowerCase() == "y") { 92 | prompt("DB host (localhost)\n", (input) => { 93 | if (input) { 94 | data.DBhost = input; 95 | } 96 | prompt("DB username (discord)\n", (input) => { 97 | if (input) { 98 | data.DBusername = input; 99 | } 100 | prompt("DB password (discord)\n", (input) => { 101 | if (input) { 102 | data.DBpassword = input; 103 | } 104 | writeTokens(); 105 | }); 106 | }); 107 | }); 108 | } else { 109 | console.log("you didn't press the correct key."); 110 | createToken(); 111 | return 112 | } 113 | }); 114 | }); 115 | }); 116 | function writeTokens() { 117 | fs.writeFile('tokens.json', JSON.stringify(data), (err) => { 118 | if (err) throw err; 119 | console.log('The file has been saved!'); 120 | console.log("you can now start the bot by typing\nnode index.js"); 121 | console.log("done!"); 122 | process.exit(); 123 | }); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /objects/armor.js: -------------------------------------------------------------------------------- 1 | var Item = require("./item"); 2 | // script with all the armor pieces 3 | 4 | // if exact is true it will take the targetlvl and makes it the lvl 5 | function Armor(targetLvl, defense, exact) { 6 | this.maxLvl = 5; 7 | this.name = "unnamed"; 8 | this.type = "armor"; 9 | this.armorType = "boots"; // boots, harness, helmet, glove or pants 10 | if (exact) { 11 | this.lvl = targetLvl; 12 | } else { 13 | var targetLvlWiggleRoom = Math.floor(Math.random()*targetLvl-targetLvl/2); 14 | this.lvl = targetLvl + targetLvlWiggleRoom; 15 | } 16 | if (this.lvl <= 0) { 17 | this.lvl = 1; 18 | } 19 | if (this.lvl > this.maxLvl) { 20 | this.lvl = this.maxLvl; 21 | } 22 | this.defense = defense || Math.ceil((Math.random()*5+5)*this.lvl*5*0.25); 23 | } 24 | // inherit from item 25 | Armor.prototype = Object.create(Item.prototype); 26 | 27 | function Shirt(targetLvl, defense, exact) { 28 | this.maxLvl = 10; 29 | this.name = "shirt"; 30 | this.type = "armor"; 31 | this.armorType = "harness"; // boots, harness, helmet, glove or pants 32 | if (exact) { 33 | this.lvl = targetLvl; 34 | } else { 35 | var targetLvlWiggleRoom = Math.floor(Math.random()*targetLvl-targetLvl/2); 36 | this.lvl = targetLvl + targetLvlWiggleRoom; 37 | } 38 | if (this.lvl <= 0) { 39 | this.lvl = 1; 40 | } 41 | if (this.lvl > this.maxLvl) { 42 | this.lvl = this.maxLvl; 43 | } 44 | this.defense = defense || Math.ceil((Math.random()*5+5)*this.lvl*5*0.25); 45 | } 46 | Shirt.prototype = Object.create(Armor.prototype); 47 | 48 | module.exports = { 49 | Shirt: Shirt 50 | }; 51 | -------------------------------------------------------------------------------- /objects/enemy.js: -------------------------------------------------------------------------------- 1 | var Game = require("./game"); // used to generate armor and weapons 2 | var Player = require("./player"); 3 | // basic enemy 4 | // give it a lvl you want it to have 5 | function Enemy(name, targetLvl) { 6 | // make it a bit more random 7 | var targetLvlWiggleRoom = Math.floor(Math.random()*targetLvl-targetLvl/2); 8 | this.lvl = targetLvl + targetLvlWiggleRoom; 9 | if (this.lvl <= 0) { 10 | this.lvl = 1; 11 | } 12 | this.name = name || "unnamed"; 13 | this.type = "enemy"; 14 | this.equipedArmor = { 15 | boots: this.getRandomArmor("boots"), 16 | pants: this.getRandomArmor("pants"), 17 | harness: this.getRandomArmor("harness"), 18 | helmet: this.getRandomArmor("helmet"), 19 | glove: this.getRandomArmor("glove") 20 | }; 21 | this.equipedWeapon = this.getRandomWeapon(); 22 | this.maxDropItems = 5; 23 | // the items it is going to drop if the user wins 24 | this.items = this.getDropItems(); 25 | this.dropItems = this.items; 26 | // hp multiplier for easier enemy creation with more hp, make it harder, for something like bosses 27 | this.hpMultiplier = 5; 28 | // max hp for the enemy it self, hp when full 29 | this.maxHp = Math.ceil((Math.random()*this.hpMultiplier+this.hpMultiplier)*this.lvl*this.hpMultiplier); 30 | // current hp from the enemy it self 31 | this.hp = this.maxHp; 32 | // totalHp of the enemy including armor and buffs... when I add buffs 33 | this.totalHp = this.hp; 34 | // defense points 35 | this.defense = Math.round((Math.random() + 5) * this.lvl); 36 | // attackPower 37 | this.attackPower = Math.round((Math.random() + 10) * this.lvl); 38 | for (var armorPiece in this.equipedArmor) { 39 | // check if there is armor in the slot 40 | if (this.equipedArmor.hasOwnProperty(armorPiece) && this.equipedArmor[armorPiece]) { 41 | this.totalHp += this.equipedArmor[armorPiece].hp; 42 | } 43 | } 44 | } 45 | Enemy.prototype = Object.create(Player.prototype); 46 | 47 | // gets a random weapon 48 | Enemy.prototype.getRandomWeapon = function() { 49 | if (Game.items.weapon.length === 0) { 50 | return null 51 | } 52 | var weapon = new Game.items.weapon[Math.floor(Math.random()*Game.items.weapon.length)].item(this.lvl); 53 | if (Math.random() >= 0.5) { 54 | return weapon 55 | } else { 56 | return null 57 | } 58 | } 59 | // get a random piece of armor, same as getRandomWeapon but for armor, left(0) or right(1) in type 60 | Enemy.prototype.getRandomArmor = function(type) { 61 | switch (type) { 62 | case 0: 63 | type = "boots"; 64 | break; 65 | case 1: 66 | type = "pants"; 67 | break; 68 | case 2: 69 | type = "harness"; 70 | break; 71 | case 3: 72 | type = "helmet"; 73 | break; 74 | case 4: 75 | type = "glove"; 76 | break; 77 | } 78 | if (Game.items.armor[type].length === 0) { 79 | return null 80 | } 81 | var armor = new Game.items.armor[type][Math.floor(Math.random()*Game.items.armor[type].length)].item(this.lvl); 82 | if (Math.random() >= 0.5) { 83 | return armor 84 | } else { 85 | return null 86 | } 87 | } 88 | 89 | Enemy.prototype.getDropItems = function() { 90 | var dropItems = []; 91 | for (var item in Game.items) { 92 | if (Game.items.hasOwnProperty(item)) { 93 | if (item === "food") { 94 | if (Game.items[item].length > 0) { 95 | var selectedItem = Game.items[item][Math.floor(Math.random()*Game.items[item].length)]; 96 | } 97 | } else { 98 | for (var item1 in Game.items[item]) { 99 | if (Game.items[item].hasOwnProperty(item1)) { 100 | if (Game.items[item][item1].length > 0) { 101 | var selectedItem = Game.items[item][item1][Math.floor(Math.random()*Game.items[item][item1].length)]; 102 | } 103 | } 104 | } 105 | } 106 | // console.log(selectedItem); 107 | if (selectedItem.dropChance > Math.random() && dropItems.length < this.maxDropItems) { 108 | dropItems.push(new selectedItem.item(this.lvl)); 109 | // possibility for double drops 110 | if (selectedItem.dropChance > Math.random() && dropItems.length < this.maxDropItems) { 111 | dropItems.push(new selectedItem.item(this.lvl)); 112 | } 113 | } 114 | } 115 | } 116 | return dropItems; 117 | } 118 | 119 | // enemy ai, its mostly random 120 | Enemy.prototype.doMove = function(opponent) { 121 | // if low health eat 122 | if (this.hp < (this.maxHp*0.4)) { 123 | for (var i = 0; i < this.items.length; i++) { 124 | if (this.items[i].type == "food") { 125 | this.eat(this.items[i]); 126 | break; 127 | } 128 | } 129 | } else { //else attack 130 | // check if there is a weapon 131 | if (this.equipedWeapon) { 132 | // get actions for the weapon 133 | var actions = this.getWeaponActions(); 134 | // attack with a random action 135 | this.attack(opponent, Math.floor(Math.random()*actions.length)); 136 | } 137 | } 138 | } 139 | 140 | module.exports = Enemy; 141 | -------------------------------------------------------------------------------- /objects/food.js: -------------------------------------------------------------------------------- 1 | // script with all the different types of food. 2 | var Item = require("./item"); 3 | 4 | function Food(targetLvl, hp, exact) { 5 | this.type = "food"; 6 | this.name = "foodName"; 7 | this.maxLvl = 5; 8 | if (exact) { 9 | this.lvl = targetLvl; 10 | } else { 11 | var targetLvlWiggleRoom = Math.floor(Math.random()*targetLvl-targetLvl/2); 12 | this.lvl = targetLvl + targetLvlWiggleRoom; 13 | } 14 | if (this.lvl <= 0) { 15 | this.lvl = 1; 16 | } 17 | if (this.lvl > this.maxLvl) { 18 | this.lvl = this.maxLvl; 19 | } 20 | // hp multiplier if its raw or something it would give less hp back 21 | this.hpMultiplier = 1.25; 22 | // hp that the food gives back to the player who eats it 23 | this.hp = hp || Math.ceil((Math.random()*this.hpMultiplier+this.hpMultiplier)*this.lvl*this.hpMultiplier); 24 | } 25 | // inherit from item 26 | Food.prototype = Object.create(Item.prototype); 27 | 28 | // donut :) 29 | function Donut(targetLvl, hp, exact) { 30 | this.type = "food"; 31 | this.name = "donut"; 32 | this.maxLvl = 30; 33 | if (exact) { 34 | this.lvl = targetLvl; 35 | } else { 36 | var targetLvlWiggleRoom = Math.floor(Math.random()*targetLvl-targetLvl/2); 37 | this.lvl = targetLvl + targetLvlWiggleRoom; 38 | } 39 | if (this.lvl <= 0) { 40 | this.lvl = 1; 41 | } 42 | if (this.lvl > this.maxLvl) { 43 | this.lvl = this.maxLvl; 44 | } 45 | // hp multiplier if its raw or something it would give less hp back 46 | this.hpMultiplier = 1.25; 47 | // hp that the food gives back to the player who eats it 48 | this.hp = hp || Math.ceil((Math.random()*this.hpMultiplier+this.hpMultiplier)*this.lvl*this.hpMultiplier); 49 | } 50 | // inherit from Food 51 | Donut.prototype = Object.create(Food.prototype); 52 | 53 | // pizza :) 54 | function Pizza(targetLvl, hp, exact) { 55 | this.type = "food"; 56 | this.name = "pizza"; 57 | this.maxLvl = 50; 58 | if (exact) { 59 | this.lvl = targetLvl; 60 | } else { 61 | var targetLvlWiggleRoom = Math.floor(Math.random()*targetLvl-targetLvl/2); 62 | this.lvl = targetLvl + targetLvlWiggleRoom; 63 | } 64 | if (this.lvl <= 0) { 65 | this.lvl = 1; 66 | } 67 | if (this.lvl > this.maxLvl) { 68 | this.lvl = this.maxLvl; 69 | } 70 | // hp multiplier if its raw or something it would give less hp back 71 | this.hpMultiplier = 1.5; 72 | // hp that the food gives back to the player who eats it 73 | this.hp = hp || Math.ceil((Math.random()*this.hpMultiplier+this.hpMultiplier)*this.lvl*this.hpMultiplier); 74 | } 75 | // inherit from Food 76 | Pizza.prototype = Object.create(Food.prototype); 77 | 78 | module.exports = { 79 | Donut: Donut, 80 | Pizza: Pizza 81 | }; 82 | -------------------------------------------------------------------------------- /objects/game.js: -------------------------------------------------------------------------------- 1 | // a javascript file for all the game components 2 | var Food = require("./food"); 3 | var Armor = require("./armor"); 4 | var Weapon = require("./weapon"); 5 | // var Player = require("./player"); 6 | // var Enemy = require("./enemy"); 7 | 8 | // index of all the items, used for enemy creation and enemy drops 9 | var items = 10 | { 11 | // all the armor pieces 12 | armor: { 13 | boots: [ 14 | 15 | ], 16 | pants: [ 17 | 18 | ], 19 | harness: [ 20 | { 21 | name: "shirt", 22 | item: Armor.Shirt, 23 | dropChance: 0.05 24 | } 25 | ], 26 | helmet: [ 27 | 28 | ], 29 | glove: [ 30 | 31 | ] 32 | // ring: [ 33 | // left: [ 34 | // 35 | // ], 36 | // right: [ 37 | // 38 | // ] 39 | // ] 40 | // amulet: [ 41 | // 42 | // ] 43 | }, 44 | // all the weapons 45 | weapon: [ 46 | { 47 | name: "hand", 48 | item: Weapon.Hand, 49 | dropChance: 0 50 | }, 51 | { 52 | name: "hockey stick", 53 | item: Weapon.HockeyStick, 54 | dropChance: 0.45 55 | }, 56 | { 57 | name: "bat", 58 | item: Weapon.Bat, 59 | dropChance: 0.3 60 | } 61 | ], 62 | // shield 63 | // shield: [ 64 | // 65 | // ], 66 | // all the different foods 67 | food: [ 68 | { 69 | name: "donut", 70 | item: Food.Donut, 71 | dropChance: 0.3 72 | }, 73 | { 74 | name: "pizza", 75 | item: Food.Pizza, 76 | dropChance: 0.5 77 | } 78 | ] 79 | }; 80 | 81 | 82 | // returns the object, you need to initialize it when you get it 83 | // example 84 | // var item = create("armor", "shirt", "harness"); 85 | // console.log(new item(5)); 86 | function create(itemType, itemName, armorType, properties) { 87 | var output; 88 | if (itemType === "armor") { 89 | if (armorType === "boots") { 90 | output = items.armor.boots.find(armor => armor.name === itemName).item; 91 | } else if (armorType === "pants") { 92 | output = items.armor.pants.find(armor => armor.name === itemName).item; 93 | } else if (armorType === "harness") { 94 | output = items.armor.harness.find(armor => armor.name === itemName).item; 95 | } else if (armorType === "helmet") { 96 | output = items.armor.helmet.find(armor => armor.name === itemName).item; 97 | } else if (armorType === "glove") { 98 | output = items.armor.glove.find(armor => armor.name === itemName).item; 99 | } 100 | } else if (itemType === "weapon" || itemType === "weapons") { 101 | output = items.weapon.find(weapon => weapon.name === itemName).item; 102 | } else if (itemType === "food") { 103 | output = items.food.find(food => food.name === itemName).item; 104 | } 105 | if (typeof properties == "object") { 106 | if (itemType === "armor") { 107 | output = new output(properties.targetLvl, properties.defense, true); 108 | } else if (itemType === "weapon") { 109 | output = new output(properties.targetLvl, properties.attackPower, true); 110 | } else if (itemType === "food") { 111 | output = new output(properties.targetLvl, properties.hp, true); 112 | } 113 | } 114 | return output; 115 | } 116 | 117 | // export so that the main file can require it all at once 118 | module.exports = { 119 | // Food: Food, 120 | // Armor: Armor, 121 | // Weapon: Weapon, 122 | // Player: Player, 123 | items: items, 124 | create: create 125 | }; 126 | -------------------------------------------------------------------------------- /objects/item.js: -------------------------------------------------------------------------------- 1 | // var Game = require("./game"); 2 | 3 | // main game component. 4 | function Item() { 5 | this.itemId; 6 | this.name; 7 | this.type = "item"; 8 | this.description = ""; // give an item an description so that the user can read it 9 | } 10 | 11 | module.exports = Item; 12 | -------------------------------------------------------------------------------- /objects/player.js: -------------------------------------------------------------------------------- 1 | var Game = require("./game"); 2 | // player 3 | function Player(id, name, xp, lvl, hp, defense, attackPower, maxHp, equipedArmor, equipedWeapon, maxItems, items) { 4 | // player id from discord user id 5 | this.id = id || "0"; 6 | this.name = name || "unnamed"; 7 | this.xp = xp || 0; 8 | this.lvl = lvl || 0; 9 | this.equipedArmor = equipedArmor || { 10 | boots: null, 11 | pants: null, 12 | harness: null, 13 | helmet: null, 14 | glove: null 15 | }; 16 | // beginners Weapon 17 | this.equipedWeapon = equipedWeapon || new Game.items.weapon[0].item(this.lvl); 18 | // the items of the player 19 | this.items = items || []; 20 | // the max amount of items a player can have (inventory) 21 | this.maxItems = maxItems || 50; 22 | // max hp for the player it self 23 | this.maxHp = maxHp || 50; 24 | // hp from the player it self 25 | this.hp = hp || this.maxHp; 26 | // the defense points 27 | this.defense = defense || 5; 28 | // the attack points 29 | this.attackPower = attackPower || 5; 30 | } 31 | 32 | Player.prototype = { 33 | // TODO: attack function, eat function 34 | eat: function(food) { 35 | this.hp += food.hp; 36 | this.dropItem(food); // after it's eaten remove from items/inventory 37 | }, 38 | // attack an opponent with an item/weapon 39 | attack: function(opponent, item, action) { 40 | var crit = false; 41 | var miss = false; 42 | var power = this.attackPower + item.attackPower * item.actions[action].attackPowerMultiplier; 43 | // if it doesn't miss 44 | if (Math.random() < item.actions[action].critChance) { 45 | power *= Math.random() + 1.25; 46 | crit = true; 47 | } 48 | if (Math.random() < item.actions[action].accuracy) { // attack can miss 49 | var wiggleRoom = Math.floor(Math.random()*(power*0.1)-(power*0.1)/2); // have some deviation 50 | power += wiggleRoom; // add to the overall power of the attack 51 | power = Math.round(((Math.random()*0.40)+0.75)*power); 52 | } else { 53 | power = 0; // did not hit and did no dmg 54 | miss = true; 55 | } 56 | if (!miss) { 57 | var output = opponent.dmg(power); 58 | } else { 59 | var output = {hp: opponent.hp, dmg: 0}; 60 | } 61 | output.crit = crit; 62 | output.miss = miss; 63 | return output; //returns the amount of dmg the attack did and the new hp of the opponent 64 | }, 65 | // drops an item, removes an item from the items array 66 | dropItem: function(item) { 67 | // drop the item 68 | this.items.splice(this.items.indexOf(item), 1); 69 | }, 70 | // equips armor in a slot(boots(0), pants(1), harness(2), helmet(3) or glove(4)) 71 | equipArmor: function(armor) { 72 | 73 | // equip armor, boots, pants, harness, helmet or glove 74 | this.equipedArmor[armor.armorType] = armor; 75 | // remove armor from items array/inventory 76 | this.items.splice(this.items.indexOf(armor), 1); 77 | // TODO: add to the defense points of the player 78 | }, 79 | // equips weapon in a slot(left(0) or right(1)) 80 | equipWeapon: function(weapon) { 81 | // if there is an item equiped at that slot return the item to the items 82 | if (this.equipedWeapon) { 83 | // push it to the items 84 | this.items.push(this.equipedWeapons); 85 | } 86 | // equip weapon 87 | this.equipedWeapon = weapon; 88 | // remove item from items/inventory 89 | this.dropItem(weapon); 90 | // TODO: add to the attackPower of the player 91 | }, 92 | // take damage, returns new hp from this player 93 | dmg: function(dmg) { 94 | var defense = this.defense; 95 | for (var armor in this.equipedArmor) { 96 | if (this.equipedArmor.hasOwnProperty(armor) && this.equipedArmor[armor] != null) { 97 | defense += this.equipedArmor[armor].defense; 98 | } 99 | } 100 | dmg -= Math.round(defense * (0.025 * Math.random()+0.75)); 101 | this.hp -= dmg; 102 | if (this.hp < 0) { 103 | this.hp = 0; 104 | } 105 | return {hp: this.hp, dmg: dmg} // returns new hp of the player 106 | }, 107 | // returns the actions of the equiped weapon 108 | getWeaponActions: function() { 109 | return this.equipedWeapon.actions; 110 | }, 111 | // adds xp and lvls up if needed from enemy or an int 112 | // returns an object with lvl if it lvled up and new xp 113 | addXp: function(enemy) { 114 | var output = {}; 115 | var lvlThreshold = Math.floor((Math.pow((this.lvl * 2), 2) + 100) * 2); 116 | if (typeof enemy == "object") { 117 | this.xp += Math.round(Math.max((enemy.lvl - this.lvl), 1)*(Math.random()*25+1)); 118 | } else { //xp amount 119 | this.xp += enemy; 120 | } 121 | // check if the player lvled up 122 | if (this.xp >= lvlThreshold) { 123 | this.lvl++; 124 | this.xp -= lvlThreshold; 125 | output.lvl = this.lvl; 126 | // TODO: add hp and defense and attack, could let user decide 127 | } 128 | output.xp = this.xp; 129 | // return object with lvl if it lvled up and new xp 130 | return output; 131 | }, 132 | // resets all the weapons actions 133 | resetWeaponActions: function() { 134 | this.equipedWeapon.resetActions(); 135 | }, 136 | // adds an item to the player in the inventory/items array 137 | addItem: function(item) { 138 | if (this.items.length < this.maxItems) { 139 | this.items.push(item); 140 | return true; 141 | } else { 142 | return false; 143 | } 144 | } 145 | }; 146 | 147 | module.exports = Player; 148 | -------------------------------------------------------------------------------- /objects/weapon.js: -------------------------------------------------------------------------------- 1 | var Item = require("./item"); 2 | // script with all the different weapons. 3 | 4 | function Weapon(targetLvl, attackPower, exact) { 5 | this.name = "unnamed"; 6 | this.type = "weapon"; 7 | this.maxLvl = 5; 8 | if (exact) { 9 | this.lvl = targetLvl; 10 | } else { 11 | var targetLvlWiggleRoom = Math.floor(Math.random()*targetLvl-targetLvl/2); 12 | this.lvl = targetLvl + targetLvlWiggleRoom; 13 | } 14 | if (this.lvl <= 0) { 15 | this.lvl = 1; 16 | } 17 | if (this.lvl > this.maxLvl) { 18 | this.lvl = this.maxLvl; 19 | } 20 | this.attackPower = attackPower || Math.ceil((Math.random()*5+5)*this.lvl*5)*0.25; 21 | this.actions = [ 22 | { 23 | // name of the action/attack 24 | name: "example", 25 | // multiplies this number with the attackPower of the object in the attack 26 | attackPowerMultiplier: 1, 27 | // how many times you can use this in battle 28 | usage: 2, 29 | // how many times it has been used in battle 30 | used: 0, 31 | // how accurate the attack is from 0 to 1 32 | accuracy: 0.9, 33 | // chance to get a critical strike 34 | critChance: 0.2 35 | } 36 | ]; 37 | } 38 | // inherit Item stuff 39 | this.prototype = Object.create(Item.prototype); 40 | 41 | // Weapon.prototype.attackDmg = function(actionIndex) { 42 | // if (this.actions[actionIndex].used < this.actions[actionIndex].usage) { 43 | // this.actions[actionIndex].used++; 44 | // return this.actions[actionIndex].power_multiplier * this.power 45 | // } else { 46 | // return 0 // it can't be used any more in this battle 47 | // } 48 | // } 49 | Weapon.prototype.resetActions = function() { 50 | for (var i = 0; i < this.actions.length; i++) { 51 | this.actions[i].used = 0; 52 | } 53 | } 54 | 55 | function Hand(targetLvl, attackPower, exact) { 56 | this.name = "hand"; 57 | this.type = "weapon"; 58 | this.maxLvl = 5; 59 | if (exact) { 60 | this.lvl = targetLvl; 61 | } else { 62 | var targetLvlWiggleRoom = Math.floor(Math.random()*targetLvl-targetLvl/2); 63 | this.lvl = targetLvl + targetLvlWiggleRoom; 64 | } 65 | if (this.lvl <= 0) { 66 | this.lvl = 1; 67 | } 68 | if (this.lvl > this.maxLvl) { 69 | this.lvl = this.maxLvl; 70 | } 71 | this.attackPower = attackPower || Math.ceil((Math.random()*5+5)*this.lvl*5)*0.25; 72 | this.actions = [ 73 | { 74 | name: "punch", 75 | attackPowerMultiplier: 1, 76 | usage: 10, 77 | used: 0, 78 | accuracy: 0.9, 79 | critChance: 0.2 80 | }, 81 | { 82 | name: "hook", 83 | attackPowerMultiplier: 1.1, 84 | usage: 5, 85 | used: 0, 86 | accuracy: 0.85, 87 | critChance: 0.2 88 | }, 89 | { 90 | name: "upper cut", 91 | attackPowerMultiplier: 1.5, 92 | usage: 3, 93 | used: 0, 94 | accuracy: 0.8, 95 | critChance: 0.2 96 | } 97 | ]; 98 | } 99 | // inherit Weapon stuff 100 | Hand.prototype = Object.create(Weapon.prototype); 101 | 102 | function Bat(targetLvl, attackPower, exact) { 103 | this.name = "bat"; 104 | this.type = "weapon"; 105 | this.maxLvl = 5; 106 | if (exact) { 107 | this.lvl = targetLvl; 108 | } else { 109 | var targetLvlWiggleRoom = Math.floor(Math.random()*targetLvl-targetLvl/2); 110 | this.lvl = targetLvl + targetLvlWiggleRoom; 111 | } 112 | if (this.lvl <= 0) { 113 | this.lvl = 1; 114 | } 115 | if (this.lvl > this.maxLvl) { 116 | this.lvl = this.maxLvl; 117 | } 118 | this.attackPower = attackPower || Math.ceil((Math.random()*5+5)*this.lvl*5)*0.25; 119 | this.actions = [ 120 | { 121 | name: "swing", 122 | attackPowerMultiplier: 1.3, 123 | usage: 7, 124 | used: 0, 125 | accuracy: 0.9, 126 | critChance: 0.2 127 | }, 128 | { 129 | name: "stab", 130 | attackPowerMultiplier: 0.8, 131 | usage: 10, 132 | used: 0, 133 | accuracy: 0.9, 134 | critChance: 0.2 135 | }, 136 | { 137 | name: "slam", 138 | attackPowerMultiplier: 1.5, 139 | usage: 3, 140 | used: 0, 141 | accuracy: 0.9, 142 | critChance: 0.2 143 | } 144 | ]; 145 | } 146 | Bat.prototype = Object.create(Weapon.prototype); 147 | 148 | 149 | function HockeyStick(targetLvl, attackPower, exact) { 150 | this.name = "hockey stick"; 151 | this.type = "weapon"; 152 | this.maxLvl = 5; 153 | if (exact) { 154 | this.lvl = targetLvl; 155 | } else { 156 | var targetLvlWiggleRoom = Math.floor(Math.random()*targetLvl-targetLvl/2); 157 | this.lvl = targetLvl + targetLvlWiggleRoom; 158 | } 159 | if (this.lvl <= 0) { 160 | this.lvl = 1; 161 | } 162 | if (this.lvl > this.maxLvl) { 163 | this.lvl = this.maxLvl; 164 | } 165 | this.attackPower = attackPower || Math.ceil((Math.random()*5+5)*this.lvl*5)*0.25; 166 | this.actions = [ 167 | { 168 | name: "swing", 169 | attackPowerMultiplier: 1.2, 170 | usage: 7, 171 | used: 0, 172 | accuracy: 0.9, 173 | critChance: 0.2 174 | }, 175 | { 176 | name: "stab", 177 | attackPowerMultiplier: 0.6, 178 | usage: 10, 179 | used: 0, 180 | accuracy: 0.9, 181 | critChance: 0.2 182 | }, 183 | { 184 | name: "slam", 185 | attackPowerMultiplier: 1.3, 186 | usage: 3, 187 | used: 0, 188 | accuracy: 0.9, 189 | critChance: 0.2 190 | } 191 | ]; 192 | } 193 | HockeyStick.prototype = Object.create(Weapon.prototype); 194 | 195 | // export 196 | module.exports = { 197 | Weapon: Weapon, 198 | Hand: Hand, 199 | Bat: Bat, 200 | HockeyStick: HockeyStick 201 | }; 202 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rpgbot", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "ansi-regex": { 7 | "version": "2.1.1", 8 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 9 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 10 | }, 11 | "ansi-styles": { 12 | "version": "2.2.1", 13 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 14 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 15 | }, 16 | "array-find-index": { 17 | "version": "1.0.2", 18 | "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", 19 | "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" 20 | }, 21 | "bignumber.js": { 22 | "version": "3.1.2", 23 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-3.1.2.tgz", 24 | "integrity": "sha1-8725mtUmihX8HwvtL7AY4mk/4jY=" 25 | }, 26 | "builtin-modules": { 27 | "version": "1.1.1", 28 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 29 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" 30 | }, 31 | "camelcase": { 32 | "version": "2.1.1", 33 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", 34 | "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" 35 | }, 36 | "camelcase-keys": { 37 | "version": "2.1.0", 38 | "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", 39 | "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=" 40 | }, 41 | "chalk": { 42 | "version": "1.1.3", 43 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 44 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=" 45 | }, 46 | "console-stamp": { 47 | "version": "0.2.5", 48 | "resolved": "https://registry.npmjs.org/console-stamp/-/console-stamp-0.2.5.tgz", 49 | "integrity": "sha1-johUIWXY/Nyz+klPbfPdFTBM1v8=" 50 | }, 51 | "core-util-is": { 52 | "version": "1.0.2", 53 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 54 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 55 | }, 56 | "currently-unhandled": { 57 | "version": "0.4.1", 58 | "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", 59 | "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=" 60 | }, 61 | "dateformat": { 62 | "version": "1.0.12", 63 | "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", 64 | "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=" 65 | }, 66 | "decamelize": { 67 | "version": "1.2.0", 68 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 69 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 70 | }, 71 | "discord.js": { 72 | "version": "11.1.0", 73 | "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-11.1.0.tgz", 74 | "integrity": "sha1-U1HVnjeY9TbeGXXpLK5NEa89kmY=" 75 | }, 76 | "error-ex": { 77 | "version": "1.3.1", 78 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", 79 | "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=" 80 | }, 81 | "escape-string-regexp": { 82 | "version": "1.0.5", 83 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 84 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 85 | }, 86 | "find-up": { 87 | "version": "1.1.2", 88 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", 89 | "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=" 90 | }, 91 | "get-stdin": { 92 | "version": "4.0.1", 93 | "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", 94 | "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" 95 | }, 96 | "graceful-fs": { 97 | "version": "4.1.11", 98 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 99 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" 100 | }, 101 | "has-ansi": { 102 | "version": "2.0.0", 103 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 104 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=" 105 | }, 106 | "hosted-git-info": { 107 | "version": "2.4.2", 108 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz", 109 | "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=" 110 | }, 111 | "indent-string": { 112 | "version": "2.1.0", 113 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", 114 | "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=" 115 | }, 116 | "inherits": { 117 | "version": "2.0.3", 118 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 119 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 120 | }, 121 | "is-arrayish": { 122 | "version": "0.2.1", 123 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 124 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" 125 | }, 126 | "is-builtin-module": { 127 | "version": "1.0.0", 128 | "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", 129 | "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=" 130 | }, 131 | "is-finite": { 132 | "version": "1.0.2", 133 | "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", 134 | "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=" 135 | }, 136 | "is-utf8": { 137 | "version": "0.2.1", 138 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", 139 | "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" 140 | }, 141 | "isarray": { 142 | "version": "0.0.1", 143 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 144 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 145 | }, 146 | "load-json-file": { 147 | "version": "1.1.0", 148 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", 149 | "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=" 150 | }, 151 | "long": { 152 | "version": "3.2.0", 153 | "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", 154 | "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" 155 | }, 156 | "loud-rejection": { 157 | "version": "1.6.0", 158 | "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", 159 | "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=" 160 | }, 161 | "map-obj": { 162 | "version": "1.0.1", 163 | "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", 164 | "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" 165 | }, 166 | "meow": { 167 | "version": "3.7.0", 168 | "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", 169 | "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=" 170 | }, 171 | "merge": { 172 | "version": "1.2.0", 173 | "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", 174 | "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=" 175 | }, 176 | "minimist": { 177 | "version": "1.2.0", 178 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 179 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" 180 | }, 181 | "mysql": { 182 | "version": "2.13.0", 183 | "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.13.0.tgz", 184 | "integrity": "sha1-mY8fjKRuLj3XFJzpgkE2U5hqrkc=" 185 | }, 186 | "normalize-package-data": { 187 | "version": "2.3.8", 188 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz", 189 | "integrity": "sha1-2Bntoqne29H/pWPqQHHZNngilbs=" 190 | }, 191 | "number-is-nan": { 192 | "version": "1.0.1", 193 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 194 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" 195 | }, 196 | "object-assign": { 197 | "version": "4.1.1", 198 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 199 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 200 | }, 201 | "parse-json": { 202 | "version": "2.2.0", 203 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", 204 | "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=" 205 | }, 206 | "path-exists": { 207 | "version": "2.1.0", 208 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", 209 | "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=" 210 | }, 211 | "path-type": { 212 | "version": "1.1.0", 213 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", 214 | "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=" 215 | }, 216 | "pify": { 217 | "version": "2.3.0", 218 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 219 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" 220 | }, 221 | "pinkie": { 222 | "version": "2.0.4", 223 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 224 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" 225 | }, 226 | "pinkie-promise": { 227 | "version": "2.0.1", 228 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 229 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=" 230 | }, 231 | "prism-media": { 232 | "version": "0.0.1", 233 | "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-0.0.1.tgz", 234 | "integrity": "sha1-o0JcnKvVDRxsAuVDlBoRiVZnvRA=" 235 | }, 236 | "read-pkg": { 237 | "version": "1.1.0", 238 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", 239 | "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=" 240 | }, 241 | "read-pkg-up": { 242 | "version": "1.0.1", 243 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", 244 | "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=" 245 | }, 246 | "readable-stream": { 247 | "version": "1.1.14", 248 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 249 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=" 250 | }, 251 | "redent": { 252 | "version": "1.0.0", 253 | "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", 254 | "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=" 255 | }, 256 | "repeating": { 257 | "version": "2.0.1", 258 | "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", 259 | "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=" 260 | }, 261 | "safe-buffer": { 262 | "version": "5.0.1", 263 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", 264 | "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" 265 | }, 266 | "semver": { 267 | "version": "5.3.0", 268 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", 269 | "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" 270 | }, 271 | "signal-exit": { 272 | "version": "3.0.2", 273 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 274 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 275 | }, 276 | "snekfetch": { 277 | "version": "3.1.8", 278 | "resolved": "https://registry.npmjs.org/snekfetch/-/snekfetch-3.1.8.tgz", 279 | "integrity": "sha512-hRXeasaRhCNxgtEbrRN6F7MvyvtdaJ6yHI37TkjXJIwMcFOaeK2LQxzfPHTqhyOYL+ZIyq49/Hdxo4SXfmkbPg==" 280 | }, 281 | "spdx-correct": { 282 | "version": "1.0.2", 283 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", 284 | "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=" 285 | }, 286 | "spdx-expression-parse": { 287 | "version": "1.0.4", 288 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", 289 | "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" 290 | }, 291 | "spdx-license-ids": { 292 | "version": "1.2.2", 293 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", 294 | "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" 295 | }, 296 | "sqlstring": { 297 | "version": "2.2.0", 298 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.2.0.tgz", 299 | "integrity": "sha1-wxNcTqirzX5+50GklmqJHYak8ZE=" 300 | }, 301 | "string_decoder": { 302 | "version": "0.10.31", 303 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 304 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 305 | }, 306 | "strip-ansi": { 307 | "version": "3.0.1", 308 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 309 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=" 310 | }, 311 | "strip-bom": { 312 | "version": "2.0.0", 313 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", 314 | "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=" 315 | }, 316 | "strip-indent": { 317 | "version": "1.0.1", 318 | "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", 319 | "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=" 320 | }, 321 | "supports-color": { 322 | "version": "2.0.0", 323 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 324 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 325 | }, 326 | "trim-newlines": { 327 | "version": "1.0.0", 328 | "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", 329 | "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" 330 | }, 331 | "tweetnacl": { 332 | "version": "0.14.5", 333 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 334 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 335 | }, 336 | "ultron": { 337 | "version": "1.1.0", 338 | "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.0.tgz", 339 | "integrity": "sha1-sHoualQagV/Go0zNRTO67DB8qGQ=" 340 | }, 341 | "validate-npm-package-license": { 342 | "version": "3.0.1", 343 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", 344 | "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=" 345 | }, 346 | "ws": { 347 | "version": "2.3.1", 348 | "resolved": "https://registry.npmjs.org/ws/-/ws-2.3.1.tgz", 349 | "integrity": "sha1-a5Sz5EfLajY/eF6vlK9jWejoHIA=" 350 | } 351 | } 352 | } 353 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rpgbot", 3 | "version": "1.0.0", 4 | "description": "an discord rpg bot", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/leon-4A6C/rpgBot.git" 12 | }, 13 | "keywords": [ 14 | "discord", 15 | "bot", 16 | "rpg" 17 | ], 18 | "author": "leon in 't Veld", 19 | "license": "ISC", 20 | "bugs": { 21 | "url": "https://github.com/leon-4A6C/rpgBot/issues" 22 | }, 23 | "homepage": "https://github.com/leon-4A6C/rpgBot#readme", 24 | "dependencies": { 25 | "console-stamp": "^0.2.5", 26 | "discord.js": "^11.1.0", 27 | "mysql": "^2.13.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tokens_default.json: -------------------------------------------------------------------------------- 1 | { 2 | "discord": "DISCORD_TOKEN", 3 | "DBhost": "localhost", 4 | "DBusername": "rpgBot", 5 | "DBpassword": "rpgBot", 6 | "DBname": "rpgBot", 7 | "prefix": "$" 8 | } 9 | --------------------------------------------------------------------------------