mirror of
https://github.com/Ratstail91/SANCTUM.git
synced 2025-11-28 18:14:28 +11:00
HARD FORK: slashed and burned everything that isn't immedately needed or working
This commit is contained in:
75
.envdev
75
.envdev
@@ -28,77 +28,46 @@ PREFIX="!"
|
|||||||
|
|
||||||
# Discord Server ID
|
# Discord Server ID
|
||||||
# Replace them with your own on a sandbox server!
|
# Replace them with your own on a sandbox server!
|
||||||
SANCTUM_ID="454425466821017611"
|
SANCTUM_ID="505291035992260635"
|
||||||
|
|
||||||
# Discord setup (Configred based on the server)
|
# Discord setup (Configred based on the server)
|
||||||
ADMIN_ROLE="Overseer"
|
ADMIN_ROLE="admin"
|
||||||
|
|
||||||
# Role IDs (A = Obsidian, B = Genesis, C = Hand)
|
# Role IDs (A = Obsidian, B = Genesis, C = Hand)
|
||||||
# Replace them with your own on a sandbox server!
|
# Replace them with your own on a sandbox server!
|
||||||
GROUP_A_ROLE="470656524042371072"
|
GROUP_A_ROLE="505293503840911360"
|
||||||
GROUP_B_ROLE="470668082441093121"
|
GROUP_B_ROLE="505293640948645888"
|
||||||
GROUP_C_ROLE="470656609295794199"
|
GROUP_C_ROLE="505293691678752768"
|
||||||
|
|
||||||
GROUP_A_NAME="Obsidian Technologies"
|
GROUP_A_NAME="Obsidian Technologies"
|
||||||
GROUP_B_NAME="Genesis Command"
|
GROUP_B_NAME="Genesis Command"
|
||||||
GROUP_C_NAME="The Hand"
|
GROUP_C_NAME="The Hand"
|
||||||
|
|
||||||
GROUP_A_CHANNEL_ID="493972208616603658"
|
GROUP_A_CHANNEL_ID="505292122732101633"
|
||||||
GROUP_B_CHANNEL_ID="493972336190685185"
|
GROUP_B_CHANNEL_ID="505292233441017866"
|
||||||
GROUP_C_CHANNEL_ID="493972354137849856"
|
GROUP_C_CHANNEL_ID="505292318006575115"
|
||||||
|
|
||||||
GROUP_A_LEADER_NAME="Kamala, Obsidian Vice President"
|
GROUP_A_LEADER_NAME="V.P. Kamala"
|
||||||
GROUP_B_LEADER_NAME="Captain Montgomery"
|
GROUP_B_LEADER_NAME="Cpt. Montgomery"
|
||||||
GROUP_C_LEADER_NAME="Dairo, High Prophet of The Hand"
|
GROUP_C_LEADER_NAME="Prophet Dairo"
|
||||||
|
|
||||||
# Channel IDs
|
# Channel IDs
|
||||||
# Replace them with your own on a sandbox server!
|
# Replace them with your own on a sandbox server!
|
||||||
OUTSKIRTS_CHANNEL_ID="462382076927148054"
|
LIBRARY_CHANNEL_ID="505500289089142812"
|
||||||
TAVERN_CHANNEL_ID="462684096024543242"
|
OUTSKIRTS_CHANNEL_ID="505292883394560000"
|
||||||
GATE_CHANNEL_ID="459196623923445779"
|
TAVERN_CHANNEL_ID="505292836963352576"
|
||||||
STASIS_CHANNEL_ID="468984551113228318"
|
GATE_CHANNEL_ID="505291599647866890"
|
||||||
CRYSTAL_SHORES_CHANNEL_ID="482629581690372099"
|
STASIS_CHANNEL_ID=""
|
||||||
SEA_OF_FOG_CHANNEL_ID="464150321699225634"
|
CRYSTAL_SHORES_CHANNEL_ID="505292474412171274"
|
||||||
DEADLANDS_CHANNEL_ID="459196395119837195"
|
SEA_OF_FOG_CHANNEL_ID="505292540434579466"
|
||||||
HELLS_GATE_CHANNEL_ID="464238060243124245"
|
DEADLANDS_CHANNEL_ID="505292597045231618"
|
||||||
TEST_CHANNEL_ID="464838060262293514"
|
|
||||||
|
|
||||||
# Bot IDs
|
|
||||||
# Replace them with your own on a sandbox server!
|
|
||||||
MORI_ID="461294299515191306"
|
|
||||||
RAVAGER_ID="458036985353732097"
|
|
||||||
MOSIAH_ID="457713779078332416"
|
|
||||||
GRAZE_ID="460640089198821377"
|
|
||||||
SONYA_ID="458078969653100554"
|
|
||||||
REY_ID="462675530928357376"
|
|
||||||
ALEXIS_ID="462708244171718656"
|
|
||||||
MONTGOMERY_GENESIS_ID="482642611023249409"
|
|
||||||
KAMALA_OBSIDIAN_ID="482644250354384906"
|
|
||||||
DAIRO_HAND_ID="482644985318211594"
|
|
||||||
LIBRARIAN_ID="458033243481047082"
|
|
||||||
|
|
||||||
# Bot Names
|
|
||||||
# Replace them with your own on a sandbox server!
|
|
||||||
GHOST_NAME="Ghost 5.0.1"
|
|
||||||
|
|
||||||
# Bot Tokens
|
# Bot Tokens
|
||||||
ADAM_TOKEN=""
|
ADAM_TOKEN=""
|
||||||
RAVAGER_TOKEN=""
|
|
||||||
WOLF_TOKEN=""
|
|
||||||
CROW_TOKEN=""
|
|
||||||
MOSIAH_TOKEN=""
|
|
||||||
REY_TOKEN=""
|
|
||||||
ALEXIS_TOKEN=""
|
|
||||||
GRAZE_TOKEN=""
|
|
||||||
MORI_TOKEN=""
|
|
||||||
LIBRARIAN_TOKEN=""
|
|
||||||
DRAVEN_MAW_TOKEN=""
|
|
||||||
SONYA_TOKEN=""
|
|
||||||
MONTGOMERY_GENESIS_TOKEN=""
|
|
||||||
KAMALA_OBSIDIAN_TOKEN=""
|
KAMALA_OBSIDIAN_TOKEN=""
|
||||||
|
MONTGOMERY_GENESIS_TOKEN=""
|
||||||
DAIRO_HAND_TOKEN=""
|
DAIRO_HAND_TOKEN=""
|
||||||
GHOST_TOKEN=""
|
LIBRARIAN_TOKEN=""
|
||||||
DEVELOPER_TOKEN=""
|
|
||||||
|
|
||||||
# Channel access roles (must match roles in your server)
|
# Channel access roles (must match roles in your server)
|
||||||
# Replace them with your own on a sandbox server!
|
# Replace them with your own on a sandbox server!
|
||||||
@@ -111,5 +80,5 @@ RANK_2_THRESHOLD=15
|
|||||||
RANK_3_THRESHOLD=30
|
RANK_3_THRESHOLD=30
|
||||||
|
|
||||||
# Server
|
# Server
|
||||||
SERVER_ADDRESS="http://skullboxstudios.com"
|
SERVER_ADDRESS="http://127.0.0.1"
|
||||||
SERVER_PASS_KEY=""
|
SERVER_PASS_KEY=""
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
token: process.env.GHOST_TOKEN,
|
|
||||||
botChannel: ""
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "nodejs-elasticbeanstalk",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "server.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "node server.js"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2",
|
|
||||||
"dotenv": "^6.0.0",
|
|
||||||
"node-cron": "^1.2.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
717
Alexis/alexis.js
717
Alexis/alexis.js
@@ -1,717 +0,0 @@
|
|||||||
// .env Variables
|
|
||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
// Node Modules
|
|
||||||
const Discord = require('discord.js');
|
|
||||||
const client = new Discord.Client();
|
|
||||||
|
|
||||||
// Bot Modules (stores http requests & random functions respectively)
|
|
||||||
const dataRequest = require('../modules/dataRequest');
|
|
||||||
const calcRandom = require('../modules/calcRandom');
|
|
||||||
|
|
||||||
// Drinks
|
|
||||||
const drinks = [
|
|
||||||
// https://brookstonbeerbulletin.com/beer-tasting-terms/
|
|
||||||
['🍺', 'Beer', 'The clean, classic Traveler\'s Watch drink.', '2'],
|
|
||||||
['🥛', 'Milk', 'An innocent, creamy drink. It is very nutritious.', '2'],
|
|
||||||
// http://scotchtasting.info/glossary/
|
|
||||||
['🥃', 'Whiskey', 'A very dignified, rich drink.', '5'],
|
|
||||||
// https://en.wikipedia.org/wiki/Wine_tasting_descriptors
|
|
||||||
['🍷', 'Wine', 'An aromatic wine, with a round taste.', '10'],
|
|
||||||
// http://richardgpeterson.com/champagne-glossary/
|
|
||||||
['🍾', 'Champagne', 'A brilliant, crisp drink. You can share your 🥂 drink with the tavern!', '20']
|
|
||||||
]
|
|
||||||
|
|
||||||
const normalActivity = '!buydrink | Bartender, Confidant'
|
|
||||||
|
|
||||||
// The ready event is vital, it means that your bot will only start reacting to information
|
|
||||||
// from Discord _after_ ready is emitted
|
|
||||||
client.on('ready', async () => {
|
|
||||||
// Generates invite link
|
|
||||||
try {
|
|
||||||
let link = await client.generateInvite(["ADMINISTRATOR"]);
|
|
||||||
console.log("Invite Link: " + link);
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can set status to 'online', 'invisible', 'away', or 'dnd' (do not disturb)
|
|
||||||
client.user.setStatus('online');
|
|
||||||
// Sets your "Playing"
|
|
||||||
client.user.setActivity(normalActivity);
|
|
||||||
console.log(`Connected! \
|
|
||||||
\nLogged in as: ${client.user.username} - (${client.user.id})`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create an event listener for messages
|
|
||||||
client.on('message', async message => {
|
|
||||||
// Message has to be in Tavern or Test
|
|
||||||
if (!(message.channel.id === process.env.TAVERN_CHANNEL_ID
|
|
||||||
|| message.channel.id === process.env.TEST_CHANNEL_ID)) return;
|
|
||||||
|
|
||||||
var sentMessageFlag = false;
|
|
||||||
|
|
||||||
// Ignores ALL bot messages with exceptions
|
|
||||||
if (message.author.bot) {
|
|
||||||
// If bot is Mori
|
|
||||||
if (message.author.id === "461294299515191306") {
|
|
||||||
if (calcRandom.gamble(33)) {
|
|
||||||
var dialogOptions = [
|
|
||||||
'Aww, do you have to rez \'em all?',
|
|
||||||
'I feel like you should skip some of \'em.',
|
|
||||||
'We don\'t say it enough, but we all appreciate what you do, honey.',
|
|
||||||
'I\'m sure everyone is thankful, they\'re just occupied.',
|
|
||||||
'Hey now, yer not gonna\' get no thanks with an attitude like that.',
|
|
||||||
'Are ya\' really in this for the glory though?',
|
|
||||||
'Thanks, hun.',
|
|
||||||
'You are very much appreciated.',
|
|
||||||
'I\'m sure it\'s not on purpose.',
|
|
||||||
'Travelers got a lot on their minds. But you\'re very needed, Sugar.'
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
|
|
||||||
message.channel.startTyping();
|
|
||||||
setTimeout(() => {
|
|
||||||
sendMessage(message.channel.id, "<@" + message.author.id + "> " + dialogOptions[randomNumber]);
|
|
||||||
message.channel.stopTyping(true);
|
|
||||||
}, calcRandom.random(2500, 6000));
|
|
||||||
sentMessageFlag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var wholeMessage = message.content.toLowerCase().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g,"");
|
|
||||||
var words = wholeMessage.split(" ");
|
|
||||||
console.log("wholeMessage: " + wholeMessage + "\nWords: " + words)
|
|
||||||
// Hearts message with "alexis" and not "date"
|
|
||||||
if (words.includes("alexis") && !words.includes("date") && sentMessageFlag === false) {
|
|
||||||
if (calcRandom.gamble(33)) {
|
|
||||||
setTimeout(function() {
|
|
||||||
message.react("❤")
|
|
||||||
}, calcRandom.random(1500,4000));
|
|
||||||
sentMessageFlag = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hey message
|
|
||||||
if (words.includes("hey") && sentMessageFlag === false) {
|
|
||||||
sayHey(message.channel, message.author.id);
|
|
||||||
sentMessageFlag = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Saying Alexis is your friend basically
|
|
||||||
if (words.includes("alexis") && words.includes("friend") && !words.includes("date") && sentMessageFlag === false) {
|
|
||||||
if (calcRandom.gamble(45)) {
|
|
||||||
var dialogOptions = [
|
|
||||||
'<@276538857174990858> is my girl.',
|
|
||||||
'<@462675530928357376>\'s been out a long while, but when she gets back I hope she stops by.',
|
|
||||||
'Me \'n <@462675530928357376> are pretty close.',
|
|
||||||
'Well I can tell ya\' who\'s not my friend. <@461294299515191306>. No offense hun.',
|
|
||||||
'That <@163770616581718017> character is mighty strange. But <@276538857174990858> fancies him so he must be alright.',
|
|
||||||
'You don\'t tip enough to call me a friend sweetie.',
|
|
||||||
'Listen here. I\'d love to chat but <@276538857174990858> \'n <@462675530928357376> have plans in a bit.',
|
|
||||||
'We\'re all friends when we drink together.',
|
|
||||||
'Ol\' Jakey never came back. Nice guy. Probably made a nice meal for a Ravager.',
|
|
||||||
'There\'s friends, and then there\'s family. Me \'n <@276538857174990858> are like that.'
|
|
||||||
];
|
|
||||||
typeRandomDialog(dialogOptions, message.channel);
|
|
||||||
sentMessageFlag = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Asking Alexis on a date
|
|
||||||
if (words.includes("alexis") && words.includes("date") && sentMessageFlag === false) {
|
|
||||||
if (calcRandom.gamble(33)) {
|
|
||||||
var dialogOptions = [
|
|
||||||
'Honey yer a darling, but not gonna happen.',
|
|
||||||
'Just because yer cute doesn\'t mean you get an auto-yes.',
|
|
||||||
':thumbsdown:',
|
|
||||||
'Hey now, what makes you think I\'m even available?',
|
|
||||||
'Calm yer britches and go ask Rey. She\'s into ones like you.',
|
|
||||||
'Nah, but thank you honey. It was sweet of ya\'',
|
|
||||||
'Listen here. I\'d love to chat but I\'d be lyin\' if I said I was interested.',
|
|
||||||
'Sweetie I try to be nice, but sometimes there\'s no nice way to say ***no***.',
|
|
||||||
'Yer gonna have to try harder than that now.',
|
|
||||||
'How about I give you a big fat maybe?'
|
|
||||||
];
|
|
||||||
typeRandomDialog(dialogOptions, message.channel, message.author.id);
|
|
||||||
sentMessageFlag = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ravager topic
|
|
||||||
if (words.includes("ravager") || words.includes("ravagers") && sentMessageFlag === false) {
|
|
||||||
if (calcRandom.gamble(33)) {
|
|
||||||
var dialogOptions = [
|
|
||||||
'never seen one in person.',
|
|
||||||
'Are they really big and scary? Only seen pictures on the \'net.',
|
|
||||||
'Fight any big ones lately?',
|
|
||||||
'What do you think they are? Like...they\'re angry that\'s for sure, but...like...why?',
|
|
||||||
'You ever got bit?',
|
|
||||||
'I hear they\'re mean \'n nasty.',
|
|
||||||
'Hope I never see one face ta face',
|
|
||||||
'You big strong travelers you. Keepin\' me safe an\' all :heart:',
|
|
||||||
'I dunno what I\'d do if one broke into the city here.',
|
|
||||||
'Just make sure you keep \'em away from ***The Watch*** ya\' hear?'
|
|
||||||
];
|
|
||||||
typeRandomDialog(dialogOptions, message.channel, message.author.id);
|
|
||||||
sentMessageFlag = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bar fights
|
|
||||||
if (words.includes("fight") || words.includes("attack") || words.includes("fighting") || words.includes("barfight") || words.includes("fite") && sentMessageFlag === false) {
|
|
||||||
if (calcRandom.gamble(33)) {
|
|
||||||
var dialogOptions = [
|
|
||||||
'Don\'t be startin\' no brawlers in here, ya\' hear?',
|
|
||||||
'Don\'t even think about it.',
|
|
||||||
'Don\'t make me give _Ghost_ a ping on the com.',
|
|
||||||
'In here is drinkin\' time. Out there in the deadlands is fightin\' time. Learn the difference.',
|
|
||||||
'You forget the rules or somethin\'?',
|
|
||||||
'Honey, just because I\'m sweet doesnt mean I can\'t kick your ass out the door.',
|
|
||||||
'You fight in here, you drink somewhere else.',
|
|
||||||
'Whatever pissing contest you\'re try\'na win, win it elsewhere.',
|
|
||||||
'Don\'t be actin\' all tuff here. Everybody knows what happened with you and that _Ravager_.',
|
|
||||||
'The first rule of drink club, no fightin\'.'
|
|
||||||
];
|
|
||||||
typeRandomDialog(dialogOptions, message.channel, message.author.id);
|
|
||||||
sentMessageFlag = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Good nights
|
|
||||||
if (words.includes("gn") || words.includes("night") || words.includes("goodnight") || words.includes("sleep") && sentMessageFlag === false) {
|
|
||||||
if (calcRandom.gamble(33)) {
|
|
||||||
var dialogOptions = [
|
|
||||||
'Night hun.',
|
|
||||||
'Goodnight sweety. You comin\' back tomorrow?',
|
|
||||||
'Have yerself a goodnight now ya\' hear?',
|
|
||||||
'Sweet dreams.',
|
|
||||||
'Nighty night.',
|
|
||||||
'Gn. See ya tomorrow?',
|
|
||||||
'Yer leavin\' already?',
|
|
||||||
'Have yerself a good rest now.',
|
|
||||||
'Sleep tight. I\' see ya\' tomorrow.',
|
|
||||||
'Don\' let the bed bugs bite. They\'re the size of ravagers here on New Eden.'
|
|
||||||
];
|
|
||||||
typeRandomDialog(dialogOptions, message.channel, message.author.id);
|
|
||||||
sentMessageFlag = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has to be (prefix)command
|
|
||||||
if (message.content.indexOf(process.env.PREFIX) !== 0) return;
|
|
||||||
|
|
||||||
// "This is the best way to define args. Trust me."
|
|
||||||
// - Some tutorial dude on the internet
|
|
||||||
const args = message.content.slice(process.env.PREFIX.length).trim().split(/ +/g);
|
|
||||||
const command = args.shift().toLowerCase();
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case "ping":
|
|
||||||
if (message.author.id === '200340393596944384' || message.author.id === '163770616581718017')
|
|
||||||
message.reply("Pong!");
|
|
||||||
break;
|
|
||||||
case "buydrink":
|
|
||||||
buyDrink(message, args);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "tip":
|
|
||||||
if (args == "") {
|
|
||||||
//if (false) {
|
|
||||||
newMessage = `:x: I appreciate the gesture, but how much did you wanna tip, <@${message.author.id}>?`;
|
|
||||||
sendMessage(message.channel.id, newMessage);
|
|
||||||
} else {
|
|
||||||
var crystalCost = Math.floor(parseFloat(args));
|
|
||||||
if (crystalCost > 0) {
|
|
||||||
//if (crystalCost > -1) {
|
|
||||||
// Valid number
|
|
||||||
var attacker = String(dataRequest.loadServerData("userStats", message.author.id));
|
|
||||||
var attackerWallet = parseFloat(attacker.split(",")[6]);
|
|
||||||
if (attackerWallet > crystalCost) {
|
|
||||||
var upgradeResponse = dataRequest.sendServerData("buyDrink", crystalCost, message.author.id);
|
|
||||||
var dialogOptions = [
|
|
||||||
'Well ain\'t you sweet. Much appreciated.',
|
|
||||||
'Awww that\'s mighty nice of ya\' :heart:',
|
|
||||||
'Thank you sweet heart. Very generous of ya\'',
|
|
||||||
'I appreciate that very much! And look forward to seein\' yer face more often. :wink:',
|
|
||||||
'Well now, you are just too kind.',
|
|
||||||
'You\' a sweet heart aren\'t ya. Thank you.',
|
|
||||||
'Sweety I just can\'t take how kind you are. :heart: Thank you very much.',
|
|
||||||
'For me? Aww, ya\' shouldn\'t have.',
|
|
||||||
'That is very much appreciated and you are welcome back to ***The Watch*** anytime.',
|
|
||||||
'Well darn, that\'s nice of ya. Thank you sweety.'
|
|
||||||
];
|
|
||||||
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
newMessage = dialogOptions[randomNumber] + "\n<@" + message.author.id + "> <:crystals:460974340247257089> **-" + crystalCost + "**";
|
|
||||||
sendMessage(message.channel.id, newMessage);
|
|
||||||
|
|
||||||
//Send PM (defunct)
|
|
||||||
//if (crystalCost >= 0) {
|
|
||||||
/*
|
|
||||||
if (crystalCost >= 50) {
|
|
||||||
var dialogOptions2 = [
|
|
||||||
'Hey so...not 100% on this but heard it through the grape vine. ',
|
|
||||||
'Ya\' know, the walls have ears around my place and occasionally I hear stuff. ',
|
|
||||||
'I ain\'t supposed to be tellin\' ya this, and I ain\'t sure how true it it...but...',
|
|
||||||
'So I probably shouldn\' get involved but I overheard some people talkin\'. Don\'t know if they spoke the truth, but...',
|
|
||||||
'Yer a generous tipper. So am I. Not solid on the info, but I got a tip for ya\'. ',
|
|
||||||
'So I hear things, and for generous people like yourself I might repeat \'em. Don\'t mean they\'re true. But...',
|
|
||||||
'I heard somethin\' I probably shouldn\'t repeat. Obviously can\'t confirm this. ',
|
|
||||||
'Things pass through my ears and I can\'t help but pass \'em on. ',
|
|
||||||
'Hey there. A fello traveler told me something ya\' should hear. Don\'t know the accuracy, just know what I heard. ',
|
|
||||||
'Ok so, don\'t know if this is up to date info, but I got somethin\' for ya. '
|
|
||||||
];
|
|
||||||
|
|
||||||
var dialogOptions3 = [
|
|
||||||
'Looks like The Order might actually be ahead in crystals this week.',
|
|
||||||
'I think The Anarchy is winning this week. Although can\'t say by how much.',
|
|
||||||
'Pretty sure The Religion has the most crystals in their bank right about now.',
|
|
||||||
'I heard that The Order is behind on crystals in the bank.',
|
|
||||||
'Someone mentioned that The Anarchy was a bit behind on crystals this week.',
|
|
||||||
'Been hearin\' that the Religion is last place in crystals this week, but they always have tricks up their sleeves.'
|
|
||||||
];
|
|
||||||
|
|
||||||
var randomNumber2 = Math.floor(Math.random() * dialogOptions2.length);
|
|
||||||
var randomNumber3 = Math.floor(Math.random() * dialogOptions3.length);
|
|
||||||
newMessage = dialogOptions2[randomNumber2] + dialogOptions3[randomNumber3];
|
|
||||||
//sendDM(message.author.id, newMessage);
|
|
||||||
message.author.send(newMessage);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Looks like ya\' ain\'t got the <:crystals:460974340247257089>. Don\'t make a girl a promise that ya\' can\'t keep.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Not a number
|
|
||||||
sendMessage(message.channel.id, `:x: Doesn't seem like a tip I could use, but I appreciate the thought, <@${message.author.id}>!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', console.error);
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/3733227/javascript-seconds-to-minutes-and-seconds
|
|
||||||
function fmtMSS(s){ // accepts seconds as Number or String. Returns m:ss
|
|
||||||
return( s - // take value s and subtract (will try to convert String to Number)
|
|
||||||
( s %= 60 ) // the new value of s, now holding the remainder of s divided by 60
|
|
||||||
// (will also try to convert String to Number)
|
|
||||||
) / 60 + ( // and divide the resulting Number by 60
|
|
||||||
// (can never result in a fractional value = no need for rounding)
|
|
||||||
// to which we concatenate a String (converts the Number to String)
|
|
||||||
// who's reference is chosen by the conditional operator:
|
|
||||||
9 < s // if seconds is larger than 9
|
|
||||||
? ':' // then we don't need to prepend a zero
|
|
||||||
: ':0' // else we do need to prepend a zero
|
|
||||||
) + s ; // and we add Number s to the string (converting it to String as well)
|
|
||||||
}
|
|
||||||
|
|
||||||
function sayHey(channel, userID) {
|
|
||||||
var dialogOptions = [
|
|
||||||
'Howdy',
|
|
||||||
'Hey back',
|
|
||||||
'Hey yourself',
|
|
||||||
'Hi',
|
|
||||||
'Hey it\'s you',
|
|
||||||
'Hi there',
|
|
||||||
'Hay is for horses silly',
|
|
||||||
'Well hello',
|
|
||||||
'Hey hey hey',
|
|
||||||
'Hey stranger'
|
|
||||||
];
|
|
||||||
var dialogOptions2 = [
|
|
||||||
'How ya\' been?',
|
|
||||||
'Whatcha\' up to?',
|
|
||||||
'What\'s the weather like out there?',
|
|
||||||
'Find any decent sized Ravagers?',
|
|
||||||
'Welcome back.',
|
|
||||||
'Glad you\'re back. Could use some company.',
|
|
||||||
'What are ya\' havin\'?',
|
|
||||||
'Whatcha\' drinkin\'?',
|
|
||||||
'Retiring for the night? Already?',
|
|
||||||
'Welcome to _The Watch!_'
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
var randomNumber2 = Math.floor(Math.random() * dialogOptions2.length);
|
|
||||||
var newMessage = dialogOptions[randomNumber] + " <@" + userID + ">!\n" + dialogOptions2[randomNumber] + "\n";
|
|
||||||
|
|
||||||
channel.startTyping();
|
|
||||||
setTimeout(function() {
|
|
||||||
sendMessage(channel.id, newMessage);
|
|
||||||
channel.stopTyping(true);
|
|
||||||
}, calcRandom.random(2500,6000));
|
|
||||||
}
|
|
||||||
|
|
||||||
function typeRandomDialog(dialogOptions, channel, playerID) {
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
|
|
||||||
channel.startTyping();
|
|
||||||
setTimeout(function() {
|
|
||||||
if (playerID === undefined)
|
|
||||||
sendMessage(channel.id, dialogOptions[randomNumber]);
|
|
||||||
else
|
|
||||||
sendMessage(channel.id, "<@" + playerID + "> " + dialogOptions[randomNumber]);
|
|
||||||
|
|
||||||
channel.stopTyping(true);
|
|
||||||
}, calcRandom.random(2500, 6000));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send message handler
|
|
||||||
function sendMessage(userID, channelID, message) {
|
|
||||||
// Handle optional first argument (so much for default arugments in node)
|
|
||||||
if (message === undefined) {
|
|
||||||
message = channelID;
|
|
||||||
channelID = userID;
|
|
||||||
userID = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility trick (@userID with an optional argument)
|
|
||||||
if (userID != null) {
|
|
||||||
message = "<@" + userID + "> " + message;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sends message (needs client var, therefore I think external script won't work)
|
|
||||||
client.channels.get(channelID).send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Async Waiting
|
|
||||||
function sleep(time) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
setTimeout(resolve, time);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buy drink
|
|
||||||
async function buyDrink(message, args) {
|
|
||||||
var randomGreet = [
|
|
||||||
`Hey ${message.author}, wanna drink? Here's what I've got!`,
|
|
||||||
`Welcome to the tavern, ${message.author}! Care for a drink?`,
|
|
||||||
`People have been asking me on dates, ${message.author}. Must've be the alcohol.`,
|
|
||||||
`How's the Ravager hunting going, ${message.author}?`
|
|
||||||
];
|
|
||||||
|
|
||||||
var randomNumber = Math.floor(Math.random() * randomGreet.length);
|
|
||||||
|
|
||||||
message.channel.startTyping();
|
|
||||||
await sleep(1500);
|
|
||||||
message.channel.stopTyping(true);
|
|
||||||
|
|
||||||
const takingTooLongMessage = ":x: Sorry, hun. But the others need me and yer taking too long. Call me back once you've made yer mind up, alright " + message.author + "?";
|
|
||||||
var footerName = message.member.displayName;
|
|
||||||
var courtesy = "";
|
|
||||||
var tmp = "";
|
|
||||||
|
|
||||||
// Generates drink text.
|
|
||||||
for (let index = 0; index < drinks.length; index++) {
|
|
||||||
const element = drinks[index];
|
|
||||||
tmp += `${element[0]} **${element[1]} <:crystals:460974340247257089> ${element[3]}** - ${element[2]}\n`
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is a mention
|
|
||||||
if (message.mentions.members.size > 0) {
|
|
||||||
footerName = message.mentions.members.first().displayName;
|
|
||||||
courtesy = `(Given to ${message.mentions.members.first().displayName}, Courtesy of ${message.member.displayName})`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor("Alexis", client.user.avatarURL)
|
|
||||||
.setColor("#ffcc4d")
|
|
||||||
.setTitle("Traveler's Watch Drinks " + courtesy)
|
|
||||||
.setDescription(tmp)
|
|
||||||
.setFooter("We hope you enjoy your stay, " + footerName + "!")
|
|
||||||
|
|
||||||
var newMessage = await message.channel.send(randomGreet[randomNumber], {embed});
|
|
||||||
var emoteReaction;
|
|
||||||
|
|
||||||
// Collects emotes and reacts upon the reaction (15 seconds)
|
|
||||||
const collector = newMessage.createReactionCollector(
|
|
||||||
(reaction, user) => (drinks.some(drinkElement => drinkElement[0] === reaction.emoji.name) || reaction.emoji.name === "❌")
|
|
||||||
&& user.id !== client.user.id && user.id === message.author.id, { time: 15 * 1000 });
|
|
||||||
var endedOnReact = false;
|
|
||||||
|
|
||||||
// Reacts
|
|
||||||
for (let i = 0; i < drinks.length; i++) {
|
|
||||||
const element = drinks[i][0];
|
|
||||||
console.log("[Reaction Options] Emote: " + element);
|
|
||||||
await newMessage.react(element);
|
|
||||||
}
|
|
||||||
await newMessage.react("❌");
|
|
||||||
|
|
||||||
// Collect
|
|
||||||
collector.once("collect", async reaction => {
|
|
||||||
emoteReaction = reaction.emoji.name;
|
|
||||||
endedOnReact = true;
|
|
||||||
collector.stop();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Chose an emote
|
|
||||||
collector.once("end", async collector => {
|
|
||||||
newMessage.clearReactions();
|
|
||||||
|
|
||||||
// If no choose
|
|
||||||
if (!endedOnReact) {
|
|
||||||
newMessage.edit(newMessage.content);
|
|
||||||
return newMessage.channel.send(takingTooLongMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If cancelled
|
|
||||||
if (emoteReaction === "❌") {
|
|
||||||
newMessage.edit(newMessage.content);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets confirmation by emote
|
|
||||||
var index = drinks.findIndex(drink => drink[0] === emoteReaction);
|
|
||||||
//console.log(index + "\n" + drinks[index]);
|
|
||||||
|
|
||||||
var confirmationMessage = await message.channel.send(`${message.author} You sure you want to buy the ${drinks[index][0]} **${drinks[index][1]}** for <:crystals:460974340247257089> **${drinks[index][3]}**?`);
|
|
||||||
await confirmationMessage.react('✅');
|
|
||||||
await confirmationMessage.react('❌');
|
|
||||||
|
|
||||||
// Collects emotes and reacts upon the reaction (15 seconds)
|
|
||||||
const newCollector = confirmationMessage.createReactionCollector(
|
|
||||||
(reaction, user) => (reaction.emoji.name === '✅' || reaction.emoji.name === '❌')
|
|
||||||
&& user.id !== client.user.id && user.id === message.author.id, { time: 15 * 1000 });
|
|
||||||
var confirmReact = false;
|
|
||||||
|
|
||||||
// Collect
|
|
||||||
newCollector.once("collect", async reaction => {
|
|
||||||
emoteReaction = reaction.emoji.name;
|
|
||||||
console.log("confirm: " + emoteReaction);
|
|
||||||
confirmReact = true;
|
|
||||||
newCollector.stop();
|
|
||||||
});
|
|
||||||
|
|
||||||
newCollector.once("end", async collector => {
|
|
||||||
confirmationMessage.delete();
|
|
||||||
|
|
||||||
// If no choose
|
|
||||||
if (!confirmReact) {
|
|
||||||
return message.channel.send(takingTooLongMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (emoteReaction === "✅") {
|
|
||||||
payDrinks(message, drinks[index]);
|
|
||||||
} else {
|
|
||||||
confirmationMessage.clearReactions();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buying drink
|
|
||||||
function payDrinks(message, drink) {
|
|
||||||
//var crystalCost = 0;
|
|
||||||
|
|
||||||
// A ton of variables
|
|
||||||
var crystalCost = parseFloat(drink[3]);
|
|
||||||
var emote = drink[0];
|
|
||||||
var givenIsAlexis = false;
|
|
||||||
var success = false;
|
|
||||||
var attacker = String(dataRequest.loadServerData("userStats", message.author.id));
|
|
||||||
var attackerWallet = parseFloat(attacker.split(",")[6]);
|
|
||||||
|
|
||||||
console.log("[Pay Drinks] Wallet: " + attackerWallet + " | Crystal Cost: " + crystalCost);
|
|
||||||
if (attackerWallet >= crystalCost) {
|
|
||||||
dataRequest.sendServerData("buyDrink", crystalCost, message.author.id);
|
|
||||||
|
|
||||||
dialogOptions = [
|
|
||||||
'Here\'s a cold one,',
|
|
||||||
'Here\'s your drink',
|
|
||||||
'Here you go,',
|
|
||||||
'Here ya are. Enjoy,',
|
|
||||||
'Sliding it your way,',
|
|
||||||
'Don\'t go alone, take this,',
|
|
||||||
'Drink up,',
|
|
||||||
'Don\'t chug it all down now,',
|
|
||||||
'Headed in your direction,',
|
|
||||||
'Comin\' up,'
|
|
||||||
];
|
|
||||||
|
|
||||||
// Alexis options
|
|
||||||
if (message.mentions.members.first() !== undefined) {
|
|
||||||
if (message.mentions.members.first().id === client.user.id) {
|
|
||||||
var dialogOptions = [
|
|
||||||
`Aww, thanks! :heart:`,
|
|
||||||
`Thanks for the drink! Cheers!`,
|
|
||||||
`Are you trying to make me drunk? Don't even TRY asking me out on a date,`
|
|
||||||
];
|
|
||||||
givenIsAlexis = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
var newMessage = "";
|
|
||||||
|
|
||||||
// Single or multiple user messages
|
|
||||||
if (message.mentions.members.size < 1) {
|
|
||||||
success = true;
|
|
||||||
newMessage = `${emote} ` + dialogOptions[randomNumber] + " <@" + message.author.id + ">! <:crystals:460974340247257089> **-" + crystalCost + "**";
|
|
||||||
} else {
|
|
||||||
// Huge scope creep, but have a list of players able to be given beer instead of just one later on
|
|
||||||
// For now, just taking the first player
|
|
||||||
let member = message.mentions.members.first();
|
|
||||||
if (member) {
|
|
||||||
// Displays ping if not Alexis
|
|
||||||
var givePingUser = ` ${member.user}!`;
|
|
||||||
if (givenIsAlexis) givePingUser = "";
|
|
||||||
|
|
||||||
success = true;
|
|
||||||
newMessage = `${emote} ` + dialogOptions[randomNumber] + givePingUser + "\n\n" + "***Courtesy of *** <@" + message.author.id + ">. <:crystals:460974340247257089> **-" + crystalCost + "**";
|
|
||||||
} else {
|
|
||||||
newMessage = ":x: <@" + message.author.id + "> You wanna buy ***WHO*** a ***WHAT*** now?";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sendMessage(message.channel.id, newMessage);
|
|
||||||
|
|
||||||
// Does champagne sharing
|
|
||||||
if (success && drink[1] === "Champagne") {
|
|
||||||
shareDrinks(message, drink);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Looks like ya\' ain\'t got the <:crystals:460974340247257089><:crystals:460974340247257089><:crystals:460974340247257089>. I ain\'t runnin\' a charity here.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mass buying of a drink
|
|
||||||
async function shareDrinks(message, drink) {
|
|
||||||
const drinkMessage = `${message.author} has bought some ${drink[0]} **${drink[1]}**! React to get your **free drink!** 🥂`;
|
|
||||||
var timer = 30; // Seconds
|
|
||||||
var decrementTime = 10;
|
|
||||||
var footerText = `⏰ ${timer} seconds left to get your free drink!`;
|
|
||||||
client.user.setActivity(`${footerText}`);
|
|
||||||
|
|
||||||
// Embed
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor("Alexis", client.user.avatarURL)
|
|
||||||
.setColor("#ffcc4d")
|
|
||||||
.setTitle("Free Drinks!")
|
|
||||||
.setDescription(drinkMessage)
|
|
||||||
.setFooter(footerText)
|
|
||||||
|
|
||||||
var embedMessage = await message.channel.send(embed);
|
|
||||||
|
|
||||||
// Message
|
|
||||||
message.channel.startTyping();
|
|
||||||
await sleep(1500);
|
|
||||||
message.channel.send("Hmm... I might just take some too, if y'all don't mind. :heart:");
|
|
||||||
message.channel.stopTyping(true);
|
|
||||||
await sleep(1500);
|
|
||||||
|
|
||||||
// Collects emotes and reacts upon the reaction (30 seconds)
|
|
||||||
var users = "";
|
|
||||||
var numberOfReacts = 0;
|
|
||||||
const newCollector = embedMessage.createReactionCollector(
|
|
||||||
(reaction, user) => reaction.emoji.name === drink[0]
|
|
||||||
, { time: timer * 1000 });
|
|
||||||
|
|
||||||
// Alexis grabbing some
|
|
||||||
await embedMessage.react(drink[0]);
|
|
||||||
|
|
||||||
// Collect
|
|
||||||
newCollector.on("collect", async reaction => {
|
|
||||||
var user = reaction.users.last();
|
|
||||||
dialogOptions = [
|
|
||||||
`${user} has taken a drink!`,
|
|
||||||
`${user} eagerly grabs the ${drink[1]}!`,
|
|
||||||
`${user} enjoys the beverage!`,
|
|
||||||
`${user} gets a free drink!`,
|
|
||||||
`${user} chugs down the ${drink[1]}!`,
|
|
||||||
`${user} races to get down the drink the fastest!`
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
users += dialogOptions[randomNumber] + "\n";
|
|
||||||
|
|
||||||
// Embed
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor("Alexis", client.user.avatarURL)
|
|
||||||
.setColor("#ffcc4d")
|
|
||||||
.setTitle("Free Drinks!")
|
|
||||||
.setDescription(`${drinkMessage}\n\n` + users)
|
|
||||||
.setFooter(footerText)
|
|
||||||
|
|
||||||
embedMessage.edit(embed);
|
|
||||||
|
|
||||||
// Counts up if not Alexis
|
|
||||||
if (reaction.users.last().id !== client.user.id) numberOfReacts++;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ends collection
|
|
||||||
newCollector.once("end", async collector => {
|
|
||||||
var number = ""
|
|
||||||
if (numberOfReacts === 1) {
|
|
||||||
number = numberOfReacts + " traveler";
|
|
||||||
} else {
|
|
||||||
number = numberOfReacts + " travelers";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Embed
|
|
||||||
embedMessage.clearReactions();
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor("Alexis", client.user.avatarURL)
|
|
||||||
.setColor("#ffcc4d")
|
|
||||||
.setTitle("Free Drinks!")
|
|
||||||
.setDescription(`${message.author}'s ${drink[0]} **${drink[1]}** has been finished. There were a total of ${number} that got the free drink! 🥂\n\n` + users)
|
|
||||||
.setFooter("⏰ The drink has been finished!")
|
|
||||||
|
|
||||||
embedMessage.edit(embed);
|
|
||||||
message.channel.send(`Everyone, thank ${message.author} for the drink! It was great.`);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
function timerFunction() {
|
|
||||||
setTimeout(async () => {
|
|
||||||
console.log("timer: " + timer + " => " + (timer - decrementTime))
|
|
||||||
timer -= decrementTime;
|
|
||||||
|
|
||||||
footerText = `⏰ ${timer} seconds left to get your free drink!`;
|
|
||||||
|
|
||||||
if (timer > 0) {
|
|
||||||
client.user.setActivity(`${footerText}`);
|
|
||||||
|
|
||||||
// Embed
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor("Alexis", client.user.avatarURL)
|
|
||||||
.setColor("#ffcc4d")
|
|
||||||
.setTitle("Free Drinks!")
|
|
||||||
.setDescription(`${drinkMessage}\n\n` + users)
|
|
||||||
.setFooter(footerText)
|
|
||||||
|
|
||||||
embedMessage.edit(embed);
|
|
||||||
} else {
|
|
||||||
client.user.setActivity(normalActivity)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timer > 0) timerFunction();
|
|
||||||
}, decrementTime * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
timerFunction();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
async function sendDM(userID, dialogOption, dialogOption2, dialogOption3) {
|
|
||||||
// Wait for 20 - 40 seconds
|
|
||||||
//await(sleep(calcRandom.random(120, 240) * 60 * 1000));
|
|
||||||
var author = client.users.get(userID);
|
|
||||||
|
|
||||||
client.send(author, dialogOption);
|
|
||||||
client.send(author, dialogOption2);
|
|
||||||
client.send(author, dialogOption3);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Log our bot in
|
|
||||||
client.login(process.env.ALEXIS_TOKEN);
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "sanctum-deploypackage",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"description": "Universal package for all SANCTUM bots, using pm2.",
|
|
||||||
"main": "",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "echo \"Error: you need to use the bot name as a command.\" && exit 1",
|
|
||||||
"alexis": "pm2 start alexis.js -i max --watch",
|
|
||||||
"graze": "pm2 start graze.js -i max --watch",
|
|
||||||
"librarian": "pm2 start librarian.js -i max --watch",
|
|
||||||
"mainframe": "pm2 start mainframe.js -i max --watch",
|
|
||||||
"mori": "pm2 start mori.js -i max --watch",
|
|
||||||
"mosiah": "pm2 start mosiah.js -i max --watch",
|
|
||||||
"ravager": "pm2 start ravager.js -i max --watch",
|
|
||||||
"rey": "pm2 start rey.js -i max --watch",
|
|
||||||
"troll": "pm2 start troll.js -i max --watch"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2",
|
|
||||||
"dotenv": "^6.0.0",
|
|
||||||
"express": "^4.16.3",
|
|
||||||
"node-cron": "^1.2.1",
|
|
||||||
"socket.io": "^2.1.1",
|
|
||||||
"socket.io-request": "^0.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,252 +0,0 @@
|
|||||||
// .env Variables
|
|
||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
// Node Modules
|
|
||||||
const Discord = require('discord.js');
|
|
||||||
const client = new Discord.Client();
|
|
||||||
//const cron = require('node-cron');
|
|
||||||
|
|
||||||
// Bot Modules
|
|
||||||
//const dataRequest = require('../modules/dataRequest');
|
|
||||||
//const calcRandom = require('../modules/calcRandom');
|
|
||||||
|
|
||||||
const playingMessage = '!join | Bot Things.';
|
|
||||||
|
|
||||||
const roles = {
|
|
||||||
"roles": [
|
|
||||||
"artists",
|
|
||||||
"developers",
|
|
||||||
"designers",
|
|
||||||
"testers",
|
|
||||||
"writers"
|
|
||||||
],
|
|
||||||
|
|
||||||
"artists": {
|
|
||||||
"name": "Artists"
|
|
||||||
},
|
|
||||||
"developers": {
|
|
||||||
"name": "Developers"
|
|
||||||
},
|
|
||||||
"designers": {
|
|
||||||
"name": "Designers"
|
|
||||||
},
|
|
||||||
"testers": {
|
|
||||||
"name": "Testers"
|
|
||||||
},
|
|
||||||
"writers": {
|
|
||||||
"name": "Writers"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The ready event is vital, it means that your bot will only start reacting to information
|
|
||||||
// from Discord _after_ ready is emitted
|
|
||||||
client.on('ready', async () => {
|
|
||||||
// Generates invite link
|
|
||||||
try {
|
|
||||||
let link = await client.generateInvite(["ADMINISTRATOR"]);
|
|
||||||
console.log("Invite Link: " + link);
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can set status to 'online', 'invisible', 'away', or 'dnd' (do not disturb)
|
|
||||||
client.user.setStatus('online');
|
|
||||||
// Sets your "Playing"
|
|
||||||
client.user.setActivity(playingMessage);
|
|
||||||
console.log(`Connected! \
|
|
||||||
\nLogged in as: ${client.user.username} - (${client.user.id})`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create an event listener for messages
|
|
||||||
client.on('message', async message => {
|
|
||||||
// Ignores ALL bot messages
|
|
||||||
if (message.author.bot) return;
|
|
||||||
/*
|
|
||||||
// Message has to be in Outskirts (should be edited later)
|
|
||||||
if (!(message.channel.id === process.env.TAVERN_CHANNEL_ID
|
|
||||||
|| message.channel.id === process.env.TEST_CHANNEL_ID)) return;
|
|
||||||
// Has to be (prefix)command
|
|
||||||
if (message.content.indexOf(process.env.PREFIX) !== 0) return;
|
|
||||||
*/
|
|
||||||
// "This is the best way to define args. Trust me."
|
|
||||||
// - Some tutorial dude on the internet
|
|
||||||
const args = message.content.slice(process.env.PREFIX.length).trim().split(/ +/g);
|
|
||||||
const command = args.shift().toLowerCase();
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case "ping":
|
|
||||||
if (isAdmin(message.author.id))
|
|
||||||
message.reply("What is your command, glorious master!");
|
|
||||||
break;
|
|
||||||
case "test":
|
|
||||||
// For testing embeds
|
|
||||||
|
|
||||||
break;
|
|
||||||
case "join":
|
|
||||||
// If chose a parameter
|
|
||||||
if (args[0]) {
|
|
||||||
var moddedArgs = args[0].toLowerCase();
|
|
||||||
if (roles.roles.includes(moddedArgs)) {
|
|
||||||
console.log("[JOIN] Found it! " + moddedArgs + "\nAdding role to " + message.author.username);
|
|
||||||
|
|
||||||
// Gets specified role
|
|
||||||
var roleName = roles[moddedArgs].name;
|
|
||||||
var newRole = message.guild.roles.find(role => role.name === roleName);
|
|
||||||
|
|
||||||
// Checks if user already has roles
|
|
||||||
if (!message.member.roles.has(newRole.id)) {
|
|
||||||
// Adds Team Role
|
|
||||||
var addTeam = false;
|
|
||||||
var teamRole = message.guild.roles.find(role => role.name === "Team");
|
|
||||||
if (!message.member.roles.has(teamRole.id)) addTeam = true;
|
|
||||||
|
|
||||||
if (!addTeam) await message.member.addRole(newRole).catch(console.error);
|
|
||||||
else await message.member.addRoles([newRole, teamRole]).catch(console.error);
|
|
||||||
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor(client.user.username, client.user.avatarURL)
|
|
||||||
.setTitle("Successful")
|
|
||||||
.setDescription(`${message.author}, you have been given the ${newRole} role!`)
|
|
||||||
.setColor(message.guild.members.get(client.user.id).displayColor)
|
|
||||||
.setFooter("Check out the general category and your role specific channel!", message.author.avatarURL)
|
|
||||||
await message.channel.send(embed);
|
|
||||||
} else {
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor(client.user.username, client.user.avatarURL)
|
|
||||||
.setTitle("Failed")
|
|
||||||
.setDescription(`${message.author}, you already have the ${newRole} role!`)
|
|
||||||
.setColor(message.guild.members.get(client.user.id).displayColor)
|
|
||||||
.setFooter("To leave a role, use !leave [ROLE NAME].", message.author.avatarURL)
|
|
||||||
await message.channel.send(embed);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showErrorMessage(args, command, message);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
displayJoinMessage(message);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "leave":
|
|
||||||
// If chose a parameter
|
|
||||||
if (args[0]) {
|
|
||||||
var moddedArgs = args[0].toLowerCase();
|
|
||||||
if (roles.roles.includes(moddedArgs)) {
|
|
||||||
console.log("[LEAVE] Found it! " + moddedArgs + "\nRemoving role to " + message.author.username);
|
|
||||||
const joinRoleMessage = "To join a role, use !join [ROLE NAME].";
|
|
||||||
var playerRoles = message.member.roles.filter(role => role.name === roles[moddedArgs].name);
|
|
||||||
|
|
||||||
// Gets specified role
|
|
||||||
var roleName = roles[moddedArgs].name;
|
|
||||||
var newRole = message.guild.roles.find(role => role.name === roleName);
|
|
||||||
|
|
||||||
// Checks if user already has roles
|
|
||||||
if (message.member.roles.has(newRole.id)) {
|
|
||||||
// Removes Team Role (if it's the last "team" type role)
|
|
||||||
var removeTeam = false;
|
|
||||||
var teamRole = message.guild.roles.find(role => role.name === "Team");
|
|
||||||
var playerRoles = message.member.roles.filter(role => roles.roles.includes(role.name.toLowerCase()));
|
|
||||||
var debugString = "All the roles a user has:\n";
|
|
||||||
|
|
||||||
// Grabs
|
|
||||||
message.member.roles.forEach(element => {
|
|
||||||
debugString += `> ${element.name}\n`
|
|
||||||
});
|
|
||||||
console.log(debugString + "removeTeam = " + removeTeam);
|
|
||||||
debugString = "All the team-defined roles a user has:\n";
|
|
||||||
playerRoles.forEach(element => {
|
|
||||||
debugString += `> ${element.name}\n`
|
|
||||||
});
|
|
||||||
console.log(debugString);
|
|
||||||
|
|
||||||
if (playerRoles.size <= 1) {
|
|
||||||
if (message.member.roles.has(teamRole.id)) removeTeam = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes specified role
|
|
||||||
var roleName = roles[moddedArgs].name;
|
|
||||||
var newRole = message.guild.roles.find(role => role.name === roleName);
|
|
||||||
|
|
||||||
if (!removeTeam) {
|
|
||||||
console.log("Removed only one role: removeTeam = " + removeTeam)
|
|
||||||
await message.member.removeRole(newRole).catch(console.error);
|
|
||||||
} else {
|
|
||||||
console.log("Removing team role: removeTeam = " + removeTeam)
|
|
||||||
await message.member.removeRoles([newRole, teamRole]).catch(console.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor(client.user.username, client.user.avatarURL)
|
|
||||||
.setTitle("Successful")
|
|
||||||
.setDescription(`${message.author}, you have removed the ${newRole} role!`)
|
|
||||||
.setColor(message.guild.members.get(client.user.id).displayColor)
|
|
||||||
.setFooter(joinRoleMessage, message.author.avatarURL)
|
|
||||||
await message.channel.send(embed);
|
|
||||||
} else {
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor(client.user.username, client.user.avatarURL)
|
|
||||||
.setTitle("Failed")
|
|
||||||
.setDescription(`${message.author}, you already don't have the ${newRole} role!`)
|
|
||||||
.setColor(message.guild.members.get(client.user.id).displayColor)
|
|
||||||
.setFooter(joinRoleMessage, message.author.avatarURL)
|
|
||||||
await message.channel.send(embed);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showErrorMessage(args, command, message);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
displayJoinMessage(message);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', console.error);
|
|
||||||
|
|
||||||
// Async Waiting
|
|
||||||
function sleep(time) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
setTimeout(resolve, time);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets if user has an Overseers rank
|
|
||||||
function isAdmin(userID) {
|
|
||||||
// Developer's Discord
|
|
||||||
var guild = client.guilds.get("500140223871582228");
|
|
||||||
return guild.members.get(userID).roles.find(role => role.name === "Team Leads");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show !join message listing commands
|
|
||||||
function displayJoinMessage(message) {
|
|
||||||
var newDialog = "";
|
|
||||||
roles.roles.forEach(element => {
|
|
||||||
var roleName = roles[element].name;
|
|
||||||
var newRole = message.guild.roles.find(role => role.name === roleName);
|
|
||||||
var memberLength = newRole.members.size;
|
|
||||||
newDialog += `__${element}__ \`${memberLength} Members\`\n`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor(client.user.username, client.user.avatarURL)
|
|
||||||
.setTitle("Roles")
|
|
||||||
.setDescription(newDialog)
|
|
||||||
.setColor(message.guild.members.get(client.user.id).displayColor)
|
|
||||||
.setFooter("To join or leave a role, use !join [ROLE NAME] or !leave [ROLE NAME].")
|
|
||||||
|
|
||||||
message.channel.send(embed);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shows error messages for !join and !leave for unknown roles
|
|
||||||
function showErrorMessage(args, command, message) {
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor(client.user.username, client.user.avatarURL)
|
|
||||||
.setTitle("Failed")
|
|
||||||
.setDescription(`Sorry, I couldn't find the "${args[0]}" role.`)
|
|
||||||
.setFooter(`Use !${command} to get a list of roles to ${command}.`)
|
|
||||||
.setColor(message.guild.members.get(client.user.id).displayColor)
|
|
||||||
|
|
||||||
message.channel.send(embed);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log our bot in (change the token by looking into the .env file)
|
|
||||||
client.login(process.env.DEVELOPER_TOKEN);
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "developerdiscord",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "Developer Discord Bot",
|
|
||||||
"main": "developerdiscord.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/TimRuswick/SANCTUM.git"
|
|
||||||
},
|
|
||||||
"author": "TheSomeoneXD",
|
|
||||||
"license": "MIT",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/TimRuswick/SANCTUM/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/TimRuswick/SANCTUM#readme",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
571
Enemy/enemy.js
571
Enemy/enemy.js
@@ -1,571 +0,0 @@
|
|||||||
// .env Variables
|
|
||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
// Node Modules
|
|
||||||
const Discord = require('discord.js');
|
|
||||||
const client = new Discord.Client();
|
|
||||||
const cron = require('node-cron');
|
|
||||||
const io = require('socket.io-client');
|
|
||||||
|
|
||||||
// Make connection
|
|
||||||
var socket = io.connect('http://localhost:80');
|
|
||||||
|
|
||||||
// Bot Modules
|
|
||||||
const npcSettings = require('./npcSettings')
|
|
||||||
const dataRequest = require('../modules/dataRequest');
|
|
||||||
const calcRandom = require('../modules/calcRandom');
|
|
||||||
|
|
||||||
// State Machine
|
|
||||||
var EnemyState = {
|
|
||||||
INACTIVE: 0,
|
|
||||||
PROWLING: 1,
|
|
||||||
ACTIVE: 2,
|
|
||||||
UNCONSCIOUS: 3
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enemy lists
|
|
||||||
class EnemyBatchInstance {
|
|
||||||
constructor(channel) {
|
|
||||||
this.state = EnemyState.INACTIVE;
|
|
||||||
this.enemies = []; // Array of `new Enemy()`s
|
|
||||||
this.channel = channel; // Channel of spawning
|
|
||||||
this.spawnPrecentage = 100;
|
|
||||||
this.hostileLevel = 1;
|
|
||||||
this.fastSummon = false; // Show prowling
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enemy instance
|
|
||||||
class Enemy {
|
|
||||||
constructor(type) {
|
|
||||||
this.state = EnemyState.INACTIVE;
|
|
||||||
this.type = type;
|
|
||||||
this.level = 1;
|
|
||||||
this.health = 420;
|
|
||||||
this.speed = 21;
|
|
||||||
this.strength = 33;
|
|
||||||
this.stash = 0;
|
|
||||||
this.fleeTime = undefined;
|
|
||||||
this.guid = undefined;
|
|
||||||
this.deletePrevMessage = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates flee time by randomization
|
|
||||||
get randomFleeTime() {
|
|
||||||
var randomFleeTime;
|
|
||||||
randomFleeTime = calcRandom.random(3 * 60 * 1000, 6 * 60 * 1000);
|
|
||||||
randomFleeTime -= (randomFleeTime % 1000);
|
|
||||||
return randomFleeTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var enemyBatchCollection = [];
|
|
||||||
|
|
||||||
// Spawning patterns
|
|
||||||
var spawnPatterns = {
|
|
||||||
"types": ['default', 'randomBatch2'],
|
|
||||||
"default": {
|
|
||||||
"ravager": {
|
|
||||||
"amount": 1
|
|
||||||
},
|
|
||||||
"type": "incrememt"
|
|
||||||
},
|
|
||||||
"randomBatch2": {
|
|
||||||
"amount": 2,
|
|
||||||
"type": "incrememt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var socketReady = false;
|
|
||||||
socket.on('spawn', (data) => {
|
|
||||||
if (!socketReady) return;
|
|
||||||
|
|
||||||
console.log(JSON.stringify(data, null, 4));
|
|
||||||
console.log(`Summoning enemies...`);
|
|
||||||
|
|
||||||
// Spawns
|
|
||||||
summonEnemy(data);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// The ready event is vital, it means that your bot will only start reacting to information
|
|
||||||
// from Discord _after_ ready is emitted
|
|
||||||
client.on('ready', async () => {
|
|
||||||
socketReady = true;
|
|
||||||
|
|
||||||
// Generates invite link
|
|
||||||
try {
|
|
||||||
let link = await client.generateInvite(["ADMINISTRATOR"]);
|
|
||||||
console.log("Invite Link: " + link);
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can set status to 'online', 'invisible', 'away', or 'dnd' (do not disturb)
|
|
||||||
client.user.setStatus('invisible');
|
|
||||||
// Sets your "Playing"
|
|
||||||
if (npcSettings.activity) {
|
|
||||||
client.user.setActivity(npcSettings.activity, { type: npcSettings.type })
|
|
||||||
.then(presence => console.log(`Activity set to ${presence.game ? presence.game.name : 'none'}`))
|
|
||||||
.catch(console.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Connected! \
|
|
||||||
\nLogged in as: ${client.user.username} - (${client.user.id})`);
|
|
||||||
|
|
||||||
// Corrects Ravager username
|
|
||||||
if (client.user.username == "Raveger") {
|
|
||||||
const newName = "Ravager";
|
|
||||||
console.log("Username is Raveger! Typos are NOT(?) cannon, so better change stuff.\nAttempting rename to " + newName + "...");
|
|
||||||
|
|
||||||
// Set username
|
|
||||||
client.user.setUsername(newName)
|
|
||||||
.then(user => console.log(`Success! New username is now ${user.username}.`))
|
|
||||||
.catch(console.error);
|
|
||||||
|
|
||||||
// Changes nickname
|
|
||||||
client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id).setNickname("");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create an event listener for messages
|
|
||||||
client.on('message', async message => {
|
|
||||||
// Ignores ALL bot messages
|
|
||||||
if (message.author.bot) return;
|
|
||||||
// Message has to be in Outskirts (should be edited later)
|
|
||||||
if (!(message.channel.id === process.env.DEADLANDS_CHANNEL_ID
|
|
||||||
|| message.channel.id === process.env.TEST_CHANNEL_ID)) return;
|
|
||||||
// Has to be (prefix)command
|
|
||||||
if (message.content.indexOf(process.env.PREFIX) !== 0) return;
|
|
||||||
|
|
||||||
// "This is the best way to define args. Trust me."
|
|
||||||
// - Some tutorial dude on the internet
|
|
||||||
const args = message.content.slice(process.env.PREFIX.length).trim().split(/ +/g);
|
|
||||||
const command = args.shift().toLowerCase();
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case "ping":
|
|
||||||
if (isAdmin(message.author.id))
|
|
||||||
message.reply("***...MRGRGRGR!***");
|
|
||||||
break;
|
|
||||||
case npcSettings.id:
|
|
||||||
if (args[0].toLowerCase() === "summon" && isAdmin(message.author.id)) {
|
|
||||||
generateEnemy(process.env.DEADLANDS_CHANNEL_ID);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', console.error);
|
|
||||||
|
|
||||||
cron.schedule('*/10 * * * *', function() {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
async function generateEnemy(channelID) {
|
|
||||||
console.log("Generating enemy...")
|
|
||||||
|
|
||||||
// Gets an enemy batch instance, or creates if non-existant
|
|
||||||
var index = enemyBatchCollection.findIndex(data => data.channel === channelID);
|
|
||||||
var enemyBatch;
|
|
||||||
console.log(index <= -1)
|
|
||||||
if (index <= -1) {
|
|
||||||
enemyBatch = new EnemyBatchInstance(channelID);
|
|
||||||
} else {
|
|
||||||
enemyBatch = enemyBatchCollection[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a spawn pattern
|
|
||||||
var randomSpawnPattern = spawnPatterns.types[calcRandom.randomExc(0, spawnPatterns.types.length)];
|
|
||||||
var newSpawnPattern = spawnPatterns[randomSpawnPattern];
|
|
||||||
newSpawnPattern = spawnPatterns["default"]; // Overruled!
|
|
||||||
|
|
||||||
// Creates a bunch of new enemies
|
|
||||||
var amount = newSpawnPattern[npcSettings.id].amount;
|
|
||||||
var newEnemies = [];
|
|
||||||
for (let i = 0; i < amount; i++) {
|
|
||||||
var enemy = new Enemy(npcSettings.id);
|
|
||||||
var elevel = enemyBatch.hostileLevel;
|
|
||||||
|
|
||||||
// Replication of newHostile in sendData.php
|
|
||||||
const healthBase = 50; const strengthBase = 3; const speedBase = 3; const stashBase = 3;
|
|
||||||
|
|
||||||
const healthMin = (healthBase * elevel) / 2;
|
|
||||||
const healthMax = healthBase * elevel;
|
|
||||||
|
|
||||||
const strengthMin = (strengthBase * elevel) / 2;
|
|
||||||
const strengthMax = strengthBase * elevel;
|
|
||||||
|
|
||||||
const speedMin = (speedBase * elevel) / 2;
|
|
||||||
const speedMax = speedBase * elevel;
|
|
||||||
|
|
||||||
const stashMin = (stashBase * elevel) / 2;
|
|
||||||
const stashMax = stashBase * elevel;
|
|
||||||
|
|
||||||
const health = Math.floor(calcRandom.randomExc(healthMin, healthMax));
|
|
||||||
const strength = Math.floor(calcRandom.randomExc(strengthMin, strengthMax));
|
|
||||||
const speed = Math.floor(calcRandom.randomExc(speedMin, speedMax));
|
|
||||||
const stash = Math.floor(calcRandom.randomExc(stashMin, stashMax));
|
|
||||||
|
|
||||||
enemy.level = elevel;
|
|
||||||
enemy.health = health;
|
|
||||||
enemy.strength = strength;
|
|
||||||
enemy.speed = speed;
|
|
||||||
enemy.stash = stash;
|
|
||||||
enemy.state = EnemyState.PROWLING;
|
|
||||||
enemy.fleeTime = enemy.randomFleeTime;
|
|
||||||
enemy.guid = guidGenerator();
|
|
||||||
|
|
||||||
// Logs stats
|
|
||||||
console.log(`\n[===== | Enemy Stats | =====]`);
|
|
||||||
console.log(`HEALTH: ${health} > ${healthMin} - ${healthMax}`);
|
|
||||||
console.log(`STRENGTH: ${strength} > ${strengthMin} - ${strengthMax}`);
|
|
||||||
console.log(`SPEED: ${speed} > ${speedMin} - ${speedMax}`);
|
|
||||||
console.log(`STASH: ${stash} > ${stashMin} - ${stashMax}`);
|
|
||||||
console.log(`[===========================]\n`);
|
|
||||||
newEnemies.push(enemy);
|
|
||||||
}
|
|
||||||
enemyBatch.enemies = newEnemies;
|
|
||||||
enemyBatch.hostileLevel++;
|
|
||||||
|
|
||||||
console.log(JSON.stringify(newEnemies, null, 2));
|
|
||||||
|
|
||||||
if (calcRandom.gamble(enemyBatch.spawnPrecentage)) {
|
|
||||||
enemyBatch.spawnPrecentage = 50;
|
|
||||||
|
|
||||||
// Creation of Ravager timer
|
|
||||||
var creationTime = calcRandom.random(35000, 540000);
|
|
||||||
creationTime = 3 * 1000; // shortcuts
|
|
||||||
|
|
||||||
console.log(`[Enemy Spawn] ${amount} "${npcSettings.id}" will be created in ${fmtMSS(creationTime / 1000)} min.`);
|
|
||||||
await sleep(creationTime);
|
|
||||||
console.log(`[Enemy Spawn] ${amount} "${npcSettings.id}" has spawned!`);
|
|
||||||
summonEnemy(enemyBatch);
|
|
||||||
|
|
||||||
enemyBatch.hostileLevel++;
|
|
||||||
} else {
|
|
||||||
console.log("[Enemy Spawn] Fail to spawn. Adding 10% more to chances.");
|
|
||||||
enemyBatch.spawnPrecentage += 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turn online and turn offline
|
|
||||||
async function summonEnemy(data) {
|
|
||||||
// If timer exists, do outpost
|
|
||||||
const summonTime = 4; // 4 is debug, normal is 35
|
|
||||||
if (!data.fastSummon) {
|
|
||||||
console.log(`Summoning Ravager... waiting for ${summonTime} seconds.`);
|
|
||||||
client.user.setStatus('online');
|
|
||||||
client.user.setActivity(`Prowling...`);
|
|
||||||
|
|
||||||
// Sets prowling states on the Ravagers
|
|
||||||
for (let i = 0; i < data.enemies.length; i++) {
|
|
||||||
const element = data.enemies[i];
|
|
||||||
element.state = EnemyState.PROWLING;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notification code
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
await sleep(summonTime * 1000);
|
|
||||||
}
|
|
||||||
console.log("Enemy has spawned!");
|
|
||||||
|
|
||||||
// Goes thru all enemies in array
|
|
||||||
for (let i = 0; i < data.enemies.length; i++) {
|
|
||||||
const element = data.enemies[i];
|
|
||||||
const hostileStats = `LVL: ${element.level} | HP: ${element.health} | STR: ${element.strength} | SPD: ${element.speed}`;
|
|
||||||
|
|
||||||
const ravagerMember = client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id);
|
|
||||||
const appearanceEmbed = new Discord.RichEmbed()
|
|
||||||
.setAuthor(ravagerMember.displayName, client.user.avatarURL)
|
|
||||||
.setColor(ravagerMember.displayColor)
|
|
||||||
.setDescription(`${healthbar(element.health, element.health)}\n` + "```" + hostileStats + "```")
|
|
||||||
|
|
||||||
var newMessage = await client.channels.get(data.channel).send(getDialog("onTheProwl"), {embed: appearanceEmbed});
|
|
||||||
await client.user.setStatus('online');
|
|
||||||
await client.user.setActivity(hostileStats);
|
|
||||||
|
|
||||||
for (let i = 0; i < data.enemies.length; i++) {
|
|
||||||
const element = data.enemies[i];
|
|
||||||
element.state = EnemyState.ACTIVE;
|
|
||||||
}
|
|
||||||
enemyTimer(element, data, data.channel, element.fleeTime, newMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Counts down
|
|
||||||
async function enemyTimer(newEnemy, data, channel, fleeTime, newMessage) {
|
|
||||||
function addUserToArray(userID) {
|
|
||||||
attackingUsers.push(userID);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function sendReactions(options) {
|
|
||||||
// Sends reactions
|
|
||||||
for (let i = 0; i < options.length; i++) {
|
|
||||||
const element = options[i];
|
|
||||||
//console.log("[Reaction Options] Emote: " + element + " | newMessage: " + newMessage);
|
|
||||||
await newMessage.react(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Waiting for the next ${fmtMSS(fleeTime / 1000)} min. to check if Ravager has been killed. ${fleeTime}`);
|
|
||||||
|
|
||||||
const ravagerMember = client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id);
|
|
||||||
const interactionEmbed = new Discord.RichEmbed()
|
|
||||||
.setColor(ravagerMember.displayColor)
|
|
||||||
.setTitle("Status")
|
|
||||||
.setDescription("...")
|
|
||||||
|
|
||||||
const sendMessageMinimum = true;
|
|
||||||
var isReadyToFlee = false;
|
|
||||||
var attackingUsers = [];
|
|
||||||
var tempAttackUsers = "";
|
|
||||||
var newChannel = client.channels.get(channel);
|
|
||||||
var interactionMessage = await newChannel.send({embed: interactionEmbed});
|
|
||||||
|
|
||||||
// Possible reaction attacks can go here
|
|
||||||
var options = ['💥', '🇦', '🇧', '🇨']
|
|
||||||
|
|
||||||
// System for no message sending except the minimum
|
|
||||||
if (sendMessageMinimum) {
|
|
||||||
// Collects emotes and reacts upon the reaction
|
|
||||||
const collector = newMessage.createReactionCollector(
|
|
||||||
(reaction, user) => options.includes(reaction.emoji.name) && user.id !== client.user.id);
|
|
||||||
|
|
||||||
sendReactions(options);
|
|
||||||
|
|
||||||
// Collect
|
|
||||||
collector.on("collect", async reaction => {
|
|
||||||
var user = reaction.users.last();
|
|
||||||
|
|
||||||
// Just in case, I managed to bug out Ravager to display its own name.
|
|
||||||
if (user.id === client.user.id) {
|
|
||||||
console.log("Well then. It bypassed the collector filter, we're stopping the Ravager from attacking itself. Would be interesting though!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send damage to server
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
tempAttackUsers += `${user} :crossed_swords: 11 DAM | <:hitback:460969716580745236> MISS (150/150)\n`;
|
|
||||||
addUserToArray(user.id);
|
|
||||||
console.log("Collecting a user! " + user.username)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ends
|
|
||||||
collector.once("end", async collector => {
|
|
||||||
console.log("Ended collector.")
|
|
||||||
flee(newEnemy, data, client.channels.get(channel));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Goes every 4 seconds
|
|
||||||
var emoteRefresh = setInterval(async () => {
|
|
||||||
await newMessage.clearReactions();
|
|
||||||
|
|
||||||
if (isReadyToFlee && newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log("Has fled!");
|
|
||||||
//interactionEmbed.setDescription("👣 The Ravager has fled...")
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
clearInterval(emoteRefresh);
|
|
||||||
collector.stop();
|
|
||||||
} else {
|
|
||||||
console.log("Sending refreshed embed... |" + tempAttackUsers + "|")
|
|
||||||
if (tempAttackUsers === "") tempAttackUsers = "...";
|
|
||||||
interactionEmbed.setDescription(tempAttackUsers);
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
sendReactions(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
tempAttackUsers = "";
|
|
||||||
}, 5 * 1000);
|
|
||||||
|
|
||||||
|
|
||||||
// Waits to see if killed, and if not send a fleeing message
|
|
||||||
await sleep(fleeTime);
|
|
||||||
if (newEnemy.state === EnemyState.ACTIVE) {
|
|
||||||
newChannel.send("**YOU ARE WEAK. THERE IS NO CHALLENGE FOR ME HERE.**\n:bangbang:***ATTEMPTING TO FLEE...***");
|
|
||||||
await sleep(20 * 1000);
|
|
||||||
|
|
||||||
// If still there despawn
|
|
||||||
if (newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log('Hostile is now able to flee, now awaiting for collector to finish.');
|
|
||||||
isReadyToFlee = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Collects emotes and reacts upon the reaction
|
|
||||||
var collector = newMessage.createReactionCollector(
|
|
||||||
(reaction, user) => options.includes(reaction.emoji.name) && user.id !== client.user.id);
|
|
||||||
|
|
||||||
sendReactions(options);
|
|
||||||
|
|
||||||
// Collect
|
|
||||||
collector.on("collect", async reaction => {
|
|
||||||
var user = reaction.users.last();
|
|
||||||
|
|
||||||
// Just in case, I managed to bug out Ravager to display its own name.
|
|
||||||
if (user.id === client.user.id) {
|
|
||||||
console.log("Well then. It bypassed the collector filter, we're stopping the Ravager from attacking itself. Would be interesting though!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send damage to server
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
tempAttackUsers += `${user} :crossed_swords: 11 DAM | <:hitback:460969716580745236> MISS (150/150)\n`;
|
|
||||||
addUserToArray(user.id);
|
|
||||||
console.log("Collecting a user! " + user.username)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ends
|
|
||||||
collector.once("end", async collector => {
|
|
||||||
console.log("Ended collector.")
|
|
||||||
flee(newEnemy, data, client.channels.get(channel));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Goes every 4 seconds
|
|
||||||
var emoteRefresh = setInterval(async () => {
|
|
||||||
await newMessage.clearReactions();
|
|
||||||
|
|
||||||
if (isReadyToFlee && newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log("Has fled!");
|
|
||||||
//interactionEmbed.setDescription("👣 The Ravager has fled...")
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
clearInterval(emoteRefresh);
|
|
||||||
collector.stop();
|
|
||||||
} else {
|
|
||||||
console.log("Sending refreshed embed... |" + tempAttackUsers + "|")
|
|
||||||
if (tempAttackUsers === "") tempAttackUsers = "...";
|
|
||||||
interactionEmbed.setDescription(tempAttackUsers);
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
sendReactions(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
tempAttackUsers = "";
|
|
||||||
}, 5 * 1000);
|
|
||||||
|
|
||||||
|
|
||||||
// Waits to see if killed, and if not send a fleeing message
|
|
||||||
await sleep(fleeTime);
|
|
||||||
if (newEnemy.state === EnemyState.ACTIVE) {
|
|
||||||
newChannel.send("**YOU ARE WEAK. THERE IS NO CHALLENGE FOR ME HERE.**\n:bangbang:***ATTEMPTING TO FLEE...***");
|
|
||||||
await sleep(20 * 1000);
|
|
||||||
|
|
||||||
// If still there despawn
|
|
||||||
if (newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log('Hostile is now able to flee, now awaiting for collector to finish.');
|
|
||||||
isReadyToFlee = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Does flee sequence
|
|
||||||
async function flee(newEnemy, data, newChannel) {
|
|
||||||
newChannel.send("**THE POOR, ILL-EQUIPPED TRAVELERS PUT UP NO FIGHT...**\n:footprints:***RETURNS TO THE WILD. ***");
|
|
||||||
socket.emit('fled', {
|
|
||||||
data: data,
|
|
||||||
ravager: newEnemy
|
|
||||||
});
|
|
||||||
|
|
||||||
if (data.length < 1) {
|
|
||||||
await client.user.setPresence('invisible');
|
|
||||||
client.user.setActivity('Prowling...');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Health bar
|
|
||||||
function healthbar(health, maxHealth) {
|
|
||||||
var heartHealthAmount = 30;
|
|
||||||
var printString = "";
|
|
||||||
var amountMultiple = 0;
|
|
||||||
var timesToLoop = Math.floor(maxHealth / heartHealthAmount);
|
|
||||||
for (var i = 0; i < timesToLoop; i++) {
|
|
||||||
amountMultiple = i * heartHealthAmount;
|
|
||||||
if (amountMultiple < health) {
|
|
||||||
printString += ":heart: ";
|
|
||||||
} else {
|
|
||||||
printString += ":black_heart:";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printString += " (" + health + "/" + maxHealth + ")";
|
|
||||||
return printString;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Async Waiting
|
|
||||||
function sleep(time) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
setTimeout(resolve, time);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets if user has an Overseers rank
|
|
||||||
function isAdmin(userID) {
|
|
||||||
var guild = client.guilds.get(process.env.SANCTUM_ID);
|
|
||||||
return guild.members.get(userID).roles.find(role => role.name === "Overseers");
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/3733227/javascript-seconds-to-minutes-and-seconds
|
|
||||||
function fmtMSS(s){ // accepts seconds as Number or String. Returns m:ss
|
|
||||||
return( s - // take value s and subtract (will try to convert String to Number)
|
|
||||||
( s %= 60 ) // the new value of s, now holding the remainder of s divided by 60
|
|
||||||
// (will also try to convert String to Number)
|
|
||||||
) / 60 + ( // and divide the resulting Number by 60
|
|
||||||
// (can never result in a fractional value = no need for rounding)
|
|
||||||
// to which we concatenate a String (converts the Number to String)
|
|
||||||
// who's reference is chosen by the conditional operator:
|
|
||||||
9 < s // if seconds is larger than 9
|
|
||||||
? ':' // then we don't need to prepend a zero
|
|
||||||
: ':0' // else we do need to prepend a zero
|
|
||||||
) + s ; // and we add Number s to the string (converting it to String as well)
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/6860853/generate-random-string-for-div-id/6860916#6860916
|
|
||||||
function guidGenerator() {
|
|
||||||
var S4 = function() {
|
|
||||||
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
|
|
||||||
};
|
|
||||||
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDialog(dialogTag, data = "", data2 = "") {
|
|
||||||
switch(dialogTag) {
|
|
||||||
case "onTheProwl":
|
|
||||||
var dialogOptions = [
|
|
||||||
'THE AIR SMELLS OF BLOOD.',
|
|
||||||
'LOOKS LIKE MEAT\'S BACK ON THE MENU BOYS.',
|
|
||||||
'FRESH MEAAAATTTT.',
|
|
||||||
'TONIGHT WE DINE ON TRAVELER FLESSHHHH.',
|
|
||||||
'SKULL CRUSHING IS MY FAVORITE SPORT.',
|
|
||||||
'HUNGRY...',
|
|
||||||
'TRAVELERS MAKE GOOD MEEEAAAAT!',
|
|
||||||
'PUNY TRAVELER THINKS THEY CAN FIGHT?!',
|
|
||||||
'HUNT THEM ALL DOWN.',
|
|
||||||
'I HUNGER FOR THE TASTE OF FLESH.'
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
return "***" + dialogOptions[randomNumber] + "***";
|
|
||||||
|
|
||||||
case "ravagerHit":
|
|
||||||
var dialogOptions = [
|
|
||||||
'STAGGERS BACK',
|
|
||||||
'FALLS BACKWARDS',
|
|
||||||
'CHARGES FORWARD CONFUSED',
|
|
||||||
'LOOKS FOR THE SOURCE OF THE HIT',
|
|
||||||
'FALLS FORWARDS',
|
|
||||||
'BLOCKS ITS FACE',
|
|
||||||
'STUMBLES BACKWARDS IN CONFUSION',
|
|
||||||
'LUNGES FORWARD DISTRACTED',
|
|
||||||
'BITES AT IT\'S ATTACKER',
|
|
||||||
'CHECKS IT\'S WOUND'
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
return `***${dialogOptions[randomNumber]}***`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log our bot in (change the token by looking into the .env file)
|
|
||||||
client.login(process.env.RAVAGER_TOKEN);
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
id: "ravager",
|
|
||||||
activity: "Prowling...",
|
|
||||||
type: "PLAYING",
|
|
||||||
token: process.env.RAVAGER_TOKEN,
|
|
||||||
botChannel: process.env.DEADLANDS_CHANNEL_ID
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "sanctum-deploypackage",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"description": "Universal package for all SANCTUM bots, using pm2.",
|
|
||||||
"main": "",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "echo \"Error: you need to use the bot name as a command.\" && exit 1",
|
|
||||||
"alexis": "pm2 start alexis.js -i max --watch",
|
|
||||||
"graze": "pm2 start graze.js -i max --watch",
|
|
||||||
"librarian": "pm2 start librarian.js -i max --watch",
|
|
||||||
"mainframe": "pm2 start mainframe.js -i max --watch",
|
|
||||||
"mori": "pm2 start mori.js -i max --watch",
|
|
||||||
"mosiah": "pm2 start mosiah.js -i max --watch",
|
|
||||||
"ravager": "pm2 start enemy-ravager.js -i max --watch",
|
|
||||||
"wolf": "pm2 start enemy-wolf.js -i max --watch",
|
|
||||||
"crow": "pm2 start enemy-crow.js -i max --watch",
|
|
||||||
"rey": "pm2 start rey.js -i max --watch",
|
|
||||||
"troll": "pm2 start troll.js -i max --watch"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2",
|
|
||||||
"dotenv": "^6.0.0",
|
|
||||||
"express": "^4.16.3",
|
|
||||||
"node-cron": "^1.2.1",
|
|
||||||
"socket.io": "^2.1.1",
|
|
||||||
"socket.io-request": "^0.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,571 +0,0 @@
|
|||||||
// .env Variables
|
|
||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
// Node Modules
|
|
||||||
const Discord = require('discord.js');
|
|
||||||
const client = new Discord.Client();
|
|
||||||
const cron = require('node-cron');
|
|
||||||
const io = require('socket.io-client');
|
|
||||||
|
|
||||||
// Make connection
|
|
||||||
var socket = io.connect('http://localhost:80');
|
|
||||||
|
|
||||||
// Bot Modules
|
|
||||||
const npcSettings = require('./npcSettings')
|
|
||||||
const dataRequest = require('../modules/dataRequest');
|
|
||||||
const calcRandom = require('../modules/calcRandom');
|
|
||||||
|
|
||||||
// State Machine
|
|
||||||
var EnemyState = {
|
|
||||||
INACTIVE: 0,
|
|
||||||
PROWLING: 1,
|
|
||||||
ACTIVE: 2,
|
|
||||||
UNCONSCIOUS: 3
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enemy lists
|
|
||||||
class EnemyBatchInstance {
|
|
||||||
constructor(channel) {
|
|
||||||
this.state = EnemyState.INACTIVE;
|
|
||||||
this.enemies = []; // Array of `new Enemy()`s
|
|
||||||
this.channel = channel; // Channel of spawning
|
|
||||||
this.spawnPrecentage = 100;
|
|
||||||
this.hostileLevel = 1;
|
|
||||||
this.fastSummon = false; // Show prowling
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enemy instance
|
|
||||||
class Enemy {
|
|
||||||
constructor(type) {
|
|
||||||
this.state = EnemyState.INACTIVE;
|
|
||||||
this.type = type;
|
|
||||||
this.level = 1;
|
|
||||||
this.health = 420;
|
|
||||||
this.speed = 21;
|
|
||||||
this.strength = 33;
|
|
||||||
this.stash = 0;
|
|
||||||
this.fleeTime = undefined;
|
|
||||||
this.guid = undefined;
|
|
||||||
this.deletePrevMessage = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates flee time by randomization
|
|
||||||
get randomFleeTime() {
|
|
||||||
var randomFleeTime;
|
|
||||||
randomFleeTime = calcRandom.random(3 * 60 * 1000, 6 * 60 * 1000);
|
|
||||||
randomFleeTime -= (randomFleeTime % 1000);
|
|
||||||
return randomFleeTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var enemyBatchCollection = [];
|
|
||||||
|
|
||||||
// Spawning patterns
|
|
||||||
var spawnPatterns = {
|
|
||||||
"types": ['default', 'randomBatch2'],
|
|
||||||
"default": {
|
|
||||||
"ravager": {
|
|
||||||
"amount": 1
|
|
||||||
},
|
|
||||||
"type": "incrememt"
|
|
||||||
},
|
|
||||||
"randomBatch2": {
|
|
||||||
"amount": 2,
|
|
||||||
"type": "incrememt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var socketReady = false;
|
|
||||||
socket.on('spawn', (data) => {
|
|
||||||
if (!socketReady) return;
|
|
||||||
|
|
||||||
console.log(JSON.stringify(data, null, 4));
|
|
||||||
console.log(`Summoning enemies...`);
|
|
||||||
|
|
||||||
// Spawns
|
|
||||||
summonEnemy(data);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// The ready event is vital, it means that your bot will only start reacting to information
|
|
||||||
// from Discord _after_ ready is emitted
|
|
||||||
client.on('ready', async () => {
|
|
||||||
socketReady = true;
|
|
||||||
|
|
||||||
// Generates invite link
|
|
||||||
try {
|
|
||||||
let link = await client.generateInvite(["ADMINISTRATOR"]);
|
|
||||||
console.log("Invite Link: " + link);
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can set status to 'online', 'invisible', 'away', or 'dnd' (do not disturb)
|
|
||||||
client.user.setStatus('invisible');
|
|
||||||
// Sets your "Playing"
|
|
||||||
if (npcSettings.activity) {
|
|
||||||
client.user.setActivity(npcSettings.activity, { type: npcSettings.type })
|
|
||||||
.then(presence => console.log(`Activity set to ${presence.game ? presence.game.name : 'none'}`))
|
|
||||||
.catch(console.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Connected! \
|
|
||||||
\nLogged in as: ${client.user.username} - (${client.user.id})`);
|
|
||||||
|
|
||||||
// Corrects Ravager username
|
|
||||||
if (client.user.username == "Raveger") {
|
|
||||||
const newName = "Ravager";
|
|
||||||
console.log("Username is Raveger! Typos are NOT(?) cannon, so better change stuff.\nAttempting rename to " + newName + "...");
|
|
||||||
|
|
||||||
// Set username
|
|
||||||
client.user.setUsername(newName)
|
|
||||||
.then(user => console.log(`Success! New username is now ${user.username}.`))
|
|
||||||
.catch(console.error);
|
|
||||||
|
|
||||||
// Changes nickname
|
|
||||||
client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id).setNickname("");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create an event listener for messages
|
|
||||||
client.on('message', async message => {
|
|
||||||
// Ignores ALL bot messages
|
|
||||||
if (message.author.bot) return;
|
|
||||||
// Message has to be in Outskirts (should be edited later)
|
|
||||||
if (!(message.channel.id === process.env.DEADLANDS_CHANNEL_ID
|
|
||||||
|| message.channel.id === process.env.TEST_CHANNEL_ID)) return;
|
|
||||||
// Has to be (prefix)command
|
|
||||||
if (message.content.indexOf(process.env.PREFIX) !== 0) return;
|
|
||||||
|
|
||||||
// "This is the best way to define args. Trust me."
|
|
||||||
// - Some tutorial dude on the internet
|
|
||||||
const args = message.content.slice(process.env.PREFIX.length).trim().split(/ +/g);
|
|
||||||
const command = args.shift().toLowerCase();
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case "ping":
|
|
||||||
if (isAdmin(message.author.id))
|
|
||||||
message.reply("***...MRGRGRGR!***");
|
|
||||||
break;
|
|
||||||
case npcSettings.id:
|
|
||||||
if (args[0].toLowerCase() === "summon" && isAdmin(message.author.id)) {
|
|
||||||
generateEnemy(process.env.DEADLANDS_CHANNEL_ID);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', console.error);
|
|
||||||
|
|
||||||
cron.schedule('*/10 * * * *', function() {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
async function generateEnemy(channelID) {
|
|
||||||
console.log("Generating enemy...")
|
|
||||||
|
|
||||||
// Gets an enemy batch instance, or creates if non-existant
|
|
||||||
var index = enemyBatchCollection.findIndex(data => data.channel === channelID);
|
|
||||||
var enemyBatch;
|
|
||||||
console.log(index <= -1)
|
|
||||||
if (index <= -1) {
|
|
||||||
enemyBatch = new EnemyBatchInstance(channelID);
|
|
||||||
} else {
|
|
||||||
enemyBatch = enemyBatchCollection[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a spawn pattern
|
|
||||||
var randomSpawnPattern = spawnPatterns.types[calcRandom.randomExc(0, spawnPatterns.types.length)];
|
|
||||||
var newSpawnPattern = spawnPatterns[randomSpawnPattern];
|
|
||||||
newSpawnPattern = spawnPatterns["default"]; // Overruled!
|
|
||||||
|
|
||||||
// Creates a bunch of new enemies
|
|
||||||
var amount = newSpawnPattern[npcSettings.id].amount;
|
|
||||||
var newEnemies = [];
|
|
||||||
for (let i = 0; i < amount; i++) {
|
|
||||||
var enemy = new Enemy(npcSettings.id);
|
|
||||||
var elevel = enemyBatch.hostileLevel;
|
|
||||||
|
|
||||||
// Replication of newHostile in sendData.php
|
|
||||||
const healthBase = 50; const strengthBase = 3; const speedBase = 3; const stashBase = 3;
|
|
||||||
|
|
||||||
const healthMin = (healthBase * elevel) / 2;
|
|
||||||
const healthMax = healthBase * elevel;
|
|
||||||
|
|
||||||
const strengthMin = (strengthBase * elevel) / 2;
|
|
||||||
const strengthMax = strengthBase * elevel;
|
|
||||||
|
|
||||||
const speedMin = (speedBase * elevel) / 2;
|
|
||||||
const speedMax = speedBase * elevel;
|
|
||||||
|
|
||||||
const stashMin = (stashBase * elevel) / 2;
|
|
||||||
const stashMax = stashBase * elevel;
|
|
||||||
|
|
||||||
const health = Math.floor(calcRandom.randomExc(healthMin, healthMax));
|
|
||||||
const strength = Math.floor(calcRandom.randomExc(strengthMin, strengthMax));
|
|
||||||
const speed = Math.floor(calcRandom.randomExc(speedMin, speedMax));
|
|
||||||
const stash = Math.floor(calcRandom.randomExc(stashMin, stashMax));
|
|
||||||
|
|
||||||
enemy.level = elevel;
|
|
||||||
enemy.health = health;
|
|
||||||
enemy.strength = strength;
|
|
||||||
enemy.speed = speed;
|
|
||||||
enemy.stash = stash;
|
|
||||||
enemy.state = EnemyState.PROWLING;
|
|
||||||
enemy.fleeTime = enemy.randomFleeTime;
|
|
||||||
enemy.guid = guidGenerator();
|
|
||||||
|
|
||||||
// Logs stats
|
|
||||||
console.log(`\n[===== | Enemy Stats | =====]`);
|
|
||||||
console.log(`HEALTH: ${health} > ${healthMin} - ${healthMax}`);
|
|
||||||
console.log(`STRENGTH: ${strength} > ${strengthMin} - ${strengthMax}`);
|
|
||||||
console.log(`SPEED: ${speed} > ${speedMin} - ${speedMax}`);
|
|
||||||
console.log(`STASH: ${stash} > ${stashMin} - ${stashMax}`);
|
|
||||||
console.log(`[===========================]\n`);
|
|
||||||
newEnemies.push(enemy);
|
|
||||||
}
|
|
||||||
enemyBatch.enemies = newEnemies;
|
|
||||||
enemyBatch.hostileLevel++;
|
|
||||||
|
|
||||||
console.log(JSON.stringify(newEnemies, null, 2));
|
|
||||||
|
|
||||||
if (calcRandom.gamble(enemyBatch.spawnPrecentage)) {
|
|
||||||
enemyBatch.spawnPrecentage = 50;
|
|
||||||
|
|
||||||
// Creation of Ravager timer
|
|
||||||
var creationTime = calcRandom.random(35000, 540000);
|
|
||||||
creationTime = 3 * 1000; // shortcuts
|
|
||||||
|
|
||||||
console.log(`[Enemy Spawn] ${amount} "${npcSettings.id}" will be created in ${fmtMSS(creationTime / 1000)} min.`);
|
|
||||||
await sleep(creationTime);
|
|
||||||
console.log(`[Enemy Spawn] ${amount} "${npcSettings.id}" has spawned!`);
|
|
||||||
summonEnemy(enemyBatch);
|
|
||||||
|
|
||||||
enemyBatch.hostileLevel++;
|
|
||||||
} else {
|
|
||||||
console.log("[Enemy Spawn] Fail to spawn. Adding 10% more to chances.");
|
|
||||||
enemyBatch.spawnPrecentage += 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turn online and turn offline
|
|
||||||
async function summonEnemy(data) {
|
|
||||||
// If timer exists, do outpost
|
|
||||||
const summonTime = 4; // 4 is debug, normal is 35
|
|
||||||
if (!data.fastSummon) {
|
|
||||||
console.log(`Summoning Ravager... waiting for ${summonTime} seconds.`);
|
|
||||||
client.user.setStatus('online');
|
|
||||||
client.user.setActivity(`Prowling...`);
|
|
||||||
|
|
||||||
// Sets prowling states on the Ravagers
|
|
||||||
for (let i = 0; i < data.enemies.length; i++) {
|
|
||||||
const element = data.enemies[i];
|
|
||||||
element.state = EnemyState.PROWLING;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notification code
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
await sleep(summonTime * 1000);
|
|
||||||
}
|
|
||||||
console.log("Enemy has spawned!");
|
|
||||||
|
|
||||||
// Goes thru all enemies in array
|
|
||||||
for (let i = 0; i < data.enemies.length; i++) {
|
|
||||||
const element = data.enemies[i];
|
|
||||||
const hostileStats = `LVL: ${element.level} | HP: ${element.health} | STR: ${element.strength} | SPD: ${element.speed}`;
|
|
||||||
|
|
||||||
const ravagerMember = client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id);
|
|
||||||
const appearanceEmbed = new Discord.RichEmbed()
|
|
||||||
.setAuthor(ravagerMember.displayName, client.user.avatarURL)
|
|
||||||
.setColor(ravagerMember.displayColor)
|
|
||||||
.setDescription(`${healthbar(element.health, element.health)}\n` + "```" + hostileStats + "```")
|
|
||||||
|
|
||||||
var newMessage = await client.channels.get(data.channel).send(getDialog("onTheProwl"), {embed: appearanceEmbed});
|
|
||||||
await client.user.setStatus('online');
|
|
||||||
await client.user.setActivity(hostileStats);
|
|
||||||
|
|
||||||
for (let i = 0; i < data.enemies.length; i++) {
|
|
||||||
const element = data.enemies[i];
|
|
||||||
element.state = EnemyState.ACTIVE;
|
|
||||||
}
|
|
||||||
enemyTimer(element, data, data.channel, element.fleeTime, newMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Counts down
|
|
||||||
async function enemyTimer(newEnemy, data, channel, fleeTime, newMessage) {
|
|
||||||
function addUserToArray(userID) {
|
|
||||||
attackingUsers.push(userID);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function sendReactions(options) {
|
|
||||||
// Sends reactions
|
|
||||||
for (let i = 0; i < options.length; i++) {
|
|
||||||
const element = options[i];
|
|
||||||
//console.log("[Reaction Options] Emote: " + element + " | newMessage: " + newMessage);
|
|
||||||
await newMessage.react(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Waiting for the next ${fmtMSS(fleeTime / 1000)} min. to check if Ravager has been killed. ${fleeTime}`);
|
|
||||||
|
|
||||||
const ravagerMember = client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id);
|
|
||||||
const interactionEmbed = new Discord.RichEmbed()
|
|
||||||
.setColor(ravagerMember.displayColor)
|
|
||||||
.setTitle("Status")
|
|
||||||
.setDescription("...")
|
|
||||||
|
|
||||||
const sendMessageMinimum = true;
|
|
||||||
var isReadyToFlee = false;
|
|
||||||
var attackingUsers = [];
|
|
||||||
var tempAttackUsers = "";
|
|
||||||
var newChannel = client.channels.get(channel);
|
|
||||||
var interactionMessage = await newChannel.send({embed: interactionEmbed});
|
|
||||||
|
|
||||||
// Possible reaction attacks can go here
|
|
||||||
var options = ['💥', '🇦', '🇧', '🇨']
|
|
||||||
|
|
||||||
// System for no message sending except the minimum
|
|
||||||
if (sendMessageMinimum) {
|
|
||||||
// Collects emotes and reacts upon the reaction
|
|
||||||
const collector = newMessage.createReactionCollector(
|
|
||||||
(reaction, user) => options.includes(reaction.emoji.name) && user.id !== client.user.id);
|
|
||||||
|
|
||||||
sendReactions(options);
|
|
||||||
|
|
||||||
// Collect
|
|
||||||
collector.on("collect", async reaction => {
|
|
||||||
var user = reaction.users.last();
|
|
||||||
|
|
||||||
// Just in case, I managed to bug out Ravager to display its own name.
|
|
||||||
if (user.id === client.user.id) {
|
|
||||||
console.log("Well then. It bypassed the collector filter, we're stopping the Ravager from attacking itself. Would be interesting though!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send damage to server
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
tempAttackUsers += `${user} :crossed_swords: 11 DAM | <:hitback:460969716580745236> MISS (150/150)\n`;
|
|
||||||
addUserToArray(user.id);
|
|
||||||
console.log("Collecting a user! " + user.username)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ends
|
|
||||||
collector.once("end", async collector => {
|
|
||||||
console.log("Ended collector.")
|
|
||||||
flee(newEnemy, data, client.channels.get(channel));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Goes every 4 seconds
|
|
||||||
var emoteRefresh = setInterval(async () => {
|
|
||||||
await newMessage.clearReactions();
|
|
||||||
|
|
||||||
if (isReadyToFlee && newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log("Has fled!");
|
|
||||||
//interactionEmbed.setDescription("👣 The Ravager has fled...")
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
clearInterval(emoteRefresh);
|
|
||||||
collector.stop();
|
|
||||||
} else {
|
|
||||||
console.log("Sending refreshed embed... |" + tempAttackUsers + "|")
|
|
||||||
if (tempAttackUsers === "") tempAttackUsers = "...";
|
|
||||||
interactionEmbed.setDescription(tempAttackUsers);
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
sendReactions(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
tempAttackUsers = "";
|
|
||||||
}, 5 * 1000);
|
|
||||||
|
|
||||||
|
|
||||||
// Waits to see if killed, and if not send a fleeing message
|
|
||||||
await sleep(fleeTime);
|
|
||||||
if (newEnemy.state === EnemyState.ACTIVE) {
|
|
||||||
newChannel.send("**YOU ARE WEAK. THERE IS NO CHALLENGE FOR ME HERE.**\n:bangbang:***ATTEMPTING TO FLEE...***");
|
|
||||||
await sleep(20 * 1000);
|
|
||||||
|
|
||||||
// If still there despawn
|
|
||||||
if (newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log('Hostile is now able to flee, now awaiting for collector to finish.');
|
|
||||||
isReadyToFlee = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Collects emotes and reacts upon the reaction
|
|
||||||
var collector = newMessage.createReactionCollector(
|
|
||||||
(reaction, user) => options.includes(reaction.emoji.name) && user.id !== client.user.id);
|
|
||||||
|
|
||||||
sendReactions(options);
|
|
||||||
|
|
||||||
// Collect
|
|
||||||
collector.on("collect", async reaction => {
|
|
||||||
var user = reaction.users.last();
|
|
||||||
|
|
||||||
// Just in case, I managed to bug out Ravager to display its own name.
|
|
||||||
if (user.id === client.user.id) {
|
|
||||||
console.log("Well then. It bypassed the collector filter, we're stopping the Ravager from attacking itself. Would be interesting though!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send damage to server
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
tempAttackUsers += `${user} :crossed_swords: 11 DAM | <:hitback:460969716580745236> MISS (150/150)\n`;
|
|
||||||
addUserToArray(user.id);
|
|
||||||
console.log("Collecting a user! " + user.username)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ends
|
|
||||||
collector.once("end", async collector => {
|
|
||||||
console.log("Ended collector.")
|
|
||||||
flee(newEnemy, data, client.channels.get(channel));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Goes every 4 seconds
|
|
||||||
var emoteRefresh = setInterval(async () => {
|
|
||||||
await newMessage.clearReactions();
|
|
||||||
|
|
||||||
if (isReadyToFlee && newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log("Has fled!");
|
|
||||||
//interactionEmbed.setDescription("👣 The Ravager has fled...")
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
clearInterval(emoteRefresh);
|
|
||||||
collector.stop();
|
|
||||||
} else {
|
|
||||||
console.log("Sending refreshed embed... |" + tempAttackUsers + "|")
|
|
||||||
if (tempAttackUsers === "") tempAttackUsers = "...";
|
|
||||||
interactionEmbed.setDescription(tempAttackUsers);
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
sendReactions(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
tempAttackUsers = "";
|
|
||||||
}, 5 * 1000);
|
|
||||||
|
|
||||||
|
|
||||||
// Waits to see if killed, and if not send a fleeing message
|
|
||||||
await sleep(fleeTime);
|
|
||||||
if (newEnemy.state === EnemyState.ACTIVE) {
|
|
||||||
newChannel.send("**YOU ARE WEAK. THERE IS NO CHALLENGE FOR ME HERE.**\n:bangbang:***ATTEMPTING TO FLEE...***");
|
|
||||||
await sleep(20 * 1000);
|
|
||||||
|
|
||||||
// If still there despawn
|
|
||||||
if (newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log('Hostile is now able to flee, now awaiting for collector to finish.');
|
|
||||||
isReadyToFlee = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Does flee sequence
|
|
||||||
async function flee(newEnemy, data, newChannel) {
|
|
||||||
newChannel.send("**THE POOR, ILL-EQUIPPED TRAVELERS PUT UP NO FIGHT...**\n:footprints:***RETURNS TO THE WILD. ***");
|
|
||||||
socket.emit('fled', {
|
|
||||||
data: data,
|
|
||||||
ravager: newEnemy
|
|
||||||
});
|
|
||||||
|
|
||||||
if (data.length < 1) {
|
|
||||||
await client.user.setPresence('invisible');
|
|
||||||
client.user.setActivity('Prowling...');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Health bar
|
|
||||||
function healthbar(health, maxHealth) {
|
|
||||||
var heartHealthAmount = 30;
|
|
||||||
var printString = "";
|
|
||||||
var amountMultiple = 0;
|
|
||||||
var timesToLoop = Math.floor(maxHealth / heartHealthAmount);
|
|
||||||
for (var i = 0; i < timesToLoop; i++) {
|
|
||||||
amountMultiple = i * heartHealthAmount;
|
|
||||||
if (amountMultiple < health) {
|
|
||||||
printString += ":heart: ";
|
|
||||||
} else {
|
|
||||||
printString += ":black_heart:";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printString += " (" + health + "/" + maxHealth + ")";
|
|
||||||
return printString;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Async Waiting
|
|
||||||
function sleep(time) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
setTimeout(resolve, time);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets if user has an Overseers rank
|
|
||||||
function isAdmin(userID) {
|
|
||||||
var guild = client.guilds.get(process.env.SANCTUM_ID);
|
|
||||||
return guild.members.get(userID).roles.find(role => role.name === "Overseers");
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/3733227/javascript-seconds-to-minutes-and-seconds
|
|
||||||
function fmtMSS(s){ // accepts seconds as Number or String. Returns m:ss
|
|
||||||
return( s - // take value s and subtract (will try to convert String to Number)
|
|
||||||
( s %= 60 ) // the new value of s, now holding the remainder of s divided by 60
|
|
||||||
// (will also try to convert String to Number)
|
|
||||||
) / 60 + ( // and divide the resulting Number by 60
|
|
||||||
// (can never result in a fractional value = no need for rounding)
|
|
||||||
// to which we concatenate a String (converts the Number to String)
|
|
||||||
// who's reference is chosen by the conditional operator:
|
|
||||||
9 < s // if seconds is larger than 9
|
|
||||||
? ':' // then we don't need to prepend a zero
|
|
||||||
: ':0' // else we do need to prepend a zero
|
|
||||||
) + s ; // and we add Number s to the string (converting it to String as well)
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/6860853/generate-random-string-for-div-id/6860916#6860916
|
|
||||||
function guidGenerator() {
|
|
||||||
var S4 = function() {
|
|
||||||
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
|
|
||||||
};
|
|
||||||
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDialog(dialogTag, data = "", data2 = "") {
|
|
||||||
switch(dialogTag) {
|
|
||||||
case "onTheProwl":
|
|
||||||
var dialogOptions = [
|
|
||||||
'THE AIR SMELLS OF BLOOD.',
|
|
||||||
'LOOKS LIKE MEAT\'S BACK ON THE MENU BOYS.',
|
|
||||||
'FRESH MEAAAATTTT.',
|
|
||||||
'TONIGHT WE DINE ON TRAVELER FLESSHHHH.',
|
|
||||||
'SKULL CRUSHING IS MY FAVORITE SPORT.',
|
|
||||||
'HUNGRY...',
|
|
||||||
'TRAVELERS MAKE GOOD MEEEAAAAT!',
|
|
||||||
'PUNY TRAVELER THINKS THEY CAN FIGHT?!',
|
|
||||||
'HUNT THEM ALL DOWN.',
|
|
||||||
'I HUNGER FOR THE TASTE OF FLESH.'
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
return "***" + dialogOptions[randomNumber] + "***";
|
|
||||||
|
|
||||||
case "ravagerHit":
|
|
||||||
var dialogOptions = [
|
|
||||||
'STAGGERS BACK',
|
|
||||||
'FALLS BACKWARDS',
|
|
||||||
'CHARGES FORWARD CONFUSED',
|
|
||||||
'LOOKS FOR THE SOURCE OF THE HIT',
|
|
||||||
'FALLS FORWARDS',
|
|
||||||
'BLOCKS ITS FACE',
|
|
||||||
'STUMBLES BACKWARDS IN CONFUSION',
|
|
||||||
'LUNGES FORWARD DISTRACTED',
|
|
||||||
'BITES AT IT\'S ATTACKER',
|
|
||||||
'CHECKS IT\'S WOUND'
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
return `***${dialogOptions[randomNumber]}***`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log our bot in (change the token by looking into the .env file)
|
|
||||||
client.login(process.env.RAVAGER_TOKEN);
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
id: "crow",
|
|
||||||
activity: "Cawing in the distance...",
|
|
||||||
type: "PLAYING",
|
|
||||||
token: process.env.CROW_TOKEN,
|
|
||||||
botChannel: process.env.CRYSTAL_SHORES
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "sanctum-deploypackage",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"description": "Universal package for all SANCTUM bots, using pm2.",
|
|
||||||
"main": "",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "echo \"Error: you need to use the bot name as a command.\" && exit 1",
|
|
||||||
"alexis": "pm2 start alexis.js -i max --watch",
|
|
||||||
"graze": "pm2 start graze.js -i max --watch",
|
|
||||||
"librarian": "pm2 start librarian.js -i max --watch",
|
|
||||||
"mainframe": "pm2 start mainframe.js -i max --watch",
|
|
||||||
"mori": "pm2 start mori.js -i max --watch",
|
|
||||||
"mosiah": "pm2 start mosiah.js -i max --watch",
|
|
||||||
"ravager": "pm2 start ravager.js -i max --watch",
|
|
||||||
"rey": "pm2 start rey.js -i max --watch",
|
|
||||||
"troll": "pm2 start troll.js -i max --watch"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2",
|
|
||||||
"dotenv": "^6.0.0",
|
|
||||||
"express": "^4.16.3",
|
|
||||||
"node-cron": "^1.2.1",
|
|
||||||
"socket.io": "^2.1.1",
|
|
||||||
"socket.io-request": "^0.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,571 +0,0 @@
|
|||||||
// .env Variables
|
|
||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
// Node Modules
|
|
||||||
const Discord = require('discord.js');
|
|
||||||
const client = new Discord.Client();
|
|
||||||
const cron = require('node-cron');
|
|
||||||
const io = require('socket.io-client');
|
|
||||||
|
|
||||||
// Make connection
|
|
||||||
var socket = io.connect('http://localhost:80');
|
|
||||||
|
|
||||||
// Bot Modules
|
|
||||||
const npcSettings = require('./npcSettings')
|
|
||||||
const dataRequest = require('../modules/dataRequest');
|
|
||||||
const calcRandom = require('../modules/calcRandom');
|
|
||||||
|
|
||||||
// State Machine
|
|
||||||
var EnemyState = {
|
|
||||||
INACTIVE: 0,
|
|
||||||
PROWLING: 1,
|
|
||||||
ACTIVE: 2,
|
|
||||||
UNCONSCIOUS: 3
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enemy lists
|
|
||||||
class EnemyBatchInstance {
|
|
||||||
constructor(channel) {
|
|
||||||
this.state = EnemyState.INACTIVE;
|
|
||||||
this.enemies = []; // Array of `new Enemy()`s
|
|
||||||
this.channel = channel; // Channel of spawning
|
|
||||||
this.spawnPrecentage = 100;
|
|
||||||
this.hostileLevel = 1;
|
|
||||||
this.fastSummon = false; // Show prowling
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enemy instance
|
|
||||||
class Enemy {
|
|
||||||
constructor(type) {
|
|
||||||
this.state = EnemyState.INACTIVE;
|
|
||||||
this.type = type;
|
|
||||||
this.level = 1;
|
|
||||||
this.health = 420;
|
|
||||||
this.speed = 21;
|
|
||||||
this.strength = 33;
|
|
||||||
this.stash = 0;
|
|
||||||
this.fleeTime = undefined;
|
|
||||||
this.guid = undefined;
|
|
||||||
this.deletePrevMessage = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates flee time by randomization
|
|
||||||
get randomFleeTime() {
|
|
||||||
var randomFleeTime;
|
|
||||||
randomFleeTime = calcRandom.random(3 * 60 * 1000, 6 * 60 * 1000);
|
|
||||||
randomFleeTime -= (randomFleeTime % 1000);
|
|
||||||
return randomFleeTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var enemyBatchCollection = [];
|
|
||||||
|
|
||||||
// Spawning patterns
|
|
||||||
var spawnPatterns = {
|
|
||||||
"types": ['default', 'randomBatch2'],
|
|
||||||
"default": {
|
|
||||||
"ravager": {
|
|
||||||
"amount": 1
|
|
||||||
},
|
|
||||||
"type": "incrememt"
|
|
||||||
},
|
|
||||||
"randomBatch2": {
|
|
||||||
"amount": 2,
|
|
||||||
"type": "incrememt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var socketReady = false;
|
|
||||||
socket.on('spawn', (data) => {
|
|
||||||
if (!socketReady) return;
|
|
||||||
|
|
||||||
console.log(JSON.stringify(data, null, 4));
|
|
||||||
console.log(`Summoning enemies...`);
|
|
||||||
|
|
||||||
// Spawns
|
|
||||||
summonEnemy(data);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// The ready event is vital, it means that your bot will only start reacting to information
|
|
||||||
// from Discord _after_ ready is emitted
|
|
||||||
client.on('ready', async () => {
|
|
||||||
socketReady = true;
|
|
||||||
|
|
||||||
// Generates invite link
|
|
||||||
try {
|
|
||||||
let link = await client.generateInvite(["ADMINISTRATOR"]);
|
|
||||||
console.log("Invite Link: " + link);
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can set status to 'online', 'invisible', 'away', or 'dnd' (do not disturb)
|
|
||||||
client.user.setStatus('invisible');
|
|
||||||
// Sets your "Playing"
|
|
||||||
if (npcSettings.activity) {
|
|
||||||
client.user.setActivity(npcSettings.activity, { type: npcSettings.type })
|
|
||||||
.then(presence => console.log(`Activity set to ${presence.game ? presence.game.name : 'none'}`))
|
|
||||||
.catch(console.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Connected! \
|
|
||||||
\nLogged in as: ${client.user.username} - (${client.user.id})`);
|
|
||||||
|
|
||||||
// Corrects Ravager username
|
|
||||||
if (client.user.username == "Raveger") {
|
|
||||||
const newName = "Ravager";
|
|
||||||
console.log("Username is Raveger! Typos are NOT(?) cannon, so better change stuff.\nAttempting rename to " + newName + "...");
|
|
||||||
|
|
||||||
// Set username
|
|
||||||
client.user.setUsername(newName)
|
|
||||||
.then(user => console.log(`Success! New username is now ${user.username}.`))
|
|
||||||
.catch(console.error);
|
|
||||||
|
|
||||||
// Changes nickname
|
|
||||||
client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id).setNickname("");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create an event listener for messages
|
|
||||||
client.on('message', async message => {
|
|
||||||
// Ignores ALL bot messages
|
|
||||||
if (message.author.bot) return;
|
|
||||||
// Message has to be in Outskirts (should be edited later)
|
|
||||||
if (!(message.channel.id === process.env.DEADLANDS_CHANNEL_ID
|
|
||||||
|| message.channel.id === process.env.TEST_CHANNEL_ID)) return;
|
|
||||||
// Has to be (prefix)command
|
|
||||||
if (message.content.indexOf(process.env.PREFIX) !== 0) return;
|
|
||||||
|
|
||||||
// "This is the best way to define args. Trust me."
|
|
||||||
// - Some tutorial dude on the internet
|
|
||||||
const args = message.content.slice(process.env.PREFIX.length).trim().split(/ +/g);
|
|
||||||
const command = args.shift().toLowerCase();
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case "ping":
|
|
||||||
if (isAdmin(message.author.id))
|
|
||||||
message.reply("***...MRGRGRGR!***");
|
|
||||||
break;
|
|
||||||
case npcSettings.id:
|
|
||||||
if (args[0].toLowerCase() === "summon" && isAdmin(message.author.id)) {
|
|
||||||
generateEnemy(process.env.DEADLANDS_CHANNEL_ID);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', console.error);
|
|
||||||
|
|
||||||
cron.schedule('*/10 * * * *', function() {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
async function generateEnemy(channelID) {
|
|
||||||
console.log("Generating enemy...")
|
|
||||||
|
|
||||||
// Gets an enemy batch instance, or creates if non-existant
|
|
||||||
var index = enemyBatchCollection.findIndex(data => data.channel === channelID);
|
|
||||||
var enemyBatch;
|
|
||||||
console.log(index <= -1)
|
|
||||||
if (index <= -1) {
|
|
||||||
enemyBatch = new EnemyBatchInstance(channelID);
|
|
||||||
} else {
|
|
||||||
enemyBatch = enemyBatchCollection[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a spawn pattern
|
|
||||||
var randomSpawnPattern = spawnPatterns.types[calcRandom.randomExc(0, spawnPatterns.types.length)];
|
|
||||||
var newSpawnPattern = spawnPatterns[randomSpawnPattern];
|
|
||||||
newSpawnPattern = spawnPatterns["default"]; // Overruled!
|
|
||||||
|
|
||||||
// Creates a bunch of new enemies
|
|
||||||
var amount = newSpawnPattern[npcSettings.id].amount;
|
|
||||||
var newEnemies = [];
|
|
||||||
for (let i = 0; i < amount; i++) {
|
|
||||||
var enemy = new Enemy(npcSettings.id);
|
|
||||||
var elevel = enemyBatch.hostileLevel;
|
|
||||||
|
|
||||||
// Replication of newHostile in sendData.php
|
|
||||||
const healthBase = 50; const strengthBase = 3; const speedBase = 3; const stashBase = 3;
|
|
||||||
|
|
||||||
const healthMin = (healthBase * elevel) / 2;
|
|
||||||
const healthMax = healthBase * elevel;
|
|
||||||
|
|
||||||
const strengthMin = (strengthBase * elevel) / 2;
|
|
||||||
const strengthMax = strengthBase * elevel;
|
|
||||||
|
|
||||||
const speedMin = (speedBase * elevel) / 2;
|
|
||||||
const speedMax = speedBase * elevel;
|
|
||||||
|
|
||||||
const stashMin = (stashBase * elevel) / 2;
|
|
||||||
const stashMax = stashBase * elevel;
|
|
||||||
|
|
||||||
const health = Math.floor(calcRandom.randomExc(healthMin, healthMax));
|
|
||||||
const strength = Math.floor(calcRandom.randomExc(strengthMin, strengthMax));
|
|
||||||
const speed = Math.floor(calcRandom.randomExc(speedMin, speedMax));
|
|
||||||
const stash = Math.floor(calcRandom.randomExc(stashMin, stashMax));
|
|
||||||
|
|
||||||
enemy.level = elevel;
|
|
||||||
enemy.health = health;
|
|
||||||
enemy.strength = strength;
|
|
||||||
enemy.speed = speed;
|
|
||||||
enemy.stash = stash;
|
|
||||||
enemy.state = EnemyState.PROWLING;
|
|
||||||
enemy.fleeTime = enemy.randomFleeTime;
|
|
||||||
enemy.guid = guidGenerator();
|
|
||||||
|
|
||||||
// Logs stats
|
|
||||||
console.log(`\n[===== | Enemy Stats | =====]`);
|
|
||||||
console.log(`HEALTH: ${health} > ${healthMin} - ${healthMax}`);
|
|
||||||
console.log(`STRENGTH: ${strength} > ${strengthMin} - ${strengthMax}`);
|
|
||||||
console.log(`SPEED: ${speed} > ${speedMin} - ${speedMax}`);
|
|
||||||
console.log(`STASH: ${stash} > ${stashMin} - ${stashMax}`);
|
|
||||||
console.log(`[===========================]\n`);
|
|
||||||
newEnemies.push(enemy);
|
|
||||||
}
|
|
||||||
enemyBatch.enemies = newEnemies;
|
|
||||||
enemyBatch.hostileLevel++;
|
|
||||||
|
|
||||||
console.log(JSON.stringify(newEnemies, null, 2));
|
|
||||||
|
|
||||||
if (calcRandom.gamble(enemyBatch.spawnPrecentage)) {
|
|
||||||
enemyBatch.spawnPrecentage = 50;
|
|
||||||
|
|
||||||
// Creation of Ravager timer
|
|
||||||
var creationTime = calcRandom.random(35000, 540000);
|
|
||||||
creationTime = 3 * 1000; // shortcuts
|
|
||||||
|
|
||||||
console.log(`[Enemy Spawn] ${amount} "${npcSettings.id}" will be created in ${fmtMSS(creationTime / 1000)} min.`);
|
|
||||||
await sleep(creationTime);
|
|
||||||
console.log(`[Enemy Spawn] ${amount} "${npcSettings.id}" has spawned!`);
|
|
||||||
summonEnemy(enemyBatch);
|
|
||||||
|
|
||||||
enemyBatch.hostileLevel++;
|
|
||||||
} else {
|
|
||||||
console.log("[Enemy Spawn] Fail to spawn. Adding 10% more to chances.");
|
|
||||||
enemyBatch.spawnPrecentage += 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turn online and turn offline
|
|
||||||
async function summonEnemy(data) {
|
|
||||||
// If timer exists, do outpost
|
|
||||||
const summonTime = 4; // 4 is debug, normal is 35
|
|
||||||
if (!data.fastSummon) {
|
|
||||||
console.log(`Summoning Ravager... waiting for ${summonTime} seconds.`);
|
|
||||||
client.user.setStatus('online');
|
|
||||||
client.user.setActivity(`Prowling...`);
|
|
||||||
|
|
||||||
// Sets prowling states on the Ravagers
|
|
||||||
for (let i = 0; i < data.enemies.length; i++) {
|
|
||||||
const element = data.enemies[i];
|
|
||||||
element.state = EnemyState.PROWLING;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notification code
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
await sleep(summonTime * 1000);
|
|
||||||
}
|
|
||||||
console.log("Enemy has spawned!");
|
|
||||||
|
|
||||||
// Goes thru all enemies in array
|
|
||||||
for (let i = 0; i < data.enemies.length; i++) {
|
|
||||||
const element = data.enemies[i];
|
|
||||||
const hostileStats = `LVL: ${element.level} | HP: ${element.health} | STR: ${element.strength} | SPD: ${element.speed}`;
|
|
||||||
|
|
||||||
const ravagerMember = client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id);
|
|
||||||
const appearanceEmbed = new Discord.RichEmbed()
|
|
||||||
.setAuthor(ravagerMember.displayName, client.user.avatarURL)
|
|
||||||
.setColor(ravagerMember.displayColor)
|
|
||||||
.setDescription(`${healthbar(element.health, element.health)}\n` + "```" + hostileStats + "```")
|
|
||||||
|
|
||||||
var newMessage = await client.channels.get(data.channel).send(getDialog("onTheProwl"), {embed: appearanceEmbed});
|
|
||||||
await client.user.setStatus('online');
|
|
||||||
await client.user.setActivity(hostileStats);
|
|
||||||
|
|
||||||
for (let i = 0; i < data.enemies.length; i++) {
|
|
||||||
const element = data.enemies[i];
|
|
||||||
element.state = EnemyState.ACTIVE;
|
|
||||||
}
|
|
||||||
enemyTimer(element, data, data.channel, element.fleeTime, newMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Counts down
|
|
||||||
async function enemyTimer(newEnemy, data, channel, fleeTime, newMessage) {
|
|
||||||
function addUserToArray(userID) {
|
|
||||||
attackingUsers.push(userID);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function sendReactions(options) {
|
|
||||||
// Sends reactions
|
|
||||||
for (let i = 0; i < options.length; i++) {
|
|
||||||
const element = options[i];
|
|
||||||
//console.log("[Reaction Options] Emote: " + element + " | newMessage: " + newMessage);
|
|
||||||
await newMessage.react(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Waiting for the next ${fmtMSS(fleeTime / 1000)} min. to check if Ravager has been killed. ${fleeTime}`);
|
|
||||||
|
|
||||||
const ravagerMember = client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id);
|
|
||||||
const interactionEmbed = new Discord.RichEmbed()
|
|
||||||
.setColor(ravagerMember.displayColor)
|
|
||||||
.setTitle("Status")
|
|
||||||
.setDescription("...")
|
|
||||||
|
|
||||||
const sendMessageMinimum = true;
|
|
||||||
var isReadyToFlee = false;
|
|
||||||
var attackingUsers = [];
|
|
||||||
var tempAttackUsers = "";
|
|
||||||
var newChannel = client.channels.get(channel);
|
|
||||||
var interactionMessage = await newChannel.send({embed: interactionEmbed});
|
|
||||||
|
|
||||||
// Possible reaction attacks can go here
|
|
||||||
var options = ['💥', '🇦', '🇧', '🇨']
|
|
||||||
|
|
||||||
// System for no message sending except the minimum
|
|
||||||
if (sendMessageMinimum) {
|
|
||||||
// Collects emotes and reacts upon the reaction
|
|
||||||
const collector = newMessage.createReactionCollector(
|
|
||||||
(reaction, user) => options.includes(reaction.emoji.name) && user.id !== client.user.id);
|
|
||||||
|
|
||||||
sendReactions(options);
|
|
||||||
|
|
||||||
// Collect
|
|
||||||
collector.on("collect", async reaction => {
|
|
||||||
var user = reaction.users.last();
|
|
||||||
|
|
||||||
// Just in case, I managed to bug out Ravager to display its own name.
|
|
||||||
if (user.id === client.user.id) {
|
|
||||||
console.log("Well then. It bypassed the collector filter, we're stopping the Ravager from attacking itself. Would be interesting though!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send damage to server
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
tempAttackUsers += `${user} :crossed_swords: 11 DAM | <:hitback:460969716580745236> MISS (150/150)\n`;
|
|
||||||
addUserToArray(user.id);
|
|
||||||
console.log("Collecting a user! " + user.username)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ends
|
|
||||||
collector.once("end", async collector => {
|
|
||||||
console.log("Ended collector.")
|
|
||||||
flee(newEnemy, data, client.channels.get(channel));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Goes every 4 seconds
|
|
||||||
var emoteRefresh = setInterval(async () => {
|
|
||||||
await newMessage.clearReactions();
|
|
||||||
|
|
||||||
if (isReadyToFlee && newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log("Has fled!");
|
|
||||||
//interactionEmbed.setDescription("👣 The Ravager has fled...")
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
clearInterval(emoteRefresh);
|
|
||||||
collector.stop();
|
|
||||||
} else {
|
|
||||||
console.log("Sending refreshed embed... |" + tempAttackUsers + "|")
|
|
||||||
if (tempAttackUsers === "") tempAttackUsers = "...";
|
|
||||||
interactionEmbed.setDescription(tempAttackUsers);
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
sendReactions(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
tempAttackUsers = "";
|
|
||||||
}, 5 * 1000);
|
|
||||||
|
|
||||||
|
|
||||||
// Waits to see if killed, and if not send a fleeing message
|
|
||||||
await sleep(fleeTime);
|
|
||||||
if (newEnemy.state === EnemyState.ACTIVE) {
|
|
||||||
newChannel.send("**YOU ARE WEAK. THERE IS NO CHALLENGE FOR ME HERE.**\n:bangbang:***ATTEMPTING TO FLEE...***");
|
|
||||||
await sleep(20 * 1000);
|
|
||||||
|
|
||||||
// If still there despawn
|
|
||||||
if (newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log('Hostile is now able to flee, now awaiting for collector to finish.');
|
|
||||||
isReadyToFlee = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Collects emotes and reacts upon the reaction
|
|
||||||
var collector = newMessage.createReactionCollector(
|
|
||||||
(reaction, user) => options.includes(reaction.emoji.name) && user.id !== client.user.id);
|
|
||||||
|
|
||||||
sendReactions(options);
|
|
||||||
|
|
||||||
// Collect
|
|
||||||
collector.on("collect", async reaction => {
|
|
||||||
var user = reaction.users.last();
|
|
||||||
|
|
||||||
// Just in case, I managed to bug out Ravager to display its own name.
|
|
||||||
if (user.id === client.user.id) {
|
|
||||||
console.log("Well then. It bypassed the collector filter, we're stopping the Ravager from attacking itself. Would be interesting though!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send damage to server
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
tempAttackUsers += `${user} :crossed_swords: 11 DAM | <:hitback:460969716580745236> MISS (150/150)\n`;
|
|
||||||
addUserToArray(user.id);
|
|
||||||
console.log("Collecting a user! " + user.username)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ends
|
|
||||||
collector.once("end", async collector => {
|
|
||||||
console.log("Ended collector.")
|
|
||||||
flee(newEnemy, data, client.channels.get(channel));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Goes every 4 seconds
|
|
||||||
var emoteRefresh = setInterval(async () => {
|
|
||||||
await newMessage.clearReactions();
|
|
||||||
|
|
||||||
if (isReadyToFlee && newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log("Has fled!");
|
|
||||||
//interactionEmbed.setDescription("👣 The Ravager has fled...")
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
clearInterval(emoteRefresh);
|
|
||||||
collector.stop();
|
|
||||||
} else {
|
|
||||||
console.log("Sending refreshed embed... |" + tempAttackUsers + "|")
|
|
||||||
if (tempAttackUsers === "") tempAttackUsers = "...";
|
|
||||||
interactionEmbed.setDescription(tempAttackUsers);
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
sendReactions(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
tempAttackUsers = "";
|
|
||||||
}, 5 * 1000);
|
|
||||||
|
|
||||||
|
|
||||||
// Waits to see if killed, and if not send a fleeing message
|
|
||||||
await sleep(fleeTime);
|
|
||||||
if (newEnemy.state === EnemyState.ACTIVE) {
|
|
||||||
newChannel.send("**YOU ARE WEAK. THERE IS NO CHALLENGE FOR ME HERE.**\n:bangbang:***ATTEMPTING TO FLEE...***");
|
|
||||||
await sleep(20 * 1000);
|
|
||||||
|
|
||||||
// If still there despawn
|
|
||||||
if (newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log('Hostile is now able to flee, now awaiting for collector to finish.');
|
|
||||||
isReadyToFlee = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Does flee sequence
|
|
||||||
async function flee(newEnemy, data, newChannel) {
|
|
||||||
newChannel.send("**THE POOR, ILL-EQUIPPED TRAVELERS PUT UP NO FIGHT...**\n:footprints:***RETURNS TO THE WILD. ***");
|
|
||||||
socket.emit('fled', {
|
|
||||||
data: data,
|
|
||||||
ravager: newEnemy
|
|
||||||
});
|
|
||||||
|
|
||||||
if (data.length < 1) {
|
|
||||||
await client.user.setPresence('invisible');
|
|
||||||
client.user.setActivity('Prowling...');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Health bar
|
|
||||||
function healthbar(health, maxHealth) {
|
|
||||||
var heartHealthAmount = 30;
|
|
||||||
var printString = "";
|
|
||||||
var amountMultiple = 0;
|
|
||||||
var timesToLoop = Math.floor(maxHealth / heartHealthAmount);
|
|
||||||
for (var i = 0; i < timesToLoop; i++) {
|
|
||||||
amountMultiple = i * heartHealthAmount;
|
|
||||||
if (amountMultiple < health) {
|
|
||||||
printString += ":heart: ";
|
|
||||||
} else {
|
|
||||||
printString += ":black_heart:";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printString += " (" + health + "/" + maxHealth + ")";
|
|
||||||
return printString;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Async Waiting
|
|
||||||
function sleep(time) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
setTimeout(resolve, time);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets if user has an Overseers rank
|
|
||||||
function isAdmin(userID) {
|
|
||||||
var guild = client.guilds.get(process.env.SANCTUM_ID);
|
|
||||||
return guild.members.get(userID).roles.find(role => role.name === "Overseers");
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/3733227/javascript-seconds-to-minutes-and-seconds
|
|
||||||
function fmtMSS(s){ // accepts seconds as Number or String. Returns m:ss
|
|
||||||
return( s - // take value s and subtract (will try to convert String to Number)
|
|
||||||
( s %= 60 ) // the new value of s, now holding the remainder of s divided by 60
|
|
||||||
// (will also try to convert String to Number)
|
|
||||||
) / 60 + ( // and divide the resulting Number by 60
|
|
||||||
// (can never result in a fractional value = no need for rounding)
|
|
||||||
// to which we concatenate a String (converts the Number to String)
|
|
||||||
// who's reference is chosen by the conditional operator:
|
|
||||||
9 < s // if seconds is larger than 9
|
|
||||||
? ':' // then we don't need to prepend a zero
|
|
||||||
: ':0' // else we do need to prepend a zero
|
|
||||||
) + s ; // and we add Number s to the string (converting it to String as well)
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/6860853/generate-random-string-for-div-id/6860916#6860916
|
|
||||||
function guidGenerator() {
|
|
||||||
var S4 = function() {
|
|
||||||
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
|
|
||||||
};
|
|
||||||
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDialog(dialogTag, data = "", data2 = "") {
|
|
||||||
switch(dialogTag) {
|
|
||||||
case "onTheProwl":
|
|
||||||
var dialogOptions = [
|
|
||||||
'THE AIR SMELLS OF BLOOD.',
|
|
||||||
'LOOKS LIKE MEAT\'S BACK ON THE MENU BOYS.',
|
|
||||||
'FRESH MEAAAATTTT.',
|
|
||||||
'TONIGHT WE DINE ON TRAVELER FLESSHHHH.',
|
|
||||||
'SKULL CRUSHING IS MY FAVORITE SPORT.',
|
|
||||||
'HUNGRY...',
|
|
||||||
'TRAVELERS MAKE GOOD MEEEAAAAT!',
|
|
||||||
'PUNY TRAVELER THINKS THEY CAN FIGHT?!',
|
|
||||||
'HUNT THEM ALL DOWN.',
|
|
||||||
'I HUNGER FOR THE TASTE OF FLESH.'
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
return "***" + dialogOptions[randomNumber] + "***";
|
|
||||||
|
|
||||||
case "ravagerHit":
|
|
||||||
var dialogOptions = [
|
|
||||||
'STAGGERS BACK',
|
|
||||||
'FALLS BACKWARDS',
|
|
||||||
'CHARGES FORWARD CONFUSED',
|
|
||||||
'LOOKS FOR THE SOURCE OF THE HIT',
|
|
||||||
'FALLS FORWARDS',
|
|
||||||
'BLOCKS ITS FACE',
|
|
||||||
'STUMBLES BACKWARDS IN CONFUSION',
|
|
||||||
'LUNGES FORWARD DISTRACTED',
|
|
||||||
'BITES AT IT\'S ATTACKER',
|
|
||||||
'CHECKS IT\'S WOUND'
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
return `***${dialogOptions[randomNumber]}***`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log our bot in (change the token by looking into the .env file)
|
|
||||||
client.login(process.env.RAVAGER_TOKEN);
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: "ravager",
|
|
||||||
activity: "Prowling...",
|
|
||||||
type: "PLAYING",
|
|
||||||
token: process.env.RAVAGER_TOKEN,
|
|
||||||
botChannel: process.env.DEADLANDS_CHANNEL_ID
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "sanctum-deploypackage",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"description": "Universal package for all SANCTUM bots, using pm2.",
|
|
||||||
"main": "",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "echo \"Error: you need to use the bot name as a command.\" && exit 1",
|
|
||||||
"alexis": "pm2 start alexis.js -i max --watch",
|
|
||||||
"graze": "pm2 start graze.js -i max --watch",
|
|
||||||
"librarian": "pm2 start librarian.js -i max --watch",
|
|
||||||
"mainframe": "pm2 start mainframe.js -i max --watch",
|
|
||||||
"mori": "pm2 start mori.js -i max --watch",
|
|
||||||
"mosiah": "pm2 start mosiah.js -i max --watch",
|
|
||||||
"ravager": "pm2 start ravager.js -i max --watch",
|
|
||||||
"rey": "pm2 start rey.js -i max --watch",
|
|
||||||
"troll": "pm2 start troll.js -i max --watch"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2",
|
|
||||||
"dotenv": "^6.0.0",
|
|
||||||
"express": "^4.16.3",
|
|
||||||
"node-cron": "^1.2.1",
|
|
||||||
"socket.io": "^2.1.1",
|
|
||||||
"socket.io-request": "^0.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,571 +0,0 @@
|
|||||||
// .env Variables
|
|
||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
// Node Modules
|
|
||||||
const Discord = require('discord.js');
|
|
||||||
const client = new Discord.Client();
|
|
||||||
const cron = require('node-cron');
|
|
||||||
const io = require('socket.io-client');
|
|
||||||
|
|
||||||
// Make connection
|
|
||||||
var socket = io.connect('http://localhost:80');
|
|
||||||
|
|
||||||
// Bot Modules
|
|
||||||
const npcSettings = require('./npcSettings')
|
|
||||||
const dataRequest = require('../modules/dataRequest');
|
|
||||||
const calcRandom = require('../modules/calcRandom');
|
|
||||||
|
|
||||||
// State Machine
|
|
||||||
var EnemyState = {
|
|
||||||
INACTIVE: 0,
|
|
||||||
PROWLING: 1,
|
|
||||||
ACTIVE: 2,
|
|
||||||
UNCONSCIOUS: 3
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enemy lists
|
|
||||||
class EnemyBatchInstance {
|
|
||||||
constructor(channel) {
|
|
||||||
this.state = EnemyState.INACTIVE;
|
|
||||||
this.enemies = []; // Array of `new Enemy()`s
|
|
||||||
this.channel = channel; // Channel of spawning
|
|
||||||
this.spawnPrecentage = 100;
|
|
||||||
this.hostileLevel = 1;
|
|
||||||
this.fastSummon = false; // Show prowling
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enemy instance
|
|
||||||
class Enemy {
|
|
||||||
constructor(type) {
|
|
||||||
this.state = EnemyState.INACTIVE;
|
|
||||||
this.type = type;
|
|
||||||
this.level = 1;
|
|
||||||
this.health = 420;
|
|
||||||
this.speed = 21;
|
|
||||||
this.strength = 33;
|
|
||||||
this.stash = 0;
|
|
||||||
this.fleeTime = undefined;
|
|
||||||
this.guid = undefined;
|
|
||||||
this.deletePrevMessage = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates flee time by randomization
|
|
||||||
get randomFleeTime() {
|
|
||||||
var randomFleeTime;
|
|
||||||
randomFleeTime = calcRandom.random(3 * 60 * 1000, 6 * 60 * 1000);
|
|
||||||
randomFleeTime -= (randomFleeTime % 1000);
|
|
||||||
return randomFleeTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var enemyBatchCollection = [];
|
|
||||||
|
|
||||||
// Spawning patterns
|
|
||||||
var spawnPatterns = {
|
|
||||||
"types": ['default', 'randomBatch2'],
|
|
||||||
"default": {
|
|
||||||
"ravager": {
|
|
||||||
"amount": 1
|
|
||||||
},
|
|
||||||
"type": "incrememt"
|
|
||||||
},
|
|
||||||
"randomBatch2": {
|
|
||||||
"amount": 2,
|
|
||||||
"type": "incrememt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var socketReady = false;
|
|
||||||
socket.on('spawn', (data) => {
|
|
||||||
if (!socketReady) return;
|
|
||||||
|
|
||||||
console.log(JSON.stringify(data, null, 4));
|
|
||||||
console.log(`Summoning enemies...`);
|
|
||||||
|
|
||||||
// Spawns
|
|
||||||
summonEnemy(data);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// The ready event is vital, it means that your bot will only start reacting to information
|
|
||||||
// from Discord _after_ ready is emitted
|
|
||||||
client.on('ready', async () => {
|
|
||||||
socketReady = true;
|
|
||||||
|
|
||||||
// Generates invite link
|
|
||||||
try {
|
|
||||||
let link = await client.generateInvite(["ADMINISTRATOR"]);
|
|
||||||
console.log("Invite Link: " + link);
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can set status to 'online', 'invisible', 'away', or 'dnd' (do not disturb)
|
|
||||||
client.user.setStatus('invisible');
|
|
||||||
// Sets your "Playing"
|
|
||||||
if (npcSettings.activity) {
|
|
||||||
client.user.setActivity(npcSettings.activity, { type: npcSettings.type })
|
|
||||||
.then(presence => console.log(`Activity set to ${presence.game ? presence.game.name : 'none'}`))
|
|
||||||
.catch(console.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Connected! \
|
|
||||||
\nLogged in as: ${client.user.username} - (${client.user.id})`);
|
|
||||||
|
|
||||||
// Corrects Ravager username
|
|
||||||
if (client.user.username == "Raveger") {
|
|
||||||
const newName = "Ravager";
|
|
||||||
console.log("Username is Raveger! Typos are NOT(?) cannon, so better change stuff.\nAttempting rename to " + newName + "...");
|
|
||||||
|
|
||||||
// Set username
|
|
||||||
client.user.setUsername(newName)
|
|
||||||
.then(user => console.log(`Success! New username is now ${user.username}.`))
|
|
||||||
.catch(console.error);
|
|
||||||
|
|
||||||
// Changes nickname
|
|
||||||
client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id).setNickname("");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create an event listener for messages
|
|
||||||
client.on('message', async message => {
|
|
||||||
// Ignores ALL bot messages
|
|
||||||
if (message.author.bot) return;
|
|
||||||
// Message has to be in Outskirts (should be edited later)
|
|
||||||
if (!(message.channel.id === process.env.DEADLANDS_CHANNEL_ID
|
|
||||||
|| message.channel.id === process.env.TEST_CHANNEL_ID)) return;
|
|
||||||
// Has to be (prefix)command
|
|
||||||
if (message.content.indexOf(process.env.PREFIX) !== 0) return;
|
|
||||||
|
|
||||||
// "This is the best way to define args. Trust me."
|
|
||||||
// - Some tutorial dude on the internet
|
|
||||||
const args = message.content.slice(process.env.PREFIX.length).trim().split(/ +/g);
|
|
||||||
const command = args.shift().toLowerCase();
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case "ping":
|
|
||||||
if (isAdmin(message.author.id))
|
|
||||||
message.reply("***...MRGRGRGR!***");
|
|
||||||
break;
|
|
||||||
case npcSettings.id:
|
|
||||||
if (args[0].toLowerCase() === "summon" && isAdmin(message.author.id)) {
|
|
||||||
generateEnemy(process.env.DEADLANDS_CHANNEL_ID);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', console.error);
|
|
||||||
|
|
||||||
cron.schedule('*/10 * * * *', function() {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
async function generateEnemy(channelID) {
|
|
||||||
console.log("Generating enemy...")
|
|
||||||
|
|
||||||
// Gets an enemy batch instance, or creates if non-existant
|
|
||||||
var index = enemyBatchCollection.findIndex(data => data.channel === channelID);
|
|
||||||
var enemyBatch;
|
|
||||||
console.log(index <= -1)
|
|
||||||
if (index <= -1) {
|
|
||||||
enemyBatch = new EnemyBatchInstance(channelID);
|
|
||||||
} else {
|
|
||||||
enemyBatch = enemyBatchCollection[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a spawn pattern
|
|
||||||
var randomSpawnPattern = spawnPatterns.types[calcRandom.randomExc(0, spawnPatterns.types.length)];
|
|
||||||
var newSpawnPattern = spawnPatterns[randomSpawnPattern];
|
|
||||||
newSpawnPattern = spawnPatterns["default"]; // Overruled!
|
|
||||||
|
|
||||||
// Creates a bunch of new enemies
|
|
||||||
var amount = newSpawnPattern[npcSettings.id].amount;
|
|
||||||
var newEnemies = [];
|
|
||||||
for (let i = 0; i < amount; i++) {
|
|
||||||
var enemy = new Enemy(npcSettings.id);
|
|
||||||
var elevel = enemyBatch.hostileLevel;
|
|
||||||
|
|
||||||
// Replication of newHostile in sendData.php
|
|
||||||
const healthBase = 50; const strengthBase = 3; const speedBase = 3; const stashBase = 3;
|
|
||||||
|
|
||||||
const healthMin = (healthBase * elevel) / 2;
|
|
||||||
const healthMax = healthBase * elevel;
|
|
||||||
|
|
||||||
const strengthMin = (strengthBase * elevel) / 2;
|
|
||||||
const strengthMax = strengthBase * elevel;
|
|
||||||
|
|
||||||
const speedMin = (speedBase * elevel) / 2;
|
|
||||||
const speedMax = speedBase * elevel;
|
|
||||||
|
|
||||||
const stashMin = (stashBase * elevel) / 2;
|
|
||||||
const stashMax = stashBase * elevel;
|
|
||||||
|
|
||||||
const health = Math.floor(calcRandom.randomExc(healthMin, healthMax));
|
|
||||||
const strength = Math.floor(calcRandom.randomExc(strengthMin, strengthMax));
|
|
||||||
const speed = Math.floor(calcRandom.randomExc(speedMin, speedMax));
|
|
||||||
const stash = Math.floor(calcRandom.randomExc(stashMin, stashMax));
|
|
||||||
|
|
||||||
enemy.level = elevel;
|
|
||||||
enemy.health = health;
|
|
||||||
enemy.strength = strength;
|
|
||||||
enemy.speed = speed;
|
|
||||||
enemy.stash = stash;
|
|
||||||
enemy.state = EnemyState.PROWLING;
|
|
||||||
enemy.fleeTime = enemy.randomFleeTime;
|
|
||||||
enemy.guid = guidGenerator();
|
|
||||||
|
|
||||||
// Logs stats
|
|
||||||
console.log(`\n[===== | Enemy Stats | =====]`);
|
|
||||||
console.log(`HEALTH: ${health} > ${healthMin} - ${healthMax}`);
|
|
||||||
console.log(`STRENGTH: ${strength} > ${strengthMin} - ${strengthMax}`);
|
|
||||||
console.log(`SPEED: ${speed} > ${speedMin} - ${speedMax}`);
|
|
||||||
console.log(`STASH: ${stash} > ${stashMin} - ${stashMax}`);
|
|
||||||
console.log(`[===========================]\n`);
|
|
||||||
newEnemies.push(enemy);
|
|
||||||
}
|
|
||||||
enemyBatch.enemies = newEnemies;
|
|
||||||
enemyBatch.hostileLevel++;
|
|
||||||
|
|
||||||
console.log(JSON.stringify(newEnemies, null, 2));
|
|
||||||
|
|
||||||
if (calcRandom.gamble(enemyBatch.spawnPrecentage)) {
|
|
||||||
enemyBatch.spawnPrecentage = 50;
|
|
||||||
|
|
||||||
// Creation of Ravager timer
|
|
||||||
var creationTime = calcRandom.random(35000, 540000);
|
|
||||||
creationTime = 3 * 1000; // shortcuts
|
|
||||||
|
|
||||||
console.log(`[Enemy Spawn] ${amount} "${npcSettings.id}" will be created in ${fmtMSS(creationTime / 1000)} min.`);
|
|
||||||
await sleep(creationTime);
|
|
||||||
console.log(`[Enemy Spawn] ${amount} "${npcSettings.id}" has spawned!`);
|
|
||||||
summonEnemy(enemyBatch);
|
|
||||||
|
|
||||||
enemyBatch.hostileLevel++;
|
|
||||||
} else {
|
|
||||||
console.log("[Enemy Spawn] Fail to spawn. Adding 10% more to chances.");
|
|
||||||
enemyBatch.spawnPrecentage += 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turn online and turn offline
|
|
||||||
async function summonEnemy(data) {
|
|
||||||
// If timer exists, do outpost
|
|
||||||
const summonTime = 4; // 4 is debug, normal is 35
|
|
||||||
if (!data.fastSummon) {
|
|
||||||
console.log(`Summoning Ravager... waiting for ${summonTime} seconds.`);
|
|
||||||
client.user.setStatus('online');
|
|
||||||
client.user.setActivity(`Prowling...`);
|
|
||||||
|
|
||||||
// Sets prowling states on the Ravagers
|
|
||||||
for (let i = 0; i < data.enemies.length; i++) {
|
|
||||||
const element = data.enemies[i];
|
|
||||||
element.state = EnemyState.PROWLING;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notification code
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
await sleep(summonTime * 1000);
|
|
||||||
}
|
|
||||||
console.log("Enemy has spawned!");
|
|
||||||
|
|
||||||
// Goes thru all enemies in array
|
|
||||||
for (let i = 0; i < data.enemies.length; i++) {
|
|
||||||
const element = data.enemies[i];
|
|
||||||
const hostileStats = `LVL: ${element.level} | HP: ${element.health} | STR: ${element.strength} | SPD: ${element.speed}`;
|
|
||||||
|
|
||||||
const ravagerMember = client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id);
|
|
||||||
const appearanceEmbed = new Discord.RichEmbed()
|
|
||||||
.setAuthor(ravagerMember.displayName, client.user.avatarURL)
|
|
||||||
.setColor(ravagerMember.displayColor)
|
|
||||||
.setDescription(`${healthbar(element.health, element.health)}\n` + "```" + hostileStats + "```")
|
|
||||||
|
|
||||||
var newMessage = await client.channels.get(data.channel).send(getDialog("onTheProwl"), {embed: appearanceEmbed});
|
|
||||||
await client.user.setStatus('online');
|
|
||||||
await client.user.setActivity(hostileStats);
|
|
||||||
|
|
||||||
for (let i = 0; i < data.enemies.length; i++) {
|
|
||||||
const element = data.enemies[i];
|
|
||||||
element.state = EnemyState.ACTIVE;
|
|
||||||
}
|
|
||||||
enemyTimer(element, data, data.channel, element.fleeTime, newMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Counts down
|
|
||||||
async function enemyTimer(newEnemy, data, channel, fleeTime, newMessage) {
|
|
||||||
function addUserToArray(userID) {
|
|
||||||
attackingUsers.push(userID);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function sendReactions(options) {
|
|
||||||
// Sends reactions
|
|
||||||
for (let i = 0; i < options.length; i++) {
|
|
||||||
const element = options[i];
|
|
||||||
//console.log("[Reaction Options] Emote: " + element + " | newMessage: " + newMessage);
|
|
||||||
await newMessage.react(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Waiting for the next ${fmtMSS(fleeTime / 1000)} min. to check if Ravager has been killed. ${fleeTime}`);
|
|
||||||
|
|
||||||
const ravagerMember = client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id);
|
|
||||||
const interactionEmbed = new Discord.RichEmbed()
|
|
||||||
.setColor(ravagerMember.displayColor)
|
|
||||||
.setTitle("Status")
|
|
||||||
.setDescription("...")
|
|
||||||
|
|
||||||
const sendMessageMinimum = true;
|
|
||||||
var isReadyToFlee = false;
|
|
||||||
var attackingUsers = [];
|
|
||||||
var tempAttackUsers = "";
|
|
||||||
var newChannel = client.channels.get(channel);
|
|
||||||
var interactionMessage = await newChannel.send({embed: interactionEmbed});
|
|
||||||
|
|
||||||
// Possible reaction attacks can go here
|
|
||||||
var options = ['💥', '🇦', '🇧', '🇨']
|
|
||||||
|
|
||||||
// System for no message sending except the minimum
|
|
||||||
if (sendMessageMinimum) {
|
|
||||||
// Collects emotes and reacts upon the reaction
|
|
||||||
const collector = newMessage.createReactionCollector(
|
|
||||||
(reaction, user) => options.includes(reaction.emoji.name) && user.id !== client.user.id);
|
|
||||||
|
|
||||||
sendReactions(options);
|
|
||||||
|
|
||||||
// Collect
|
|
||||||
collector.on("collect", async reaction => {
|
|
||||||
var user = reaction.users.last();
|
|
||||||
|
|
||||||
// Just in case, I managed to bug out Ravager to display its own name.
|
|
||||||
if (user.id === client.user.id) {
|
|
||||||
console.log("Well then. It bypassed the collector filter, we're stopping the Ravager from attacking itself. Would be interesting though!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send damage to server
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
tempAttackUsers += `${user} :crossed_swords: 11 DAM | <:hitback:460969716580745236> MISS (150/150)\n`;
|
|
||||||
addUserToArray(user.id);
|
|
||||||
console.log("Collecting a user! " + user.username)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ends
|
|
||||||
collector.once("end", async collector => {
|
|
||||||
console.log("Ended collector.")
|
|
||||||
flee(newEnemy, data, client.channels.get(channel));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Goes every 4 seconds
|
|
||||||
var emoteRefresh = setInterval(async () => {
|
|
||||||
await newMessage.clearReactions();
|
|
||||||
|
|
||||||
if (isReadyToFlee && newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log("Has fled!");
|
|
||||||
//interactionEmbed.setDescription("👣 The Ravager has fled...")
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
clearInterval(emoteRefresh);
|
|
||||||
collector.stop();
|
|
||||||
} else {
|
|
||||||
console.log("Sending refreshed embed... |" + tempAttackUsers + "|")
|
|
||||||
if (tempAttackUsers === "") tempAttackUsers = "...";
|
|
||||||
interactionEmbed.setDescription(tempAttackUsers);
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
sendReactions(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
tempAttackUsers = "";
|
|
||||||
}, 5 * 1000);
|
|
||||||
|
|
||||||
|
|
||||||
// Waits to see if killed, and if not send a fleeing message
|
|
||||||
await sleep(fleeTime);
|
|
||||||
if (newEnemy.state === EnemyState.ACTIVE) {
|
|
||||||
newChannel.send("**YOU ARE WEAK. THERE IS NO CHALLENGE FOR ME HERE.**\n:bangbang:***ATTEMPTING TO FLEE...***");
|
|
||||||
await sleep(20 * 1000);
|
|
||||||
|
|
||||||
// If still there despawn
|
|
||||||
if (newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log('Hostile is now able to flee, now awaiting for collector to finish.');
|
|
||||||
isReadyToFlee = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Collects emotes and reacts upon the reaction
|
|
||||||
var collector = newMessage.createReactionCollector(
|
|
||||||
(reaction, user) => options.includes(reaction.emoji.name) && user.id !== client.user.id);
|
|
||||||
|
|
||||||
sendReactions(options);
|
|
||||||
|
|
||||||
// Collect
|
|
||||||
collector.on("collect", async reaction => {
|
|
||||||
var user = reaction.users.last();
|
|
||||||
|
|
||||||
// Just in case, I managed to bug out Ravager to display its own name.
|
|
||||||
if (user.id === client.user.id) {
|
|
||||||
console.log("Well then. It bypassed the collector filter, we're stopping the Ravager from attacking itself. Would be interesting though!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send damage to server
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
tempAttackUsers += `${user} :crossed_swords: 11 DAM | <:hitback:460969716580745236> MISS (150/150)\n`;
|
|
||||||
addUserToArray(user.id);
|
|
||||||
console.log("Collecting a user! " + user.username)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ends
|
|
||||||
collector.once("end", async collector => {
|
|
||||||
console.log("Ended collector.")
|
|
||||||
flee(newEnemy, data, client.channels.get(channel));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Goes every 4 seconds
|
|
||||||
var emoteRefresh = setInterval(async () => {
|
|
||||||
await newMessage.clearReactions();
|
|
||||||
|
|
||||||
if (isReadyToFlee && newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log("Has fled!");
|
|
||||||
//interactionEmbed.setDescription("👣 The Ravager has fled...")
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
clearInterval(emoteRefresh);
|
|
||||||
collector.stop();
|
|
||||||
} else {
|
|
||||||
console.log("Sending refreshed embed... |" + tempAttackUsers + "|")
|
|
||||||
if (tempAttackUsers === "") tempAttackUsers = "...";
|
|
||||||
interactionEmbed.setDescription(tempAttackUsers);
|
|
||||||
if (interactionMessage) await interactionMessage.edit({embed: interactionEmbed});
|
|
||||||
sendReactions(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
tempAttackUsers = "";
|
|
||||||
}, 5 * 1000);
|
|
||||||
|
|
||||||
|
|
||||||
// Waits to see if killed, and if not send a fleeing message
|
|
||||||
await sleep(fleeTime);
|
|
||||||
if (newEnemy.state === EnemyState.ACTIVE) {
|
|
||||||
newChannel.send("**YOU ARE WEAK. THERE IS NO CHALLENGE FOR ME HERE.**\n:bangbang:***ATTEMPTING TO FLEE...***");
|
|
||||||
await sleep(20 * 1000);
|
|
||||||
|
|
||||||
// If still there despawn
|
|
||||||
if (newEnemy.state !== EnemyState.UNCONSCIOUS) {
|
|
||||||
console.log('Hostile is now able to flee, now awaiting for collector to finish.');
|
|
||||||
isReadyToFlee = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Does flee sequence
|
|
||||||
async function flee(newEnemy, data, newChannel) {
|
|
||||||
newChannel.send("**THE POOR, ILL-EQUIPPED TRAVELERS PUT UP NO FIGHT...**\n:footprints:***RETURNS TO THE WILD. ***");
|
|
||||||
socket.emit('fled', {
|
|
||||||
data: data,
|
|
||||||
ravager: newEnemy
|
|
||||||
});
|
|
||||||
|
|
||||||
if (data.length < 1) {
|
|
||||||
await client.user.setPresence('invisible');
|
|
||||||
client.user.setActivity('Prowling...');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Health bar
|
|
||||||
function healthbar(health, maxHealth) {
|
|
||||||
var heartHealthAmount = 30;
|
|
||||||
var printString = "";
|
|
||||||
var amountMultiple = 0;
|
|
||||||
var timesToLoop = Math.floor(maxHealth / heartHealthAmount);
|
|
||||||
for (var i = 0; i < timesToLoop; i++) {
|
|
||||||
amountMultiple = i * heartHealthAmount;
|
|
||||||
if (amountMultiple < health) {
|
|
||||||
printString += ":heart: ";
|
|
||||||
} else {
|
|
||||||
printString += ":black_heart:";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printString += " (" + health + "/" + maxHealth + ")";
|
|
||||||
return printString;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Async Waiting
|
|
||||||
function sleep(time) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
setTimeout(resolve, time);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets if user has an Overseers rank
|
|
||||||
function isAdmin(userID) {
|
|
||||||
var guild = client.guilds.get(process.env.SANCTUM_ID);
|
|
||||||
return guild.members.get(userID).roles.find(role => role.name === "Overseers");
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/3733227/javascript-seconds-to-minutes-and-seconds
|
|
||||||
function fmtMSS(s){ // accepts seconds as Number or String. Returns m:ss
|
|
||||||
return( s - // take value s and subtract (will try to convert String to Number)
|
|
||||||
( s %= 60 ) // the new value of s, now holding the remainder of s divided by 60
|
|
||||||
// (will also try to convert String to Number)
|
|
||||||
) / 60 + ( // and divide the resulting Number by 60
|
|
||||||
// (can never result in a fractional value = no need for rounding)
|
|
||||||
// to which we concatenate a String (converts the Number to String)
|
|
||||||
// who's reference is chosen by the conditional operator:
|
|
||||||
9 < s // if seconds is larger than 9
|
|
||||||
? ':' // then we don't need to prepend a zero
|
|
||||||
: ':0' // else we do need to prepend a zero
|
|
||||||
) + s ; // and we add Number s to the string (converting it to String as well)
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/6860853/generate-random-string-for-div-id/6860916#6860916
|
|
||||||
function guidGenerator() {
|
|
||||||
var S4 = function() {
|
|
||||||
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
|
|
||||||
};
|
|
||||||
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDialog(dialogTag, data = "", data2 = "") {
|
|
||||||
switch(dialogTag) {
|
|
||||||
case "onTheProwl":
|
|
||||||
var dialogOptions = [
|
|
||||||
'THE AIR SMELLS OF BLOOD.',
|
|
||||||
'LOOKS LIKE MEAT\'S BACK ON THE MENU BOYS.',
|
|
||||||
'FRESH MEAAAATTTT.',
|
|
||||||
'TONIGHT WE DINE ON TRAVELER FLESSHHHH.',
|
|
||||||
'SKULL CRUSHING IS MY FAVORITE SPORT.',
|
|
||||||
'HUNGRY...',
|
|
||||||
'TRAVELERS MAKE GOOD MEEEAAAAT!',
|
|
||||||
'PUNY TRAVELER THINKS THEY CAN FIGHT?!',
|
|
||||||
'HUNT THEM ALL DOWN.',
|
|
||||||
'I HUNGER FOR THE TASTE OF FLESH.'
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
return "***" + dialogOptions[randomNumber] + "***";
|
|
||||||
|
|
||||||
case "ravagerHit":
|
|
||||||
var dialogOptions = [
|
|
||||||
'STAGGERS BACK',
|
|
||||||
'FALLS BACKWARDS',
|
|
||||||
'CHARGES FORWARD CONFUSED',
|
|
||||||
'LOOKS FOR THE SOURCE OF THE HIT',
|
|
||||||
'FALLS FORWARDS',
|
|
||||||
'BLOCKS ITS FACE',
|
|
||||||
'STUMBLES BACKWARDS IN CONFUSION',
|
|
||||||
'LUNGES FORWARD DISTRACTED',
|
|
||||||
'BITES AT IT\'S ATTACKER',
|
|
||||||
'CHECKS IT\'S WOUND'
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
return `***${dialogOptions[randomNumber]}***`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log our bot in (change the token by looking into the .env file)
|
|
||||||
client.login(process.env.RAVAGER_TOKEN);
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
id: "wolf",
|
|
||||||
activity: "OwOing... Totally not placeholder.",
|
|
||||||
type: "PLAYING",
|
|
||||||
token: process.env.WOLF_TOKEN,
|
|
||||||
botChannel: process.env.SEA_OF_FOG_CHANNEL_ID
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "sanctum-deploypackage",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"description": "Universal package for all SANCTUM bots, using pm2.",
|
|
||||||
"main": "",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "echo \"Error: you need to use the bot name as a command.\" && exit 1",
|
|
||||||
"alexis": "pm2 start alexis.js -i max --watch",
|
|
||||||
"graze": "pm2 start graze.js -i max --watch",
|
|
||||||
"librarian": "pm2 start librarian.js -i max --watch",
|
|
||||||
"mainframe": "pm2 start mainframe.js -i max --watch",
|
|
||||||
"mori": "pm2 start mori.js -i max --watch",
|
|
||||||
"mosiah": "pm2 start mosiah.js -i max --watch",
|
|
||||||
"ravager": "pm2 start ravager.js -i max --watch",
|
|
||||||
"rey": "pm2 start rey.js -i max --watch",
|
|
||||||
"troll": "pm2 start troll.js -i max --watch"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2",
|
|
||||||
"dotenv": "^6.0.0",
|
|
||||||
"express": "^4.16.3",
|
|
||||||
"node-cron": "^1.2.1",
|
|
||||||
"socket.io": "^2.1.1",
|
|
||||||
"socket.io-request": "^0.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
185
Graze/graze.js
185
Graze/graze.js
@@ -1,185 +0,0 @@
|
|||||||
// .env Variables
|
|
||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
// Node Modules
|
|
||||||
const Discord = require('discord.js');
|
|
||||||
const client = new Discord.Client();
|
|
||||||
const cron = require('node-cron');
|
|
||||||
|
|
||||||
// Bot Modules (stores http requests & random functions respectively)
|
|
||||||
const dataRequest = require('../modules/dataRequest');
|
|
||||||
const calcRandom = require('../modules/calcRandom');
|
|
||||||
const channelProcessor = require('../modules/channelProcessor');
|
|
||||||
|
|
||||||
// State Machine (Uncomment if needed)
|
|
||||||
/*
|
|
||||||
var BotEnumState = {
|
|
||||||
WAITING: 0,
|
|
||||||
ACTIVE: 1
|
|
||||||
}
|
|
||||||
var botState = BotEnumState.ACTIVE;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The ready event is vital, it means that your bot will only start reacting to information
|
|
||||||
// from Discord _after_ ready is emitted
|
|
||||||
client.on('ready', async () => {
|
|
||||||
// Generates invite link
|
|
||||||
try {
|
|
||||||
let link = await client.generateInvite(["ADMINISTRATOR"]);
|
|
||||||
console.log("Invite Link: " + link);
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can set status to 'online', 'invisible', 'away', or 'dnd' (do not disturb)
|
|
||||||
client.user.setStatus('online');
|
|
||||||
// Sets your "Playing"
|
|
||||||
client.user.setActivity('!upgrade | Nanotech Upgrades.');
|
|
||||||
console.log(`Connected! \
|
|
||||||
\nLogged in as: ${client.user.username} - (${client.user.id})`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Error handler
|
|
||||||
client.on('error', console.error);
|
|
||||||
|
|
||||||
// Create an event listener for messages
|
|
||||||
client.on('message', async message => {
|
|
||||||
// Ignores ALL bot messages
|
|
||||||
if (message.author.bot) return;
|
|
||||||
// Message has to be a bot channel (should be edited later)
|
|
||||||
if (!channelProcessor.isBotChannel(message.channel.id)) return;
|
|
||||||
// Has to be (prefix)command
|
|
||||||
if (message.content.indexOf(process.env.PREFIX) !== 0) return;
|
|
||||||
|
|
||||||
// "This is the best way to define args. Trust me."
|
|
||||||
// - Some tutorial dude on the internet
|
|
||||||
const args = message.content.slice(process.env.PREFIX.length).trim().split(/ +/g);
|
|
||||||
const command = args.shift().toLowerCase();
|
|
||||||
|
|
||||||
//handle the command
|
|
||||||
switch(command) {
|
|
||||||
case "upgrade":
|
|
||||||
if (!args[0]) {
|
|
||||||
//shows upgrade menu
|
|
||||||
var intro = `${message.author} Hey buddy! Here's what we can upgrade ASAP!`;
|
|
||||||
var newMessage = "STR - <:cannister:462046687058198530> **1**\n```Permanently upgrades your Strength by 1, so you can hit them Ravagers harder.```\n"
|
|
||||||
newMessage += "SPD - <:cannister:462046687058198530> **1**\n```Permanently upgrades your Speed by 1, so you can get hit less in battle.```\n"
|
|
||||||
newMessage += "STAM - <:cannister:462046687058198530> **1**\n```Permanently upgrades your Max Stamina by 1, so you can hit more Ravagers.```\n"
|
|
||||||
newMessage += "HP - <:cannister:462046687058198530> **1**\n```Permanently upgrades your Max HP by 10, so you can can take those beatings like a champ.```"
|
|
||||||
//sendMessage(message.channel.id, newMessage);
|
|
||||||
|
|
||||||
// Grabs all parameters from server
|
|
||||||
var attacker = String(dataRequest.loadServerData("userStats",message.author.id));
|
|
||||||
var attackerStatPoints = parseFloat(attacker.split(",")[10]); // Cannisters
|
|
||||||
const keepersOfTheCityColor = client.guilds.get(process.env.SANCTUM_ID).roles.find(role => role.name === "Keepers of the City").color;
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor("Graze", client.user.avatarURL)
|
|
||||||
.setColor(keepersOfTheCityColor)
|
|
||||||
.setTitle("Nanotech Upgrades")
|
|
||||||
.setDescription(newMessage)
|
|
||||||
.setFooter(`${message.member.displayName}, you have ${attackerStatPoints} cannisters! Use !upgrade [OPTION] to upgrade that stat!`)
|
|
||||||
|
|
||||||
message.channel.send(intro, embed);
|
|
||||||
} else {
|
|
||||||
console.log(args[0]);
|
|
||||||
//Upgrades stats
|
|
||||||
var statToUpgrade = String(args[0]);
|
|
||||||
var numberOfPointsToUpgrade = 1;
|
|
||||||
var canUpgrade = 0;
|
|
||||||
var suffix = "point.";
|
|
||||||
//var statToUpgrade = String(args.split(" ")[0]);
|
|
||||||
//var numberOfPointsToUpgrade = parseFloat(args.split(" ")[1]);
|
|
||||||
switch (statToUpgrade.toUpperCase()) {
|
|
||||||
case "STRENGTH":
|
|
||||||
statToUpgrade = "STR";
|
|
||||||
break;
|
|
||||||
case "HEALTH":
|
|
||||||
statToUpgrade = "HP";
|
|
||||||
break;
|
|
||||||
case "STAMINA":
|
|
||||||
statToUpgrade = "STAM";
|
|
||||||
break;
|
|
||||||
case "SPEED":
|
|
||||||
statToUpgrade = "SPD";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (statToUpgrade.toUpperCase()) {
|
|
||||||
case "STR":
|
|
||||||
numberOfPointsToUpgrade = 1;
|
|
||||||
canUpgrade = 1;
|
|
||||||
suffix = "point.";
|
|
||||||
break;
|
|
||||||
case "HP":
|
|
||||||
numberOfPointsToUpgrade = 10;
|
|
||||||
canUpgrade = 1;
|
|
||||||
suffix = "points.";
|
|
||||||
break;
|
|
||||||
case "SPD":
|
|
||||||
numberOfPointsToUpgrade = 1;
|
|
||||||
canUpgrade = 1;
|
|
||||||
suffix = "point.";
|
|
||||||
break;
|
|
||||||
case "STAM":
|
|
||||||
numberOfPointsToUpgrade = 1;
|
|
||||||
canUpgrade = 1;
|
|
||||||
suffix = "point.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (canUpgrade == 0) {
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Believe me, I wish I could upgrade things like that.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var upgradeResponse = dataRequest.sendServerData("upgradeStats", statToUpgrade, message.author.id);
|
|
||||||
if (String(upgradeResponse) == "notEnoughPoints") {
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Hey now, you don't have that many cannisters.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (String(upgradeResponse) == "failure") {
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Sorry, no can do right now. Come back later though, ok?");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (String(upgradeResponse) == "success") {
|
|
||||||
var skillName = "";
|
|
||||||
switch (statToUpgrade.toUpperCase()) {
|
|
||||||
case "STR":
|
|
||||||
skillName = "strength";
|
|
||||||
break;
|
|
||||||
case "HP":
|
|
||||||
skillName = "health";
|
|
||||||
break;
|
|
||||||
case "SPD":
|
|
||||||
skillName = "speed";
|
|
||||||
break;
|
|
||||||
case "STAM":
|
|
||||||
skillName = "stamina";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sendMessage(message.channel.id, "<@" + message.author.id + "> Sweet! I used your Nanotech Cannister to upgrade your **" + skillName + "** by " + numberOfPointsToUpgrade + " " + suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send message handler
|
|
||||||
function sendMessage(userID, channelID, message) {
|
|
||||||
// Handle optional first argument (so much for default arugments in node)
|
|
||||||
if (message === undefined) {
|
|
||||||
message = channelID;
|
|
||||||
channelID = userID;
|
|
||||||
userID = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility trick (@userID with an optional argument)
|
|
||||||
if (userID != null) {
|
|
||||||
message = "<@" + userID + "> " + message;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sends message (needs client var, therefore I think external script won't work)
|
|
||||||
client.channels.get(channelID).send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log our bot in (change the token by looking into the .env file)
|
|
||||||
client.login(process.env.GRAZE_TOKEN);
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "sanctum-deploypackage",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"description": "Universal package for all SANCTUM bots, using pm2.",
|
|
||||||
"main": "",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "echo \"Error: you need to use the bot name as a command.\" && exit 1",
|
|
||||||
"alexis": "pm2 start alexis.js -i max --watch",
|
|
||||||
"graze": "pm2 start graze.js -i max --watch",
|
|
||||||
"librarian": "pm2 start librarian.js -i max --watch",
|
|
||||||
"mainframe": "pm2 start mainframe.js -i max --watch",
|
|
||||||
"mori": "pm2 start mori.js -i max --watch",
|
|
||||||
"mosiah": "pm2 start mosiah.js -i max --watch",
|
|
||||||
"ravager": "pm2 start ravager.js -i max --watch",
|
|
||||||
"rey": "pm2 start rey.js -i max --watch",
|
|
||||||
"troll": "pm2 start troll.js -i max --watch"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2",
|
|
||||||
"dotenv": "^6.0.0",
|
|
||||||
"express": "^4.16.3",
|
|
||||||
"node-cron": "^1.2.1",
|
|
||||||
"socket.io": "^2.1.1",
|
|
||||||
"socket.io-request": "^0.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2018 TimRuswick
|
Copyright (c) 2018 TimRuswick, Kayne Ruse
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
272
Mori/mori.js
272
Mori/mori.js
@@ -1,272 +0,0 @@
|
|||||||
// .env Variables
|
|
||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
// Node Modules
|
|
||||||
const Discord = require('discord.js');
|
|
||||||
const client = new Discord.Client();
|
|
||||||
const cron = require('node-cron');
|
|
||||||
|
|
||||||
// Bot Modules (stores http requests & random functions respectively)
|
|
||||||
const dataRequest = require('../modules/dataRequest');
|
|
||||||
const calcRandom = require('../modules/calcRandom');
|
|
||||||
const channelProcessor = require('../modules/channelProcessor');
|
|
||||||
|
|
||||||
var medItems = [0, 1, 2];
|
|
||||||
var availableTreatments = [];
|
|
||||||
var itemCount = 3;
|
|
||||||
const treatments = [
|
|
||||||
// Name | Crystals | HP | Description
|
|
||||||
/*
|
|
||||||
['TREAT','5','15','Heals 15HP immediately. Must have more than 0HP.'],
|
|
||||||
['TREATV2','7','%15','Heals to 15% HP immediately. Must have more than 0HP.'],
|
|
||||||
*/
|
|
||||||
['PATCH','10','50','Heals 50HP immediately. Must have more than 0HP.'],
|
|
||||||
['PATCHV2','15','%50','Heals to 50% HP immediately. Must have more than 0HP.'],
|
|
||||||
['REGEN','20','100','Heals 100HP immediately. Must have more than 0HP.'],
|
|
||||||
['REGENV2','25','%100','Heals all HP to maximum immediately. Must have more than 0HP.'],
|
|
||||||
['REVIVE','20','25','Brings a traveler back from a KO (0HP) to 25HP immediately.'],
|
|
||||||
['REVIVEV2','25','%50','Brings a traveler back from a KO (0HP) to 50% HP immediately.'],
|
|
||||||
['REVIVEV3','30','%100','Brings a traveler back from a KO (0HP) to 100% HP immediately.']
|
|
||||||
];
|
|
||||||
|
|
||||||
// The ready event is vital, it means that your bot will only start reacting to information
|
|
||||||
// from Discord _after_ ready is emitted
|
|
||||||
client.on('ready', async () => {
|
|
||||||
// Generates invite link
|
|
||||||
try {
|
|
||||||
let link = await client.generateInvite(["ADMINISTRATOR"]);
|
|
||||||
console.log("Invite Link: " + link);
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can set status to 'online', 'invisible', 'away', or 'dnd' (do not disturb)
|
|
||||||
client.user.setStatus('online');
|
|
||||||
// Sets your "Playing"
|
|
||||||
client.user.setActivity('!heal | BioMed Specialist.');
|
|
||||||
console.log(`Connected! \
|
|
||||||
\nLogged in as: ${client.user.username} - (${client.user.id})`);
|
|
||||||
|
|
||||||
resetInventory(itemCount);
|
|
||||||
});
|
|
||||||
|
|
||||||
//Revives everyone every morning at 7am PST (server time dependant).
|
|
||||||
cron.schedule('0 7 * * *', function() {
|
|
||||||
console.log('Reviving');
|
|
||||||
dataRequest.sendServerData("reviveAll",0);
|
|
||||||
|
|
||||||
var dialogOptions = [
|
|
||||||
'Ahhh. Just finished reviving all of our fellow travelers.',
|
|
||||||
'Rezing travelers is hard work. <@462708244171718656> How was your night?',
|
|
||||||
'Finished up bringing everybody back from the dead. I swear I\'m a magician sometimes.',
|
|
||||||
'Another day. More lives saved. No thanks from anybody. Good times.',
|
|
||||||
'Hello everybody. I see you\'re alive and well. Because of me, but no biggie.',
|
|
||||||
'Bringing everybody back every day is grueling, thankless work.',
|
|
||||||
'I need a vacation. Just brought everybody back and they immediatly go fight ravagers.',
|
|
||||||
'Everybody should be up. Please don\'t run straight to the deadlands.',
|
|
||||||
'Everybody is alive. Thanks to me. But hey, no need to thank me or anything. I\' just drink in silence.',
|
|
||||||
'Good day. All the travelers are back up. Time for some sleep. Goodnight everybody.'
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
|
|
||||||
client.channels.get(process.env.TAVERN_CHANNEL_ID).startTyping();
|
|
||||||
setTimeout(function() {
|
|
||||||
sendMessage(process.env.TAVERN_CHANNEL_ID, dialogOptions[randomNumber]);
|
|
||||||
client.channels.get(process.env.TAVERN_CHANNEL_ID).stopTyping(true);
|
|
||||||
}, calcRandom.random(2500,6000));
|
|
||||||
resetInventory(itemCount);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create an event listener for messages
|
|
||||||
client.on('message', async message => {
|
|
||||||
// Ignores ALL bot messages
|
|
||||||
if (message.author.bot) return;
|
|
||||||
// Message has to be in Outskirts (should be edited later)
|
|
||||||
if (!channelProcessor.isBotChannel(message.channel.id)) return;
|
|
||||||
// Has to be (prefix)command
|
|
||||||
if (message.content.indexOf (process.env.PREFIX) !== 0) return;
|
|
||||||
|
|
||||||
// "This is the best way to define args. Trust me."
|
|
||||||
// - Some tutorial dude on the internet
|
|
||||||
const args = message.content.slice(process.env.PREFIX.length).trim().split(/ +/g);
|
|
||||||
const command = args.shift().toLowerCase();
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case "reset":
|
|
||||||
if (isAdmin(message.author.id))
|
|
||||||
resetInventory(3);
|
|
||||||
break;
|
|
||||||
case "heal":
|
|
||||||
if (!args[0]) {
|
|
||||||
// Grabs all parameters from server
|
|
||||||
var attacker = String(dataRequest.loadServerData("userStats",message.author.id));
|
|
||||||
var attackerWallet = parseFloat(attacker.split(",")[6]); // Crystals
|
|
||||||
|
|
||||||
var intro = `${message.author} Here's what I've got at the moment. My prices are based on availability, `
|
|
||||||
+ `it's hard to find stuff these days.`;
|
|
||||||
var newMessage = "";
|
|
||||||
for (var i = 0; i < availableTreatments.length; i++) {
|
|
||||||
//newMessage += availableTreatments[i][0] + " - **" + availableTreatments[i][1] + "**<:crystals:460974340247257089>\n```" + availableTreatments[i][3] + "```\n";
|
|
||||||
newMessage += `${availableTreatments[i][0]} - <:crystals:460974340247257089> **${availableTreatments[i][1]}**\n` + "```" + availableTreatments[i][3] + "```\n";
|
|
||||||
}
|
|
||||||
const keepersOfTheCityColor = client.guilds.get(process.env.SANCTUM_ID).roles.find(role => role.name === "Keepers of the City").color;
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor("Mori", client.user.avatarURL)
|
|
||||||
.setColor(keepersOfTheCityColor)
|
|
||||||
.setTitle("BioTech Healing")
|
|
||||||
.setDescription(newMessage)
|
|
||||||
.setFooter(`${message.member.displayName}, you have ${attackerWallet} crystals. Use !heal [OPTION] to buy.`)
|
|
||||||
//sendMessage(message.channel.id, newMessage);
|
|
||||||
message.channel.send(intro, embed);
|
|
||||||
} else {
|
|
||||||
//4815
|
|
||||||
var purchase = args[0].toUpperCase();
|
|
||||||
var treatmentCost = 0;
|
|
||||||
var treatmentName = '';
|
|
||||||
var treatmentAvailable = false;
|
|
||||||
for (var i = 0, len = availableTreatments.length; i < len; i++) {
|
|
||||||
if (availableTreatments[i][0] === purchase) {
|
|
||||||
treatmentAvailable = true;
|
|
||||||
treatmentName = availableTreatments[i][0];
|
|
||||||
//treatmentCost = availableTreatments[i][1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (treatmentAvailable) {
|
|
||||||
var healResponse = String(dataRequest.sendServerData("heal", treatmentCost, message.author.id, treatmentName));
|
|
||||||
var response = String(healResponse.split(",")[0]);
|
|
||||||
var health = String(healResponse.split(",")[1]);
|
|
||||||
switch (response) {
|
|
||||||
case "success":
|
|
||||||
sendMessage(message.channel.id, "<@" + message.author.id + "> I\'ve applied a " + purchase + " via nanotech .\n**-" + treatmentCost + "**<:crystals:460974340247257089> | **" + health + "**HP." );
|
|
||||||
break;
|
|
||||||
case "notEnoughCrystals":
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Sorry, looks like you don\'t have the funds for that." );
|
|
||||||
break;
|
|
||||||
case "cantDoThat":
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Sorry, you don\'t meet the requirements for this procedure." );
|
|
||||||
break;
|
|
||||||
case "youreKnockedOut":
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> You\'re currently knoecked out (0HP). You require a revive procdure to heal immediately, or you can wait until 7 AM UTC when I revive everyone." );
|
|
||||||
break;
|
|
||||||
case "lessThanYourHealth":
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Doing that procedure would put you at less than your current HP." );
|
|
||||||
break;
|
|
||||||
case "fullHealth":
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Looks like you\'re already full health. Why would you want to heal?" );
|
|
||||||
break;
|
|
||||||
case "failure":
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Sorry, not sure I understand what procedure you\'d like to purchase." );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> I don\'t have that type of procedure available." );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', console.error);
|
|
||||||
|
|
||||||
// Gets if user has an Overseers rank
|
|
||||||
function isAdmin(userID) {
|
|
||||||
var guild = client.guilds.get(process.env.SANCTUM_ID);
|
|
||||||
return guild.members.get(userID).roles.find(role => role.name === "Overseers");
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetInventory(itemCount) {
|
|
||||||
console.log("\nResetting inventory...");
|
|
||||||
medItems = [];
|
|
||||||
availableTreatments = [];
|
|
||||||
var treatmentsClone = arrayClone(treatments);
|
|
||||||
var tempnum = 0;
|
|
||||||
var i = 0;
|
|
||||||
// DEBUG
|
|
||||||
//itemCount = treatments.length;
|
|
||||||
|
|
||||||
// Chooses random numbers, in order to pick random heal packs
|
|
||||||
do {
|
|
||||||
tempnum = Math.floor(Math.random() * treatments.length);
|
|
||||||
if (!medItems.includes(tempnum)) {
|
|
||||||
medItems.push(tempnum);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
while (medItems.length < itemCount);
|
|
||||||
|
|
||||||
medItems.sort(sortNumber);
|
|
||||||
message = "";
|
|
||||||
var list2 = new Array();
|
|
||||||
for (var i = 0; i < medItems.length; i++) {
|
|
||||||
//console.log('MED ITEM: [' + medItems[i] + '] ADDED');
|
|
||||||
availableTreatments.push(treatmentsClone[medItems[i]]);
|
|
||||||
tempnum = parseFloat(availableTreatments[i][1]);
|
|
||||||
//console.log(">>> Tempnum: " + tempnum + " | availableTreatments: " + availableTreatments[i][1]);
|
|
||||||
//console.log(">>> MedItems: " + treatments[medItems[i]] + "");
|
|
||||||
// Older Calculations
|
|
||||||
var multiple = parseFloat(Math.floor(tempnum / 6));
|
|
||||||
if (calcRandom.gamble(50)) {
|
|
||||||
availableTreatments[i][1] = tempnum + multiple;
|
|
||||||
} else {
|
|
||||||
availableTreatments[i][1] = tempnum - multiple;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Specifically for Treat
|
|
||||||
availableTreatments[i][1] += calcRandom.random(-3, 3);
|
|
||||||
|
|
||||||
console.log(availableTreatments[i][0] + " | Base Cost: " + tempnum + " | HP: " + availableTreatments[i][2] + " | Modifier: " + multiple + " | Final: " + availableTreatments[i][1]);
|
|
||||||
|
|
||||||
message = availableTreatments[i][0] + " - **" + availableTreatments[i][1] + "**<:crystals:460974340247257089>\n```" + availableTreatments[i][3] + "```\n";
|
|
||||||
//console.log(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortNumber(a,b) {
|
|
||||||
return a - b;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send message handler
|
|
||||||
function sendMessage(userID, channelID, message) {
|
|
||||||
// Handle optional first argument (so much for default arugments in node)
|
|
||||||
if (message === undefined) {
|
|
||||||
message = channelID;
|
|
||||||
channelID = userID;
|
|
||||||
userID = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility trick (@userID with an optional argument)
|
|
||||||
if (userID != null) {
|
|
||||||
message = "<@" + userID + "> " + message;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sends message (needs client var, therefore I think external script won't work)
|
|
||||||
client.channels.get(channelID).send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
This function is for fixing a bug where an array gets edited, and possibly
|
|
||||||
causing negative numbers due to my calcRandom +2 -2 change. This will not
|
|
||||||
work with arrays containing objects (eg. JSON data).
|
|
||||||
*/
|
|
||||||
// https://blog.andrewray.me/how-to-clone-a-nested-array-in-javascript/
|
|
||||||
function arrayClone(arr) {
|
|
||||||
var i, copy;
|
|
||||||
|
|
||||||
if( Array.isArray( arr ) ) {
|
|
||||||
copy = arr.slice( 0 );
|
|
||||||
for( i = 0; i < copy.length; i++ ) {
|
|
||||||
copy[ i ] = arrayClone( copy[ i ] );
|
|
||||||
}
|
|
||||||
return copy;
|
|
||||||
} else if( typeof arr === 'object' ) {
|
|
||||||
throw 'Cannot clone array containing an object!';
|
|
||||||
} else {
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Log our bot in (change the token by looking into the .env file)
|
|
||||||
client.login(process.env.MORI_TOKEN);
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "sanctum-deploypackage",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"description": "Universal package for all SANCTUM bots, using pm2.",
|
|
||||||
"main": "",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "echo \"Error: you need to use the bot name as a command.\" && exit 1",
|
|
||||||
"alexis": "pm2 start alexis.js -i max --watch",
|
|
||||||
"graze": "pm2 start graze.js -i max --watch",
|
|
||||||
"librarian": "pm2 start librarian.js -i max --watch",
|
|
||||||
"mainframe": "pm2 start mainframe.js -i max --watch",
|
|
||||||
"mori": "pm2 start mori.js -i max --watch",
|
|
||||||
"mosiah": "pm2 start mosiah.js -i max --watch",
|
|
||||||
"ravager": "pm2 start ravager.js -i max --watch",
|
|
||||||
"rey": "pm2 start rey.js -i max --watch",
|
|
||||||
"troll": "pm2 start troll.js -i max --watch"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2",
|
|
||||||
"dotenv": "^6.0.0",
|
|
||||||
"express": "^4.16.3",
|
|
||||||
"node-cron": "^1.2.1",
|
|
||||||
"socket.io": "^2.1.1",
|
|
||||||
"socket.io-request": "^0.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
144
Mosiah/mosiah.js
144
Mosiah/mosiah.js
@@ -1,144 +0,0 @@
|
|||||||
// .env Variables
|
|
||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
// Node Modules
|
|
||||||
const Discord = require('discord.js');
|
|
||||||
const client = new Discord.Client();
|
|
||||||
const cron = require('node-cron');
|
|
||||||
|
|
||||||
// Bot Modules
|
|
||||||
const dataRequest = require('../modules/dataRequest');
|
|
||||||
const calcRandom = require('../modules/calcRandom');
|
|
||||||
|
|
||||||
const normalActivity = '!wager | Games of Fortune';
|
|
||||||
|
|
||||||
// State Machine
|
|
||||||
var MosiahEnumState = {
|
|
||||||
WAITING: 0,
|
|
||||||
GAMBLING: 1
|
|
||||||
}
|
|
||||||
var mosiahState = MosiahEnumState.WAITING;
|
|
||||||
|
|
||||||
// The ready event is vital, it means that your bot will only start reacting to information
|
|
||||||
// from Discord _after_ ready is emitted
|
|
||||||
client.on('ready', async () => {
|
|
||||||
// Generates invite link
|
|
||||||
try {
|
|
||||||
let link = await client.generateInvite(["ADMINISTRATOR"]);
|
|
||||||
console.log("Invite Link: " + link);
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
client.user.setStatus('invisible');
|
|
||||||
client.user.setActivity(normalActivity);
|
|
||||||
console.log(`Connected! \
|
|
||||||
\nLogged in as: ${client.user.username} - (${client.user.id})`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create an event listener for messages
|
|
||||||
client.on('message', async message => {
|
|
||||||
// Ignores ALL bot messages
|
|
||||||
if (message.author.bot) return;
|
|
||||||
// Message has to be in Tavern or Test
|
|
||||||
if (!(message.channel.id === process.env.TAVERN_CHANNEL_ID
|
|
||||||
|| message.channel.id === process.env.TEST_CHANNEL_ID)) return;
|
|
||||||
// Has to be (prefix)command
|
|
||||||
if (message.content.indexOf(process.env.PREFIX) !== 0) return;
|
|
||||||
|
|
||||||
// "This is the best way to define args. Trust me."
|
|
||||||
// - Some tutorial dude on the internet
|
|
||||||
const args = message.content.slice(process.env.PREFIX.length).trim().split(/ +/g);
|
|
||||||
const command = args.shift().toLowerCase();
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case "wager":
|
|
||||||
if (mosiahState == MosiahEnumState.GAMBLING)
|
|
||||||
wagerMessage(message, args);
|
|
||||||
else
|
|
||||||
message.reply("I'm out and about right now. Don't wanna get found by the wrong peoples.");
|
|
||||||
break;
|
|
||||||
case "msummon":
|
|
||||||
if (isAdmin(message.author.id)) MosiahTurnOnline();
|
|
||||||
break;
|
|
||||||
case "mvanish":
|
|
||||||
if (isAdmin(message.author.id)) MosiahTurnOffline();
|
|
||||||
break;
|
|
||||||
case "rigged":
|
|
||||||
message.channel.send("What are you talkin' about? I may look like it, being an outcaster from the city, but I'd never rip peoples off.");
|
|
||||||
|
|
||||||
// Testing out textadv payment
|
|
||||||
if (isAdmin(message.author.id)) dataRequest.sendServerData("gambleWon", 50, message.author.id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', console.error);
|
|
||||||
|
|
||||||
// Gets if user has an Overseers rank
|
|
||||||
function isAdmin(userID) {
|
|
||||||
var guild = client.guilds.get(process.env.SANCTUM_ID);
|
|
||||||
return guild.members.get(userID).roles.find(role => role.name === "Overseers");
|
|
||||||
}
|
|
||||||
|
|
||||||
function wagerMessage(message, args) {
|
|
||||||
var amount = Math.floor(args[0]);
|
|
||||||
var account = dataRequest.loadServerData("account", message.author.id);
|
|
||||||
if (amount > 0) {
|
|
||||||
if (amount <= account) {
|
|
||||||
if (calcRandom.gamble(49)) {
|
|
||||||
sendMessage(message.channel.id, "<@" + message.author.id + "> Ya got me. Here's your " + amount + " crystals. ");
|
|
||||||
dataRequest.sendServerData("gambleWon", amount, message.author.id);
|
|
||||||
} else {
|
|
||||||
sendMessage(message.channel.id, "<@" + message.author.id + "> Looks like ya lost. Guess I'll keep your " + amount + " crystals. ");
|
|
||||||
dataRequest.sendServerData("gambleLost", amount, message.author.id);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Yer a funny one ain't ya. Show me the crystals first.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Aww c'mon. You wanna wager me nothin'?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cron.schedule('0 7 * * Saturday', function(){
|
|
||||||
console.log('Saturday join.' + new Date().toLocaleString());
|
|
||||||
MosiahTurnOnline();
|
|
||||||
});
|
|
||||||
|
|
||||||
cron.schedule('0 7 * * Sunday', function(){
|
|
||||||
console.log('Sunday leave.' + new Date().toLocaleString());
|
|
||||||
MosiahTurnOffline();
|
|
||||||
});
|
|
||||||
|
|
||||||
function MosiahTurnOnline() {
|
|
||||||
client.user.setStatus('online');
|
|
||||||
client.channels.get(process.env.TAVERN_CHANNEL_ID).send("*Psst.* Anyone wanna wager a few **<:crystals:460974340247257089> Crystals** with me?");
|
|
||||||
mosiahState = MosiahEnumState.GAMBLING;
|
|
||||||
}
|
|
||||||
|
|
||||||
function MosiahTurnOffline() {
|
|
||||||
client.user.setStatus('invisible');
|
|
||||||
mosiahState = MosiahEnumState.WAITING;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send message handler
|
|
||||||
function sendMessage(userID, channelID, message) {
|
|
||||||
// Handle optional first argument (so much for default arugments in node)
|
|
||||||
if (message === undefined) {
|
|
||||||
message = channelID;
|
|
||||||
channelID = userID;
|
|
||||||
userID = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility trick (@userID with an optional argument)
|
|
||||||
if (userID != null) {
|
|
||||||
message = "<@" + userID + "> " + message;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sends message (needs client var, therefore I think external script won't work)
|
|
||||||
client.channels.get(channelID).send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log our bot in
|
|
||||||
client.login(process.env.MOSIAH_TOKEN);
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "sanctum-deploypackage",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"description": "Universal package for all SANCTUM bots, using pm2.",
|
|
||||||
"main": "",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "echo \"Error: you need to use the bot name as a command.\" && exit 1",
|
|
||||||
"alexis": "pm2 start alexis.js -i max --watch",
|
|
||||||
"graze": "pm2 start graze.js -i max --watch",
|
|
||||||
"librarian": "pm2 start librarian.js -i max --watch",
|
|
||||||
"mainframe": "pm2 start mainframe.js -i max --watch",
|
|
||||||
"mori": "pm2 start mori.js -i max --watch",
|
|
||||||
"mosiah": "pm2 start mosiah.js -i max --watch",
|
|
||||||
"ravager": "pm2 start ravager.js -i max --watch",
|
|
||||||
"rey": "pm2 start rey.js -i max --watch",
|
|
||||||
"troll": "pm2 start troll.js -i max --watch"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2",
|
|
||||||
"dotenv": "^6.0.0",
|
|
||||||
"express": "^4.16.3",
|
|
||||||
"node-cron": "^1.2.1",
|
|
||||||
"socket.io": "^2.1.1",
|
|
||||||
"socket.io-request": "^0.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#.htaccess
|
|
||||||
Options -Indexes
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,81 +0,0 @@
|
|||||||
<?php
|
|
||||||
//header('Access-Control-Allow-Origin: *');
|
|
||||||
//header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
|
|
||||||
include_once 'functions.php';
|
|
||||||
|
|
||||||
if( isset($_GET['pk']) ){ $privateKey = $_GET['pk']; } else{ $privateKey = ''; };
|
|
||||||
$sqlterms = '';
|
|
||||||
$debug = false;
|
|
||||||
|
|
||||||
if($privateKey != "123"){
|
|
||||||
echo throwError("invalidPrivateKey");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<HTML>
|
|
||||||
<HEAD>
|
|
||||||
<TITLE>THE CODEX</TITLE>
|
|
||||||
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.css">
|
|
||||||
|
|
||||||
<script
|
|
||||||
src="https://code.jquery.com/jquery-3.3.1.min.js"
|
|
||||||
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.js"></script>
|
|
||||||
</HEAD>
|
|
||||||
|
|
||||||
<BODY>
|
|
||||||
|
|
||||||
<table id="table_id" class="display">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>Level</th>
|
|
||||||
<th>Crystals</th>
|
|
||||||
<th>SPD</th>
|
|
||||||
<th>STR</th>
|
|
||||||
<th>STAM</th>
|
|
||||||
<th>HP</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$con = mysqlConnect();
|
|
||||||
$q = "SELECT discordUserID,wallet,speed,health,maxHealth,strength,maxStamina,stamina,lvl FROM users LIMIT 500;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$discordUserID=stripslashes($a['discordUserID']);
|
|
||||||
$wallet=stripslashes($a['wallet']);
|
|
||||||
$speed=stripslashes($a['speed']);
|
|
||||||
$health=stripslashes($a['health']);
|
|
||||||
$maxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$strength=stripslashes($a['strength']);
|
|
||||||
$maxStamina=stripslashes($a['maxStamina']);
|
|
||||||
$stamina=stripslashes($a['stamina']);
|
|
||||||
$lvl=stripslashes($a['lvl']);
|
|
||||||
?>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><?php echo $discordUserID; ?></td>
|
|
||||||
<td><?php echo $lvl; ?></td>
|
|
||||||
<td><?php echo $wallet; ?></td>
|
|
||||||
<td><?php echo $speed; ?></td>
|
|
||||||
<td><?php echo $strength; ?></td>
|
|
||||||
<td><?php echo $stamina."/".$maxStamina; ?></td>
|
|
||||||
<td><?php echo $health."/".$maxHealth; ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<script>
|
|
||||||
$(document).ready( function () {
|
|
||||||
$('#table_id').DataTable();
|
|
||||||
} );
|
|
||||||
</script>
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
CREATE DATABASE discordbot;
|
|
||||||
|
|
||||||
CREATE TABLE discordbot.userLog (
|
|
||||||
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
discordUserID bigint,
|
|
||||||
actionTime TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
actionType varchar(16),
|
|
||||||
actionData varchar(255)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE discordbot.users (
|
|
||||||
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
discordUserID bigint,
|
|
||||||
timeJoined TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
wallet int,
|
|
||||||
speed int NOT NULL DEFAULT 5,
|
|
||||||
health int NOT NULL DEFAULT 100,
|
|
||||||
maxHealth int NOT NULL DEFAULT 100,
|
|
||||||
strength int NOT NULL DEFAULT 5,
|
|
||||||
stamina int NOT NULL DEFAULT 5,
|
|
||||||
maxStamina int NOT NULL DEFAULT 5,
|
|
||||||
xp int NOT NULL DEFAULT 0,
|
|
||||||
lvl int NOT NULL DEFAULT 0,
|
|
||||||
statPoints int NOT NULL DEFAULT 0
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE discordbot.factions (
|
|
||||||
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
discordRoleID bigint,
|
|
||||||
discordRoleName varchar(16),
|
|
||||||
account int,
|
|
||||||
isCurrentVictor bool
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE discordbot.hostiles (
|
|
||||||
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
timeCreated TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
hostileName varchar(32),
|
|
||||||
hostileType varchar(32),
|
|
||||||
maxHealth int NOT NULL DEFAULT 100,
|
|
||||||
health varchar(16) NOT NULL DEFAULT 100,
|
|
||||||
strength int NOT NULL DEFAULT 10,
|
|
||||||
speed int NOT NULL DEFAULT 10,
|
|
||||||
stash int NOT NULL DEFAULT 10,
|
|
||||||
alive bool NOT NULL DEFAULT 0,
|
|
||||||
fled bool NOT NULL DEFAULT 0,
|
|
||||||
claimID varchar(4)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE discordbot.attackLog (
|
|
||||||
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
timeAttacked TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
discordUserID bigint,
|
|
||||||
hostileID varchar(16),
|
|
||||||
damage int NOT NULL DEFAULT 0
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE discordbot.artifacts (
|
|
||||||
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
discordUserID bigint,
|
|
||||||
scrap int NOT NULL DEFAULT 0,
|
|
||||||
common int NOT NULL DEFAULT 0,
|
|
||||||
uncommon int NOT NULL DEFAULT 0,
|
|
||||||
rare int NOT NULL DEFAULT 0,
|
|
||||||
ultrarare int NOT NULL DEFAULT 0
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE discordbot.artifactEvents (
|
|
||||||
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
timeStarted TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
eventType varchar(16) NOT NULL DEFAULT "default",
|
|
||||||
eventLevel int NOT NULL DEFAULT 0
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE discordbot.lootPool (
|
|
||||||
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
created TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
name varchar(128) NOT NULL DEFAULT "default",
|
|
||||||
gearType varchar(16) NOT NULL DEFAULT "weapon",
|
|
||||||
subType varchar(16) NOT NULL DEFAULT "melee",
|
|
||||||
baseLvl int NOT NULL DEFAULT 0,
|
|
||||||
baseAtk int NOT NULL DEFAULT 0,
|
|
||||||
baseDef int NOT NULL DEFAULT 0,
|
|
||||||
rarity int NOT NULL DEFAULT 0,
|
|
||||||
perksAvailable varchar(16) NOT NULL DEFAULT "none",
|
|
||||||
eventLevel int NOT NULL DEFAULT 0
|
|
||||||
);
|
|
||||||
@@ -1,197 +0,0 @@
|
|||||||
<?php
|
|
||||||
function privateKey(){
|
|
||||||
return "INSERT PRIVATE KEY";
|
|
||||||
}
|
|
||||||
|
|
||||||
function throwError($errorName){
|
|
||||||
switch ($errorName) {
|
|
||||||
case "invalidPrivateKey":
|
|
||||||
return "Sorry, this didnt work. Admins used an invalid key. Bug them about it!";
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
echo "i equals 1";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
echo "i equals 2";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function constants($tag){
|
|
||||||
|
|
||||||
//Base Domain Name
|
|
||||||
if ($tag == 'baseurl'){ return "http://gdu.io/"; }
|
|
||||||
|
|
||||||
//Base URL to the members section
|
|
||||||
if ($tag == 'ubaseurl'){ return "http://gdu.io/"; }
|
|
||||||
|
|
||||||
//Turns on PHP errors
|
|
||||||
if ($tag == 'debugmode'){ return true; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function getLevel($xp,$lvlbase){
|
|
||||||
if($xp >= 1){
|
|
||||||
$lvl = $lvlbase * sqrt($xp);;
|
|
||||||
} else{
|
|
||||||
$lvl = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Returns level based total # of xp
|
|
||||||
return $lvl;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
function getLevel($xp,$lvlbase){
|
|
||||||
if($xp >= 1){
|
|
||||||
$lvl = log($xp,$lvlbase);
|
|
||||||
} else{
|
|
||||||
$lvl = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Returns level based total # of xp
|
|
||||||
return $lvl;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
function getCurrentLevelProgress($xp,$lvl){
|
|
||||||
|
|
||||||
$baseLevel = floor($lvl);
|
|
||||||
$levelDecimal = $lvl - $baseLevel;
|
|
||||||
|
|
||||||
$percentage = $levelDecimal*100;
|
|
||||||
$fullNumber = 100;
|
|
||||||
|
|
||||||
$actualPercentage = floor(($percentage / 100) * $fullNumber);
|
|
||||||
|
|
||||||
//Returns progress in percentage
|
|
||||||
return $actualPercentage;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
|
|
||||||
|
|
||||||
function getXp($lvl,$lvlbase){
|
|
||||||
|
|
||||||
$xp = floor(pow($lvlbase,ceil($lvl)) - pow($lvlbase,floor($lvl)));
|
|
||||||
|
|
||||||
//Returns xp needed from start to finish to complete current level
|
|
||||||
return $xp;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAllXp($lvl,$lvlbase){
|
|
||||||
|
|
||||||
|
|
||||||
$xp = pow($lvlbase,floor($lvl));
|
|
||||||
//Returns # of xp required to reach current level
|
|
||||||
return $xp;
|
|
||||||
}
|
|
||||||
function getCurrentLevelProgress($xp,$lvl,$lvlbase){
|
|
||||||
|
|
||||||
$xpInCurrentLevel = getXp($lvl,$lvlbase);
|
|
||||||
$totalXpRequiredForCurrentLevel = getAllXp($lvl,$lvlbase);
|
|
||||||
$xpTowardNextLevel = $xp - $totalXpRequiredForCurrentLevel;
|
|
||||||
|
|
||||||
if($xpInCurrentLevel > 0){
|
|
||||||
$xpProgress = round(($xpTowardNextLevel / $xpInCurrentLevel)*100,1);
|
|
||||||
}else{
|
|
||||||
$xpProgress = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Returns progress in percentage
|
|
||||||
return $xpProgress;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
function addXp($uid,$xpamount){
|
|
||||||
$con = mysqlConnect();
|
|
||||||
$q = "UPDATE users SET xp=(xp + $xpamount) WHERE discordUserID = '$uid'";
|
|
||||||
$r = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
function getLevelBase(){
|
|
||||||
return 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
function full_url()
|
|
||||||
{
|
|
||||||
$s = empty($_SERVER["HTTPS"]) ? '' : ($_SERVER["HTTPS"] == "on") ? "s" : "";
|
|
||||||
$sp = strtolower($_SERVER["SERVER_PROTOCOL"]);
|
|
||||||
$protocol = substr($sp, 0, strpos($sp, "/")) . $s;
|
|
||||||
$port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":".$_SERVER["SERVER_PORT"]);
|
|
||||||
return $protocol . "://" . $_SERVER['SERVER_NAME'] . $port . $_SERVER['REQUEST_URI'];
|
|
||||||
}
|
|
||||||
// CLASS FOR CONVERTING TIME TO AGO
|
|
||||||
class convertToAgo {
|
|
||||||
|
|
||||||
function convert_datetime($str) {
|
|
||||||
|
|
||||||
list($date, $time) = explode(' ', $str);
|
|
||||||
list($year, $month, $day) = explode('-', $date);
|
|
||||||
list($hour, $minute, $second) = explode(':', $time);
|
|
||||||
$timestamp = mktime($hour, $minute, $second, $month, $day, $year);
|
|
||||||
return $timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeAgo($timestamp){
|
|
||||||
|
|
||||||
$difference = time() - $timestamp;
|
|
||||||
$periods = array("second", "minute", "hour", "day", "week", "month", "year", "decade");
|
|
||||||
$lengths = array("60","60","24","7","4.35","12","10");
|
|
||||||
for($j = 0; $difference >= $lengths[$j]; $j++)
|
|
||||||
$difference /= $lengths[$j];
|
|
||||||
$difference = round($difference);
|
|
||||||
if($difference != 1) $periods[$j].= "s";
|
|
||||||
if ( (($periods[$j] == "minute") or ($periods[$j] == "minutes") && ($difference < 3))
|
|
||||||
or (($periods[$j] == "second") or ($periods[$j] == "seconds")) ){
|
|
||||||
$text = "Just now";
|
|
||||||
} else {
|
|
||||||
$text = "$difference $periods[$j] ago";
|
|
||||||
}
|
|
||||||
return $text;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // END CLASS
|
|
||||||
|
|
||||||
|
|
||||||
function checkArrayFor($array, $key, $val) {
|
|
||||||
foreach ($array as $item)
|
|
||||||
if (isset($item[$key]) && $item[$key] == $val)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function addhttp($url) {
|
|
||||||
if ($url != ''){
|
|
||||||
if (!preg_match("~^(?:f|ht)tps?://~i", $url)) {
|
|
||||||
$url = "http://" . $url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function mysqlConnect() {
|
|
||||||
$dbhost = 'INSERT DB HOST';
|
|
||||||
$dbusername = 'INSERT DB USERNAME';
|
|
||||||
$dbpassword = 'INSERT DB PASSWORD';
|
|
||||||
$dbtable = 'INSERT DB TABLE';
|
|
||||||
|
|
||||||
$userDB = 'user';
|
|
||||||
$userdataDB = 'userdata';
|
|
||||||
$memberDB = 'member';
|
|
||||||
$memberdataDB = 'memberdata';
|
|
||||||
|
|
||||||
$con = mysqli_connect($dbhost,$dbusername,$dbpassword,$dbtable);
|
|
||||||
if (!$con) { die('Could not connect: ' . mysqli_error());}
|
|
||||||
mysqli_select_db($con, "$dbtable")or die("cannot select DB");
|
|
||||||
return $con;
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
<?php
|
|
||||||
//header('Access-Control-Allow-Origin: *');
|
|
||||||
//header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
|
|
||||||
include_once 'functions.php';
|
|
||||||
|
|
||||||
if( isset($_GET['dataToLoad']) ){ $dataToLoad = $_GET['dataToLoad']; } else{ $dataToLoad = ''; };
|
|
||||||
if( isset($_GET['userid']) ){ $userID = $_GET['userid']; } else{ $userID = ''; };
|
|
||||||
if( isset($_GET['pk']) ){ $privateKey = $_GET['pk']; } else{ $privateKey = ''; };
|
|
||||||
$sqlterms = '';
|
|
||||||
$debug = false;
|
|
||||||
|
|
||||||
if($privateKey != privateKey()){
|
|
||||||
echo throwError("invalidPrivateKey");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$con = mysqlConnect();
|
|
||||||
|
|
||||||
switch ($dataToLoad) {
|
|
||||||
case "hasConvertedToday":
|
|
||||||
$q = "SELECT id FROM userLog WHERE actionTime >= (DATE_SUB(now(), INTERVAL 30 DAY)) AND actionType = 'conversion' AND discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
echo 1;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "account":
|
|
||||||
$q = "SELECT wallet FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$account=stripslashes($a['wallet']);
|
|
||||||
}
|
|
||||||
echo $account;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "{ERROR}";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "bank":
|
|
||||||
$q = "SELECT account FROM factions WHERE discordRoleID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$account=stripslashes($a['account']);
|
|
||||||
}
|
|
||||||
echo $account;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "{ERROR}";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "victors":
|
|
||||||
$q = "SELECT discordRoleName FROM factions WHERE isCurrentVictor = '1';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$discordRoleName=stripslashes($a['discordRoleName']);
|
|
||||||
}
|
|
||||||
echo $discordRoleName;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "0";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "hostileActive":
|
|
||||||
$q = "SELECT id FROM hostiles WHERE alive = 1 AND health > 0 AND fled = 0;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$hostileID=stripslashes($a['id']);
|
|
||||||
}
|
|
||||||
echo $hostileID;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "0";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "lastHostileActive":
|
|
||||||
$q = "SELECT id FROM hostiles ORDER BY id DESC LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$hostileID=stripslashes($a['id']);
|
|
||||||
}
|
|
||||||
echo $hostileID;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "0";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "userStats":
|
|
||||||
$q = "SELECT strength,speed,stamina,health,maxStamina,maxHealth,wallet,xp,lvl,statPoints,chests FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$strength=stripslashes($a['strength']);
|
|
||||||
$speed=stripslashes($a['speed']);
|
|
||||||
$stamina=stripslashes($a['stamina']);
|
|
||||||
$health=stripslashes($a['health']);
|
|
||||||
$maxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$maxStamina=stripslashes($a['maxStamina']);
|
|
||||||
$wallet=stripslashes($a['wallet']);
|
|
||||||
$xp=stripslashes($a['xp']);
|
|
||||||
$recordedLVL=stripslashes($a['lvl']);
|
|
||||||
$statPoints=stripslashes($a['statPoints']);
|
|
||||||
$chests=stripslashes($a['chests']);
|
|
||||||
$lvlbase = getLevelBase();
|
|
||||||
$lvl = getLevel($xp,$lvlbase);
|
|
||||||
$lvlpercent = getCurrentLevelProgress($xp,$lvl);
|
|
||||||
}
|
|
||||||
echo $strength.",".$speed.",".$stamina.",".$health.",".$maxStamina.",".$maxHealth.",".$wallet.",".$xp.",".$recordedLVL.",".$lvlpercent.",".$statPoints.",".$chests;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "0";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "artifactsGet":
|
|
||||||
|
|
||||||
$q = "SELECT scrap,common,uncommon,rare,ultrarare FROM artifacts WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
$a = mysqli_fetch_assoc($r2);
|
|
||||||
$scrapQuantity=stripslashes($a['scrap']);
|
|
||||||
$commonQuantity=stripslashes($a['common']);
|
|
||||||
$uncommonQuantity=stripslashes($a['uncommon']);
|
|
||||||
$rareQuantity=stripslashes($a['rare']);
|
|
||||||
$ultrarareQuantity=stripslashes($a['ultrarare']);
|
|
||||||
echo "success,".$ultrarareQuantity.",".$rareQuantity.",".$uncommonQuantity.",".$commonQuantity.",".$scrapQuantity;
|
|
||||||
} else{
|
|
||||||
echo "failure";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
if ($dataToLoad == "crystals"){
|
|
||||||
echo "343 Crystals in the vault!";
|
|
||||||
} else{
|
|
||||||
echo "No command found.";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if($featured==1){
|
|
||||||
$sqlterms .= "AND userartistinfo.featured = 1 ";
|
|
||||||
}
|
|
||||||
if($search !== ''){
|
|
||||||
$sqlterms .= "AND (userartistinfo.city LIKE '%".$search."%' OR userartistinfo.state LIKE '%".$search."%' OR userartistinfo.zip LIKE '%".$search."%')";
|
|
||||||
}
|
|
||||||
$q = "SELECT
|
|
||||||
user.id as artistid, user.slug, user.displayname, user.picurl,
|
|
||||||
userartistinfo.genre, userartistinfo.views,
|
|
||||||
userartistinfo.contactemail, userartistinfo.phone, userartistinfo.address, userartistinfo.city, userartistinfo.state, userartistinfo.zip, userartistinfo.website
|
|
||||||
FROM user, userartistinfo
|
|
||||||
where user.active = 1
|
|
||||||
AND user.id = userartistinfo.id
|
|
||||||
AND user.type = 'store'
|
|
||||||
".$sqlterms."
|
|
||||||
ORDER BY user.created DESC, views DESC
|
|
||||||
LIMIT 15";
|
|
||||||
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$i=0;
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
|
|
||||||
$displayname = stripslashes($a['displayname']);
|
|
||||||
$picurl = s3url('weedauthority-userimages', stripslashes($a['picurl']) );
|
|
||||||
$phone = stripslashes($a['phone']);
|
|
||||||
$address = stripslashes($a['address'])."<br />".stripslashes($a['city'])." ".stripslashes($a['state']).", ".stripslashes($a['zip']);
|
|
||||||
$addressPlainText = stripslashes($a['address'])." ".stripslashes($a['city'])." ".stripslashes($a['state']).", ".stripslashes($a['zip']);
|
|
||||||
$link = $baseurl."dispensary/".stripslashes($a['slug']);
|
|
||||||
//$maplink ="https://maps.google.com/maps?q=". urlencode($addressPlainText);
|
|
||||||
//$maplink = "https://www.google.com/maps/place/".urlencode($addressPlainText)."/";
|
|
||||||
$maplink = stripslashes($a['website']);
|
|
||||||
|
|
||||||
$statushtml = "<div id='build-" . $i . "' class='card'><div class='list-block beta-div'><div class='beta-title'>" . $displayname . "</div><img src='" . $picurl . "' class='beta-icon'>";
|
|
||||||
$statushtml .= "<div class='beta-version'><i class='fa fa-phone'></i> " . $phone . "</div><div class='beta-version'><i class='fa fa-map-marker'></i> " . $address . "</div><div class='beta-button'>";
|
|
||||||
$statushtml .= "<button class='button button-fill launchbutton launchbuttonactive launchbeta' data-url='" . $maplink . "'>View Shop</button>";
|
|
||||||
//$statushtml .= "<a href='geo://0,0?q=".$addressPlainText."' data-rel='external'><button class='button button-fill launchbutton launchbuttonactive launchbeta''>View Shop</button></a>";
|
|
||||||
$statushtml .= "</div><div style='clear:both;'></div><BR></div></div>";
|
|
||||||
|
|
||||||
|
|
||||||
$array[$i]=array($statushtml );
|
|
||||||
//$array[$i]=array($displayname,$picurl,$phone,$address,$link );
|
|
||||||
//echo $title;
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
$array[0]=array("<BR /><BR /><center><i class='fa fa-search error-icon' aria-hidden='true'></i><BR /><BR />
|
|
||||||
Looks like we can't find any shops matching that criteria. <BR />Try searching again!</center>");
|
|
||||||
//echo json_encode($array);
|
|
||||||
}
|
|
||||||
|
|
||||||
echo json_encode($array);
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
*/
|
|
||||||
if($debug){
|
|
||||||
echo "\n"."UID:".$userID;
|
|
||||||
}
|
|
||||||
|
|
||||||
//mysqli_close($con);
|
|
||||||
|
|
||||||
|
|
||||||
?>
|
|
||||||
@@ -1,752 +0,0 @@
|
|||||||
<?php
|
|
||||||
//header('Access-Control-Allow-Origin: *');
|
|
||||||
//header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
|
|
||||||
include_once 'functions.php';
|
|
||||||
|
|
||||||
if( isset($_GET['dataType']) ){ $dataType = $_GET['dataType']; } else{ $dataType = ''; };
|
|
||||||
if( isset($_GET['dataToSend']) ){ $dataToSend = $_GET['dataToSend']; } else{ $dataToSend = ''; };
|
|
||||||
if( isset($_GET['dataToSend2']) ){ $dataToSend2 = $_GET['dataToSend2']; } else{ $dataToSend2 = ''; };
|
|
||||||
if( isset($_GET['userid']) ){ $userID = $_GET['userid']; } else{ $userID = ''; };
|
|
||||||
if( isset($_GET['pk']) ){ $privateKey = $_GET['pk']; } else{ $privateKey = ''; };
|
|
||||||
$debug = false;
|
|
||||||
|
|
||||||
if($privateKey != privateKey()){
|
|
||||||
echo throwError("invalidPrivateKey");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$con = mysqlConnect();
|
|
||||||
|
|
||||||
switch ($dataType) {
|
|
||||||
case "conversion":
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', '" . $dataToSend . "');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
break;
|
|
||||||
case "newUser":
|
|
||||||
/*
|
|
||||||
$q = "INSERT INTO users (discordUserID,wallet)
|
|
||||||
SELECT * FROM (SELECT '$userID',0) AS tmp
|
|
||||||
WHERE NOT EXISTS (
|
|
||||||
SELECT discordUserID FROM users WHERE discordUserID = '$userID'
|
|
||||||
) LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
*/
|
|
||||||
|
|
||||||
$q = "SELECT id FROM users WHERE discordUserID = '$userID' LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
echo "userAlreadyExists";
|
|
||||||
} else{
|
|
||||||
$q = "INSERT INTO users (discordUserID,wallet)
|
|
||||||
SELECT * FROM (SELECT '$userID',0) AS tmp
|
|
||||||
WHERE NOT EXISTS (
|
|
||||||
SELECT discordUserID FROM users WHERE discordUserID = '$userID'
|
|
||||||
) LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "createdUser";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "checkin":
|
|
||||||
$q = "SELECT id,actionTime FROM userLog WHERE actionTime >= CURDATE() AND actionType = 'checkin' AND discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
//already checked in today.
|
|
||||||
$a = mysqli_fetch_assoc($r2);
|
|
||||||
$flastupdated=stripslashes($a['actionTime']);
|
|
||||||
|
|
||||||
$timeAgoObject = new convertToAgo; // Create an object for the time conversion functions
|
|
||||||
// Query your database here and get timestamp
|
|
||||||
$ts = $flastupdated;
|
|
||||||
$convertedTime = ($timeAgoObject -> convert_datetime($ts)); // Convert Date Time
|
|
||||||
$when = ($timeAgoObject -> makeAgo($convertedTime)); // Then convert to ago time
|
|
||||||
//date("F j, Y, g:i a", strtotime($flastupdated));
|
|
||||||
echo $when;
|
|
||||||
} else{
|
|
||||||
//Can check in.
|
|
||||||
$q = "UPDATE users SET wallet = wallet + $dataToSend WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', 'Checked in for $dataToSend crystals.');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo 1;
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "deposit":
|
|
||||||
$q = "SELECT wallet FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$account=stripslashes($a['wallet']);
|
|
||||||
}
|
|
||||||
if($account >= $dataToSend && $dataToSend > 0){
|
|
||||||
//has enough credits in their account
|
|
||||||
$q = "UPDATE users SET wallet = wallet - $dataToSend WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "UPDATE factions SET account = account + $dataToSend WHERE discordRoleID = '$dataToSend2' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', 'Deposited $dataToSend crystals to $dataToSend2.');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo 1;
|
|
||||||
} else{
|
|
||||||
echo "{ERROR} - Not enough crystals in your account.";
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "{ERROR} - Cant find wallet. Something went wrong.";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "gambleWon":
|
|
||||||
$q = "UPDATE users SET wallet = wallet + $dataToSend WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', 'Gambled and won for $dataToSend crystals.');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo 1;
|
|
||||||
exit;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case "gambleLost":
|
|
||||||
$q = "UPDATE users SET wallet = wallet - $dataToSend WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', 'Gambled and lost for $dataToSend crystals.');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo 1;
|
|
||||||
exit;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "transfer":
|
|
||||||
$q = "UPDATE users SET wallet = wallet - $dataToSend2 WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "UPDATE users SET wallet = wallet + $dataToSend2 WHERE discordUserID = '$dataToSend' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', '$userID gave $dataToSend2 crystals to $dataToSend.');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo 1;
|
|
||||||
exit;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "attack":
|
|
||||||
|
|
||||||
$q = "UPDATE hostiles SET health = health - $dataToSend WHERE id = '$dataToSend2' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "UPDATE users SET stamina = stamina - 1 WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
//$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
//VALUES (" . $userID . ", '" . $dataType . "', '$userID attacked Ravager#$dataToSend2.');";
|
|
||||||
//$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO attackLog (discordUserID, hostileID, damage)
|
|
||||||
VALUES ('$userID','$dataToSend2','$dataToSend');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "SELECT hostiles.health,hostiles.maxHealth,hostiles.speed,hostiles.strength,users.speed as userspeed,users.health as userhealth FROM hostiles,users WHERE hostiles.id = '$dataToSend2' AND users.discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$hostileHealth=stripslashes($a['health']);
|
|
||||||
$hostileMaxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$hostileSpeed=stripslashes($a['speed']);
|
|
||||||
$hostileStrength=stripslashes($a['strength']);
|
|
||||||
$userSpeed=stripslashes($a['userspeed']);
|
|
||||||
$userHealth=stripslashes($a['userhealth']);
|
|
||||||
}
|
|
||||||
if($hostileHealth <= 0){
|
|
||||||
if($hostileHealth < 0){ $hostileHealth = 0;};
|
|
||||||
//returns health less than zero, kill enemy.
|
|
||||||
$q = "UPDATE hostiles SET alive = 0,health = 0 WHERE id = '$dataToSend2' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
$criticalHit = 0;
|
|
||||||
$hitAmount = getEnemyDamage($hostileSpeed,$userSpeed,$hostileStrength);
|
|
||||||
if($hitAmount > 0){
|
|
||||||
if ($hitAmount >= $userHealth){$hitAmount = $userHealth; $criticalHit = 1;};
|
|
||||||
$q = "UPDATE users SET health = health - $hitAmount WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
echo $hostileHealth.",".$hostileMaxHealth.",".$hitAmount.",".$criticalHit;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
exit;
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "hostileAttackBack":
|
|
||||||
|
|
||||||
$q = "UPDATE users SET stamina = stamina - 1 WHERE discordUserID = '$userID' AND stamina > 0 LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
|
|
||||||
$q = "SELECT hostiles.health,hostiles.maxHealth,hostiles.speed,hostiles.strength,users.speed as userspeed,users.health as userhealth FROM hostiles,users WHERE hostiles.id = '$dataToSend2' AND users.discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$hostileHealth=stripslashes($a['health']);
|
|
||||||
$hostileMaxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$hostileSpeed=stripslashes($a['speed']);
|
|
||||||
$hostileStrength=stripslashes($a['strength']);
|
|
||||||
$userSpeed=stripslashes($a['userspeed']);
|
|
||||||
$userHealth=stripslashes($a['userhealth']);
|
|
||||||
}
|
|
||||||
$criticalHit = 0;
|
|
||||||
$hitAmount = getEnemyDamage($hostileSpeed,$userSpeed,$hostileStrength);
|
|
||||||
if($hitAmount > 0){
|
|
||||||
if ($hitAmount >= $userHealth){$hitAmount = $userHealth; $criticalHit = 1;};
|
|
||||||
$q = "UPDATE users SET health = health - $hitAmount WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
echo $hostileHealth.",".$hostileMaxHealth.",".$hitAmount.",".$criticalHit;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
exit;
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "hostileFlee":
|
|
||||||
$q = "SELECT id FROM hostiles WHERE alive = 1 ORDER BY id DESC LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$hostileID=stripslashes($a['id']);
|
|
||||||
}
|
|
||||||
$q = "UPDATE hostiles SET fled = 1,alive=0 WHERE id = '$hostileID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "fled";
|
|
||||||
} else{
|
|
||||||
echo "alreadyDead";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "newHostile":
|
|
||||||
$q = "SELECT id FROM hostiles WHERE alive = 1 LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
echo "notCreated";
|
|
||||||
} else{
|
|
||||||
$elvl = $dataToSend;
|
|
||||||
$healthBase = 50; $strengthBase = 3; $speedBase = 3; $stashBase = 3;
|
|
||||||
$healthMin = ($healthBase * $elvl) / 2; $healthMax = $healthBase * $elvl;
|
|
||||||
$strengthMin = ($strengthBase * $elvl) / 2; $strengthMax = $strengthBase * $elvl;
|
|
||||||
$speedMin = ($speedBase * $elvl) / 2; $speedMax = $speedBase * $elvl;
|
|
||||||
$stashMin = ($stashBase * $elvl) / 2; $stashMax = $stashBase * $elvl;
|
|
||||||
|
|
||||||
$health = floor(rand($healthMin,$healthMax));
|
|
||||||
$strength = floor(rand($strengthMin,$strengthMax));
|
|
||||||
$speed = floor(rand($speedMin,$speedMax));
|
|
||||||
$stash = floor(rand($stashMin,$stashMax));
|
|
||||||
|
|
||||||
$claimID = floor(rand(1000,9999));
|
|
||||||
$q = "INSERT INTO hostiles (hostileType, maxHealth, health, strength, speed, stash, alive, claimID)
|
|
||||||
VALUES ('ravager', '$health', '$health', '$strength', '$speed', '$stash', 1, '$claimID');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo $health.",".$speed.",".$strength.",".$claimID;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "claim":
|
|
||||||
$claimAmount = $dataToSend2;
|
|
||||||
|
|
||||||
|
|
||||||
$q = "SELECT stash FROM hostiles WHERE alive = 0 AND claimID = '$dataToSend' LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$stash=stripslashes($a['stash']);
|
|
||||||
}
|
|
||||||
if($claimAmount <= $stash){
|
|
||||||
//take money from the stash
|
|
||||||
$q = "UPDATE hostiles SET stash = stash - $claimAmount WHERE claimID = '$dataToSend' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "UPDATE users SET wallet = wallet + $claimAmount WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', '$userID claimed $claimAmount crystals from a Ravager.');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$stash = $stash - $claimAmount;
|
|
||||||
if($stash == 0){
|
|
||||||
$q = "UPDATE hostiles SET claimID=0 WHERE claimID = '$dataToSend' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
echo $stash;
|
|
||||||
}else{
|
|
||||||
echo "notEnough";
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "noClaimID";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
exit;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "getHostileData":
|
|
||||||
$q = "SELECT stash,claimID FROM hostiles WHERE alive = 0 AND id = '$dataToSend' LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$stash=stripslashes($a['stash']);
|
|
||||||
$claimID=stripslashes($a['claimID']);
|
|
||||||
}
|
|
||||||
echo $stash.",".$claimID;
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "getDamageDistribution":
|
|
||||||
//Gets base stats for enemy
|
|
||||||
$q = "SELECT stash,maxHealth,fled FROM hostiles WHERE id = '$dataToSend' LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$a = mysqli_fetch_assoc($r2);
|
|
||||||
$stash=stripslashes($a['stash']);
|
|
||||||
$maxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$fled=stripslashes($a['fled']);
|
|
||||||
$totalCrystalsInStash = 0;
|
|
||||||
|
|
||||||
if($fled == 1){
|
|
||||||
echo "fled";
|
|
||||||
}else{
|
|
||||||
//gets all dammage from users
|
|
||||||
$damageDistribution = array();
|
|
||||||
$q = "SELECT discordUserID,SUM(damage) totalDamage FROM attackLog WHERE hostileID = $dataToSend GROUP BY discordUserID;";
|
|
||||||
//$q = "SELECT attackLog.damage,attackLog.discordUserID,hostiles.stash,hostiles.maxHealth FROM attackLog WHERE hostiles.id = attackLog.hostileID AND attackLog.hostileID = '$dataToSend';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$damage=stripslashes($a['totalDamage']);
|
|
||||||
$discordUserID=stripslashes($a['discordUserID']);
|
|
||||||
$damagePercent = round(( $damage / $maxHealth ) * 100);
|
|
||||||
$percentStashAmount = round($stash * ($damagePercent/100));
|
|
||||||
$totalCrystalsInStash += $percentStashAmount;
|
|
||||||
// you can add single array values too
|
|
||||||
$damageDistribution[] = array('id'=>$discordUserID, 'totalDamage'=>$damage, 'damagePercent'=>$damagePercent, 'crystalsReceived'=>$percentStashAmount);
|
|
||||||
if($dataToSend2 == 1){
|
|
||||||
//Flag to actually distribute crystals
|
|
||||||
$q2 = "UPDATE users SET wallet = wallet + $percentStashAmount WHERE discordUserID = '$discordUserID' LIMIT 1";
|
|
||||||
$r3 = mysqli_query($con,$q2);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
echo json_encode($damageDistribution);
|
|
||||||
} else{
|
|
||||||
echo 0;
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case "updateStamina":
|
|
||||||
$q = "UPDATE users SET stamina = stamina + 1 WHERE stamina < maxStamina;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
//UPDATE users SET health = min(floor(health + (maxHeath/100)), maxHealth)
|
|
||||||
$q = "UPDATE users SET health = least(floor(health + (maxHealth/100)), maxHealth) WHERE health < maxHealth AND health > 0;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
exit;
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case "reviveAll":
|
|
||||||
$q = "UPDATE users SET health = 1 WHERE health = 0;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (0,'revive','reviveAll');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
exit;
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case "lvlinfo":
|
|
||||||
$q = "SELECT xp,lvl FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$xp=stripslashes($a['xp']);
|
|
||||||
$currentlvl=stripslashes($a['lvl']);
|
|
||||||
$lvlbase=getLevelBase();
|
|
||||||
$lvl=getLevel($xp,$lvlbase);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//echo "LEVEL: ".getLevel($xp,$lvlbase),"<BR>XP: ".$xp."<BR>CURRENT LEVEL PROGRESS:".getCurrentLevelProgress($xp,$lvl);
|
|
||||||
echo "LEVEL: ".getLevel($dataToSend,$lvlbase),"<BR>XP: ".$xp."<BR>CURRENT LEVEL PROGRESS:".getCurrentLevelProgress($xp,$lvl);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "upgradeStats":
|
|
||||||
//Changed it to just upgrade 1 point automatically
|
|
||||||
$dataToSend2 = 1;
|
|
||||||
$q = "SELECT statPoints FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$statPoints=stripslashes($a['statPoints']);
|
|
||||||
}
|
|
||||||
if($dataToSend2 <= $statPoints){
|
|
||||||
$tableName = "";
|
|
||||||
switch (strtoupper($dataToSend)) {
|
|
||||||
case "STR":
|
|
||||||
$tableName = "strength = strength + ".$dataToSend2;
|
|
||||||
break;
|
|
||||||
case "HP":
|
|
||||||
$tableName = "maxHealth = maxHealth + 10";
|
|
||||||
break;
|
|
||||||
case "SPD":
|
|
||||||
$tableName = "speed = speed + ".$dataToSend2;
|
|
||||||
break;
|
|
||||||
case "STAM":
|
|
||||||
$tableName = "maxStamina = maxStamina + ".$dataToSend2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$q = "UPDATE users SET statPoints = statPoints - $dataToSend2,$tableName WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success";
|
|
||||||
} else{
|
|
||||||
echo "notEnoughPoints";
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
echo "failure";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "heal":
|
|
||||||
$q = "SELECT health,maxHealth,wallet FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$health=stripslashes($a['health']);
|
|
||||||
$maxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$crystals=stripslashes($a['wallet']);
|
|
||||||
}
|
|
||||||
$treatmentCost = $dataToSend;
|
|
||||||
$treatmentName = $dataToSend2;
|
|
||||||
$newHealth = $health;
|
|
||||||
if($health == $maxHealth){echo "fullHealth";exit;}
|
|
||||||
|
|
||||||
if($health > 0){
|
|
||||||
if($crystals >= $treatmentCost){
|
|
||||||
switch ($treatmentName) {
|
|
||||||
case "TREAT":
|
|
||||||
$newHealth += 15;
|
|
||||||
break;
|
|
||||||
case "TREATV2":
|
|
||||||
$newHealth = $maxHealth*0.15;
|
|
||||||
break;
|
|
||||||
case "PATCH":
|
|
||||||
$newHealth += 50;
|
|
||||||
break;
|
|
||||||
case "PATCHV2":
|
|
||||||
$newHealth = $maxHealth*0.5;
|
|
||||||
break;
|
|
||||||
case "REGEN":
|
|
||||||
$newHealth += 100;
|
|
||||||
break;
|
|
||||||
case "REGENV2":
|
|
||||||
$newHealth = $maxHealth;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
echo "cantDoThat";exit;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if($newHealth < $health){echo "lessThanYourHealth";exit;}
|
|
||||||
if($newHealth>$maxHealth){$newHealth = $maxHealth;};
|
|
||||||
$q = "UPDATE users SET health = $newHealth,wallet = wallet - $treatmentCost WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success,".$newHealth."/".$maxHealth;
|
|
||||||
} else{
|
|
||||||
echo "notEnoughCrystals";
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
if($crystals >= $treatmentCost){
|
|
||||||
switch ($treatmentName) {
|
|
||||||
case "REVIVE":
|
|
||||||
$newHealth = 25;
|
|
||||||
break;
|
|
||||||
case "REVIVEV2":
|
|
||||||
$newHealth = $maxHealth*0.5;
|
|
||||||
break;
|
|
||||||
case "REVIVEV3":
|
|
||||||
$newHealth = $maxHealth;
|
|
||||||
break;
|
|
||||||
case "TREAT":
|
|
||||||
echo "youreKnockedOut";exit;
|
|
||||||
break;
|
|
||||||
case "TREATV2":
|
|
||||||
echo "youreKnockedOut";exit;
|
|
||||||
break;
|
|
||||||
case "PATCH":
|
|
||||||
echo "youreKnockedOut";exit;
|
|
||||||
break;
|
|
||||||
case "PATCHV2":
|
|
||||||
echo "youreKnockedOut";exit;
|
|
||||||
break;
|
|
||||||
case "REGEN":
|
|
||||||
echo "youreKnockedOut";exit;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
echo "cantDoThat";exit;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if($newHealth < $health){echo "lessThanYourHealth";exit;}
|
|
||||||
if($newHealth>$maxHealth){$newHealth = $maxHealth;};
|
|
||||||
$q = "UPDATE users SET health = $newHealth,wallet = wallet - $treatmentCost WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success,".$newHealth."/".$maxHealth;
|
|
||||||
}else{
|
|
||||||
echo "notEnoughCrystals";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
echo "failure";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "addXP":
|
|
||||||
addXp($userID,$dataToSend);
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case "getLevelUp":
|
|
||||||
//addXp($userID,$dataToSend);
|
|
||||||
$levelCap = 30;$levelCapXP = 625;
|
|
||||||
$q = "SELECT xp,lvl,statPoints,chests FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$xp=stripslashes($a['xp']);
|
|
||||||
$lvl=stripslashes($a['lvl']);
|
|
||||||
$statPoints=stripslashes($a['statPoints']);
|
|
||||||
$chests=stripslashes($a['chests']);
|
|
||||||
}
|
|
||||||
$lvlbase = getLevelBase();
|
|
||||||
$currentLVL = floor(getLevel($xp,$lvlbase));
|
|
||||||
if($currentLVL > $lvl){
|
|
||||||
if($currentLVL > $levelCap){
|
|
||||||
$chests += 1;
|
|
||||||
$q = "UPDATE users SET lvl = $levelCap,chests = chests + 1,xp = $levelCapXP WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
}else{
|
|
||||||
$statPoints += 1;
|
|
||||||
$q = "UPDATE users SET lvl = lvl + 1,statPoints = statPoints + 1 WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$lvl = $lvl + 1;
|
|
||||||
}
|
|
||||||
echo "levelup,".$lvl.",".$statPoints.",".$statPoints;
|
|
||||||
} else{
|
|
||||||
echo "xpadded,".$currentLVL.",".$statPoints;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case "scavenge":
|
|
||||||
$random = floor(rand(0,101));
|
|
||||||
$ultrarare = 0;$rare = 0; $uncommon = 0; $common = 0; $scrap = 0;
|
|
||||||
if($random <= 0.5){
|
|
||||||
$ultrarare = 1;
|
|
||||||
}
|
|
||||||
if($random <= 3 && $random > 0.5){
|
|
||||||
$rare = round(rand(1,2));
|
|
||||||
}
|
|
||||||
if($random <= 10 && $random > 3){
|
|
||||||
$uncommon = round(rand(1,3));
|
|
||||||
}
|
|
||||||
if($random <= 50 && $random > 10){
|
|
||||||
$common = round(rand(1,3));
|
|
||||||
}
|
|
||||||
if($random > 50){
|
|
||||||
$scrap = round(rand(1,7));
|
|
||||||
}
|
|
||||||
|
|
||||||
$staminaCost = $dataToSend;
|
|
||||||
$crystalCost = $dataToSend2;
|
|
||||||
$q = "UPDATE users SET stamina = stamina - $staminaCost,wallet = wallet - $crystalCost WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "SELECT id FROM artifacts WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
|
|
||||||
$q = "UPDATE artifacts SET scrap = scrap + $scrap,common = common + $common,uncommon = uncommon + $uncommon,rare = rare + $rare,ultrarare = ultrarare + $ultrarare WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success,".$ultrarare.",".$rare.",".$uncommon.",".$common.",".$scrap;
|
|
||||||
} else{
|
|
||||||
$q = "INSERT INTO artifacts (discordUserID, scrap, common, uncommon, rare, ultrarare)
|
|
||||||
VALUES ($userID,$scrap,$common,$uncommon,$rare,$ultrarare);";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success,".$ultrarare.",".$rare.",".$uncommon.",".$common.",".$scrap;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "artifactSell":
|
|
||||||
|
|
||||||
|
|
||||||
$q = "SELECT scrap,common,uncommon,rare,ultrarare FROM artifacts WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
$a = mysqli_fetch_assoc($r2);
|
|
||||||
$scrapQuantity=stripslashes($a['scrap']);
|
|
||||||
$commonQuantity=stripslashes($a['common']);
|
|
||||||
$uncommonQuantity=stripslashes($a['uncommon']);
|
|
||||||
$rareQuantity=stripslashes($a['rare']);
|
|
||||||
$ultrarareQuantity=stripslashes($a['ultrarare']);
|
|
||||||
|
|
||||||
$itemToSell = strtolower ($dataToSend);
|
|
||||||
$price = 0;$totalPayout = 0;$itemQuantity = 0;
|
|
||||||
|
|
||||||
$price = 0.1;
|
|
||||||
$scrapTotalPayout = round($price * $scrapQuantity);
|
|
||||||
$price = 2;
|
|
||||||
$commonTotalPayout = $price * $commonQuantity;
|
|
||||||
$price = 5;
|
|
||||||
$uncommonTotalPayout = $price * $uncommonQuantity;
|
|
||||||
$price = 10;
|
|
||||||
$rareTotalPayout = $price * $rareQuantity;
|
|
||||||
$price = 30;
|
|
||||||
$ultrarareTotalPayout = $price * $ultrarareQuantity;
|
|
||||||
|
|
||||||
$itemQuantity = $scrapQuantity + $commonQuantity + $uncommonQuantity + $rareQuantity + $ultrarareQuantity;
|
|
||||||
$totalPayout = $scrapTotalPayout + $commonTotalPayout + $uncommonTotalPayout + $rareTotalPayout + $ultrarareTotalPayout;
|
|
||||||
|
|
||||||
if($itemToSell == "all"){
|
|
||||||
$q = "UPDATE artifacts SET scrap =0,common = 0,uncommon = 0,rare = 0,ultrarare = 0 WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "UPDATE users SET wallet = wallet + $totalPayout WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success,".$itemQuantity.",".$totalPayout;
|
|
||||||
}else{
|
|
||||||
|
|
||||||
$crystals = 0;
|
|
||||||
switch ($itemToSell) {
|
|
||||||
case "scrap":
|
|
||||||
$singlePayout = $scrapTotalPayout;
|
|
||||||
$itemQuantity = $scrapQuantity;
|
|
||||||
break;
|
|
||||||
case "common":
|
|
||||||
$singlePayout = $commonTotalPayout;
|
|
||||||
$itemQuantity = $commonQuantity;
|
|
||||||
break;
|
|
||||||
case "uncommon":
|
|
||||||
$singlePayout = $uncommonTotalPayout;
|
|
||||||
$itemQuantity = $uncommonQuantity;
|
|
||||||
break;
|
|
||||||
case "rare":
|
|
||||||
$singlePayout = $rareTotalPayout;
|
|
||||||
$itemQuantity = $rareQuantity;
|
|
||||||
break;
|
|
||||||
case "ultrarare":
|
|
||||||
$singlePayout = $ultrarareTotalPayout;
|
|
||||||
$itemQuantity = $ultrarareQuantity;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$q = "UPDATE artifacts SET $itemToSell = 0 WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "UPDATE users SET wallet = wallet + $singlePayout WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success,".$itemQuantity.",".$singlePayout;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
echo "failure";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "buyDrink":
|
|
||||||
$q = "UPDATE users SET wallet = wallet - $dataToSend WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//echo json_encode($array);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if($debug){
|
|
||||||
echo "\n"."UID:".$userID;
|
|
||||||
}
|
|
||||||
|
|
||||||
mysqli_close($con);
|
|
||||||
|
|
||||||
|
|
||||||
function getEnemyDamage($hostileSpeed,$userSpeed,$hostileStrength){
|
|
||||||
$hitAmount = 0;
|
|
||||||
$percentage = floor(rand(0,101));
|
|
||||||
if($hostileSpeed > $userSpeed){
|
|
||||||
if($percentage <= 80 ){
|
|
||||||
//80% chance to hit you back.
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
if($percentage <= 30){
|
|
||||||
//30% chance to hit you back.
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if($hostileSpeed > $userSpeed){
|
|
||||||
if(20 > rand(0,100)){
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
} elseif($hostileSpeed == $userSpeed){
|
|
||||||
if(50 >= rand(0,100)){
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
if(70 >= rand(0,100)){
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return $hitAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
@@ -1,743 +0,0 @@
|
|||||||
<?php
|
|
||||||
//header('Access-Control-Allow-Origin: *');
|
|
||||||
//header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
|
|
||||||
include_once 'functions.php';
|
|
||||||
|
|
||||||
if( isset($_GET['dataType']) ){ $dataType = $_GET['dataType']; } else{ $dataType = ''; };
|
|
||||||
if( isset($_GET['dataToSend']) ){ $dataToSend = $_GET['dataToSend']; } else{ $dataToSend = ''; };
|
|
||||||
if( isset($_GET['dataToSend2']) ){ $dataToSend2 = $_GET['dataToSend2']; } else{ $dataToSend2 = ''; };
|
|
||||||
if( isset($_GET['userid']) ){ $userID = $_GET['userid']; } else{ $userID = ''; };
|
|
||||||
if( isset($_GET['pk']) ){ $privateKey = $_GET['pk']; } else{ $privateKey = ''; };
|
|
||||||
$debug = false;
|
|
||||||
|
|
||||||
if($privateKey != privateKey()){
|
|
||||||
echo throwError("invalidPrivateKey");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$con = mysqlConnect();
|
|
||||||
|
|
||||||
switch ($dataType) {
|
|
||||||
case "conversion":
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', '" . $dataToSend . "');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
break;
|
|
||||||
case "newUser":
|
|
||||||
/*
|
|
||||||
$q = "INSERT INTO users (discordUserID,wallet)
|
|
||||||
SELECT * FROM (SELECT '$userID',0) AS tmp
|
|
||||||
WHERE NOT EXISTS (
|
|
||||||
SELECT discordUserID FROM users WHERE discordUserID = '$userID'
|
|
||||||
) LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
*/
|
|
||||||
|
|
||||||
$q = "SELECT id FROM users WHERE discordUserID = '$userID' LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
echo "userAlreadyExists";
|
|
||||||
} else{
|
|
||||||
$q = "INSERT INTO users (discordUserID,wallet)
|
|
||||||
SELECT * FROM (SELECT '$userID',0) AS tmp
|
|
||||||
WHERE NOT EXISTS (
|
|
||||||
SELECT discordUserID FROM users WHERE discordUserID = '$userID'
|
|
||||||
) LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "createdUser";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "checkin":
|
|
||||||
$q = "SELECT id,actionTime FROM userLog WHERE actionTime >= CURDATE() AND actionType = 'checkin' AND discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
//already checked in today.
|
|
||||||
$a = mysqli_fetch_assoc($r2);
|
|
||||||
$flastupdated=stripslashes($a['actionTime']);
|
|
||||||
|
|
||||||
$timeAgoObject = new convertToAgo; // Create an object for the time conversion functions
|
|
||||||
// Query your database here and get timestamp
|
|
||||||
$ts = $flastupdated;
|
|
||||||
$convertedTime = ($timeAgoObject -> convert_datetime($ts)); // Convert Date Time
|
|
||||||
$when = ($timeAgoObject -> makeAgo($convertedTime)); // Then convert to ago time
|
|
||||||
//date("F j, Y, g:i a", strtotime($flastupdated));
|
|
||||||
echo $when;
|
|
||||||
} else{
|
|
||||||
//Can check in.
|
|
||||||
$q = "UPDATE users SET wallet = wallet + $dataToSend WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', 'Checked in for $dataToSend crystals.');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo 1;
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "deposit":
|
|
||||||
$q = "SELECT wallet FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$account=stripslashes($a['wallet']);
|
|
||||||
}
|
|
||||||
if($account >= $dataToSend && $dataToSend > 0){
|
|
||||||
//has enough credits in their account
|
|
||||||
$q = "UPDATE users SET wallet = wallet - $dataToSend WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "UPDATE factions SET account = account + $dataToSend WHERE discordRoleID = '$dataToSend2' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', 'Deposited $dataToSend crystals to $dataToSend2.');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo 1;
|
|
||||||
} else{
|
|
||||||
echo "{ERROR} - Not enough crystals in your account.";
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "{ERROR} - Cant find wallet. Something went wrong.";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "gambleWon":
|
|
||||||
$q = "UPDATE users SET wallet = wallet + $dataToSend WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', 'Gambled and won for $dataToSend crystals.');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo 1;
|
|
||||||
exit;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case "gambleLost":
|
|
||||||
$q = "UPDATE users SET wallet = wallet - $dataToSend WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', 'Gambled and lost for $dataToSend crystals.');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo 1;
|
|
||||||
exit;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "transfer":
|
|
||||||
$q = "UPDATE users SET wallet = wallet - $dataToSend2 WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "UPDATE users SET wallet = wallet + $dataToSend2 WHERE discordUserID = '$dataToSend' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', '$userID gave $dataToSend2 crystals to $dataToSend.');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo 1;
|
|
||||||
exit;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "attack":
|
|
||||||
|
|
||||||
$q = "UPDATE hostiles SET health = health - $dataToSend WHERE id = '$dataToSend2' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "UPDATE users SET stamina = stamina - 1 WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
//$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
//VALUES (" . $userID . ", '" . $dataType . "', '$userID attacked Ravager#$dataToSend2.');";
|
|
||||||
//$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO attackLog (discordUserID, hostileID, damage)
|
|
||||||
VALUES ('$userID','$dataToSend2','$dataToSend');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "SELECT hostiles.health,hostiles.maxHealth,hostiles.speed,hostiles.strength,users.speed as userspeed,users.health as userhealth FROM hostiles,users WHERE hostiles.id = '$dataToSend2' AND users.discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$hostileHealth=stripslashes($a['health']);
|
|
||||||
$hostileMaxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$hostileSpeed=stripslashes($a['speed']);
|
|
||||||
$hostileStrength=stripslashes($a['strength']);
|
|
||||||
$userSpeed=stripslashes($a['userspeed']);
|
|
||||||
$userHealth=stripslashes($a['userhealth']);
|
|
||||||
}
|
|
||||||
if($hostileHealth <= 0){
|
|
||||||
if($hostileHealth < 0){ $hostileHealth = 0;};
|
|
||||||
//returns health less than zero, kill enemy.
|
|
||||||
$q = "UPDATE hostiles SET alive = 0,health = 0 WHERE id = '$dataToSend2' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
$criticalHit = 0;
|
|
||||||
$hitAmount = getEnemyDamage($hostileSpeed,$userSpeed,$hostileStrength);
|
|
||||||
if($hitAmount > 0){
|
|
||||||
if ($hitAmount >= $userHealth){$hitAmount = $userHealth; $criticalHit = 1;};
|
|
||||||
$q = "UPDATE users SET health = health - $hitAmount WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
echo $hostileHealth.",".$hostileMaxHealth.",".$hitAmount.",".$criticalHit;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
exit;
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "hostileAttackBack":
|
|
||||||
|
|
||||||
$q = "UPDATE users SET stamina = stamina - 1 WHERE discordUserID = '$userID' AND stamina > 0 LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
|
|
||||||
$q = "SELECT hostiles.health,hostiles.maxHealth,hostiles.speed,hostiles.strength,users.speed as userspeed,users.health as userhealth FROM hostiles,users WHERE hostiles.id = '$dataToSend2' AND users.discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$hostileHealth=stripslashes($a['health']);
|
|
||||||
$hostileMaxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$hostileSpeed=stripslashes($a['speed']);
|
|
||||||
$hostileStrength=stripslashes($a['strength']);
|
|
||||||
$userSpeed=stripslashes($a['userspeed']);
|
|
||||||
$userHealth=stripslashes($a['userhealth']);
|
|
||||||
}
|
|
||||||
$criticalHit = 0;
|
|
||||||
$hitAmount = getEnemyDamage($hostileSpeed,$userSpeed,$hostileStrength);
|
|
||||||
if($hitAmount > 0){
|
|
||||||
if ($hitAmount >= $userHealth){$hitAmount = $userHealth; $criticalHit = 1;};
|
|
||||||
$q = "UPDATE users SET health = health - $hitAmount WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
echo $hostileHealth.",".$hostileMaxHealth.",".$hitAmount.",".$criticalHit;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
exit;
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "hostileFlee":
|
|
||||||
$q = "SELECT id FROM hostiles WHERE alive = 1 ORDER BY id DESC LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$hostileID=stripslashes($a['id']);
|
|
||||||
}
|
|
||||||
$q = "UPDATE hostiles SET fled = 1,alive=0 WHERE id = '$hostileID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "fled";
|
|
||||||
} else{
|
|
||||||
echo "alreadyDead";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "newHostile":
|
|
||||||
$q = "SELECT id FROM hostiles WHERE alive = 1 LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
echo "notCreated";
|
|
||||||
} else{
|
|
||||||
$elvl = $dataToSend;
|
|
||||||
$healthBase = 150; $strengthBase = 6; $speedBase = 6; $stashBase = 9;
|
|
||||||
$healthMin = ($healthBase * $elvl) / 2; $healthMax = $healthBase * $elvl;
|
|
||||||
$strengthMin = ($strengthBase * $elvl) / 2; $strengthMax = $strengthBase * $elvl;
|
|
||||||
$speedMin = ($speedBase * $elvl) / 2; $speedMax = $speedBase * $elvl;
|
|
||||||
$stashMin = ($stashBase * $elvl) / 2; $stashMax = $stashBase * $elvl;
|
|
||||||
|
|
||||||
$health = floor(rand($healthMin,$healthMax));
|
|
||||||
$strength = floor(rand($strengthMin,$strengthMax));
|
|
||||||
$speed = floor(rand($speedMin,$speedMax));
|
|
||||||
$stash = floor(rand($stashMin,$stashMax));
|
|
||||||
|
|
||||||
$claimID = floor(rand(1000,9999));
|
|
||||||
$q = "INSERT INTO hostiles (hostileType, maxHealth, health, strength, speed, stash, alive, claimID)
|
|
||||||
VALUES ('ravager', '$health', '$health', '$strength', '$speed', '$stash', 1, '$claimID');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo $health.",".$speed.",".$strength.",".$claimID;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "claim":
|
|
||||||
$claimAmount = $dataToSend2;
|
|
||||||
|
|
||||||
|
|
||||||
$q = "SELECT stash FROM hostiles WHERE alive = 0 AND claimID = '$dataToSend' LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$stash=stripslashes($a['stash']);
|
|
||||||
}
|
|
||||||
if($claimAmount <= $stash){
|
|
||||||
//take money from the stash
|
|
||||||
$q = "UPDATE hostiles SET stash = stash - $claimAmount WHERE claimID = '$dataToSend' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "UPDATE users SET wallet = wallet + $claimAmount WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (" . $userID . ", '" . $dataType . "', '$userID claimed $claimAmount crystals from a Ravager.');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$stash = $stash - $claimAmount;
|
|
||||||
if($stash == 0){
|
|
||||||
$q = "UPDATE hostiles SET claimID=0 WHERE claimID = '$dataToSend' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
echo $stash;
|
|
||||||
}else{
|
|
||||||
echo "notEnough";
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "noClaimID";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
exit;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "getHostileData":
|
|
||||||
$q = "SELECT stash,claimID FROM hostiles WHERE alive = 0 AND id = '$dataToSend' LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$stash=stripslashes($a['stash']);
|
|
||||||
$claimID=stripslashes($a['claimID']);
|
|
||||||
}
|
|
||||||
echo $stash.",".$claimID;
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "getDamageDistribution":
|
|
||||||
//Gets base stats for enemy
|
|
||||||
$q = "SELECT stash,maxHealth,fled FROM hostiles WHERE id = '$dataToSend' LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$a = mysqli_fetch_assoc($r2);
|
|
||||||
$stash=stripslashes($a['stash']);
|
|
||||||
$maxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$fled=stripslashes($a['fled']);
|
|
||||||
$totalCrystalsInStash = 0;
|
|
||||||
|
|
||||||
if($fled == 1){
|
|
||||||
echo "fled";
|
|
||||||
}else{
|
|
||||||
//gets all dammage from users
|
|
||||||
$damageDistribution = array();
|
|
||||||
$q = "SELECT discordUserID,SUM(damage) totalDamage FROM attackLog WHERE hostileID = $dataToSend GROUP BY discordUserID;";
|
|
||||||
//$q = "SELECT attackLog.damage,attackLog.discordUserID,hostiles.stash,hostiles.maxHealth FROM attackLog WHERE hostiles.id = attackLog.hostileID AND attackLog.hostileID = '$dataToSend';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$damage=stripslashes($a['totalDamage']);
|
|
||||||
$discordUserID=stripslashes($a['discordUserID']);
|
|
||||||
$damagePercent = round(( $damage / $maxHealth ) * 100);
|
|
||||||
$percentStashAmount = round($stash * ($damagePercent/100));
|
|
||||||
$totalCrystalsInStash += $percentStashAmount;
|
|
||||||
// you can add single array values too
|
|
||||||
$damageDistribution[] = array('id'=>$discordUserID, 'totalDamage'=>$damage, 'damagePercent'=>$damagePercent, 'crystalsReceived'=>$percentStashAmount);
|
|
||||||
if($dataToSend2 == 1){
|
|
||||||
//Flag to actually distribute crystals
|
|
||||||
$q2 = "UPDATE users SET wallet = wallet + $percentStashAmount WHERE discordUserID = '$discordUserID' LIMIT 1";
|
|
||||||
$r3 = mysqli_query($con,$q2);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
echo json_encode($damageDistribution);
|
|
||||||
} else{
|
|
||||||
echo 0;
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case "updateStamina":
|
|
||||||
$q = "UPDATE users SET stamina = stamina + 1 WHERE stamina < maxStamina;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
//UPDATE users SET health = min(floor(health + (maxHeath/100)), maxHealth)
|
|
||||||
$q = "UPDATE users SET health = least(floor(health + (maxHealth/100)), maxHealth) WHERE health < maxHealth AND health > 0;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
exit;
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case "reviveAll":
|
|
||||||
$q = "UPDATE users SET health = 1 WHERE health = 0;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
VALUES (0,'revive','reviveAll');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
exit;
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case "lvlinfo":
|
|
||||||
$q = "SELECT xp,lvl FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$xp=stripslashes($a['xp']);
|
|
||||||
$currentlvl=stripslashes($a['lvl']);
|
|
||||||
$lvlbase=getLevelBase();
|
|
||||||
$lvl=getLevel($xp,$lvlbase);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
echo "LEVEL: ".getLevel($xp,$lvlbase),"<BR>XP: ".$xp."<BR>CURRENT LEVEL PROGRESS:".getCurrentLevelProgress($xp,$lvl);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "upgradeStats":
|
|
||||||
//Changed it to just upgrade 1 point automatically
|
|
||||||
$dataToSend2 = 1;
|
|
||||||
$q = "SELECT statPoints FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$statPoints=stripslashes($a['statPoints']);
|
|
||||||
}
|
|
||||||
if($dataToSend2 <= $statPoints){
|
|
||||||
$tableName = "";
|
|
||||||
switch (strtoupper($dataToSend)) {
|
|
||||||
case "STR":
|
|
||||||
$tableName = "strength = strength + ".$dataToSend2;
|
|
||||||
break;
|
|
||||||
case "HP":
|
|
||||||
$tableName = "maxHealth = maxHealth + 10";
|
|
||||||
break;
|
|
||||||
case "SPD":
|
|
||||||
$tableName = "speed = speed + ".$dataToSend2;
|
|
||||||
break;
|
|
||||||
case "STAM":
|
|
||||||
$tableName = "maxStamina = maxStamina + ".$dataToSend2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$q = "UPDATE users SET statPoints = statPoints - $dataToSend2,$tableName WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success";
|
|
||||||
} else{
|
|
||||||
echo "notEnoughPoints";
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
echo "failure";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "heal":
|
|
||||||
$q = "SELECT health,maxHealth,wallet FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$health=stripslashes($a['health']);
|
|
||||||
$maxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$crystals=stripslashes($a['wallet']);
|
|
||||||
}
|
|
||||||
$treatmentCost = $dataToSend;
|
|
||||||
$treatmentName = $dataToSend2;
|
|
||||||
$newHealth = $health;
|
|
||||||
if($health == $maxHealth){echo "fullHealth";exit;}
|
|
||||||
|
|
||||||
if($health > 0){
|
|
||||||
if($crystals >= $treatmentCost){
|
|
||||||
switch ($treatmentName) {
|
|
||||||
case "TREAT":
|
|
||||||
$newHealth += 15;
|
|
||||||
break;
|
|
||||||
case "TREATV2":
|
|
||||||
$newHealth = $maxHealth*0.15;
|
|
||||||
break;
|
|
||||||
case "PATCH":
|
|
||||||
$newHealth += 50;
|
|
||||||
break;
|
|
||||||
case "PATCHV2":
|
|
||||||
$newHealth = $maxHealth*0.5;
|
|
||||||
break;
|
|
||||||
case "REGEN":
|
|
||||||
$newHealth += 100;
|
|
||||||
break;
|
|
||||||
case "REGENV2":
|
|
||||||
$newHealth = $maxHealth;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
echo "cantDoThat";exit;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if($newHealth < $health){echo "lessThanYourHealth";exit;}
|
|
||||||
if($newHealth>$maxHealth){$newHealth = $maxHealth;};
|
|
||||||
$q = "UPDATE users SET health = $newHealth,wallet = wallet - $treatmentCost WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success,".$newHealth."/".$maxHealth;
|
|
||||||
} else{
|
|
||||||
echo "notEnoughCrystals";
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
if($crystals >= $treatmentCost){
|
|
||||||
switch ($treatmentName) {
|
|
||||||
case "REVIVE":
|
|
||||||
$newHealth = 25;
|
|
||||||
break;
|
|
||||||
case "REVIVEV2":
|
|
||||||
$newHealth = $maxHealth*0.5;
|
|
||||||
break;
|
|
||||||
case "REVIVEV3":
|
|
||||||
$newHealth = $maxHealth;
|
|
||||||
break;
|
|
||||||
case "TREAT":
|
|
||||||
echo "youreKnockedOut";exit;
|
|
||||||
break;
|
|
||||||
case "TREATV2":
|
|
||||||
echo "youreKnockedOut";exit;
|
|
||||||
break;
|
|
||||||
case "PATCH":
|
|
||||||
echo "youreKnockedOut";exit;
|
|
||||||
break;
|
|
||||||
case "PATCHV2":
|
|
||||||
echo "youreKnockedOut";exit;
|
|
||||||
break;
|
|
||||||
case "REGEN":
|
|
||||||
echo "youreKnockedOut";exit;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
echo "cantDoThat";exit;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if($newHealth < $health){echo "lessThanYourHealth";exit;}
|
|
||||||
if($newHealth>$maxHealth){$newHealth = $maxHealth;};
|
|
||||||
$q = "UPDATE users SET health = $newHealth,wallet = wallet - $treatmentCost WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success,".$newHealth."/".$maxHealth;
|
|
||||||
}else{
|
|
||||||
echo "notEnoughCrystals";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
echo "failure";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "addXP":
|
|
||||||
addXp($userID,$dataToSend);
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case "getLevelUp":
|
|
||||||
//addXp($userID,$dataToSend);
|
|
||||||
$q = "SELECT xp,lvl,statPoints FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$xp=stripslashes($a['xp']);
|
|
||||||
$lvl=stripslashes($a['lvl']);
|
|
||||||
$statPoints=stripslashes($a['statPoints']);
|
|
||||||
}
|
|
||||||
$lvlbase = getLevelBase();
|
|
||||||
$currentLVL = floor(getLevel($xp,$lvlbase));
|
|
||||||
if($currentLVL > $lvl){
|
|
||||||
$statPoints += 1;
|
|
||||||
$q = "UPDATE users SET lvl = lvl + 1,statPoints = statPoints + 1 WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$lvl = $lvl + 1;
|
|
||||||
echo "levelup,".$lvl.",".$statPoints;
|
|
||||||
} else{
|
|
||||||
echo "xpadded,".$currentLVL.",".$statPoints;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case "scavenge":
|
|
||||||
$random = floor(rand(0,101));
|
|
||||||
$ultrarare = 0;$rare = 0; $uncommon = 0; $common = 0; $scrap = 0;
|
|
||||||
if($random <= 0.5){
|
|
||||||
$ultrarare = 1;
|
|
||||||
}
|
|
||||||
if($random <= 3 && $random > 0.5){
|
|
||||||
$rare = round(rand(1,2));
|
|
||||||
}
|
|
||||||
if($random <= 10 && $random > 3){
|
|
||||||
$uncommon = round(rand(1,3));
|
|
||||||
}
|
|
||||||
if($random <= 50 && $random > 10){
|
|
||||||
$common = round(rand(1,3));
|
|
||||||
}
|
|
||||||
if($random > 50){
|
|
||||||
$scrap = round(rand(1,7));
|
|
||||||
}
|
|
||||||
|
|
||||||
$staminaCost = $dataToSend;
|
|
||||||
$crystalCost = $dataToSend2;
|
|
||||||
$q = "UPDATE users SET stamina = stamina - $staminaCost,wallet = wallet - $crystalCost WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "SELECT id FROM artifacts WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
|
|
||||||
$q = "UPDATE artifacts SET scrap = scrap + $scrap,common = common + $common,uncommon = uncommon + $uncommon,rare = rare + $rare,ultrarare = ultrarare + $ultrarare WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success,".$ultrarare.",".$rare.",".$uncommon.",".$common.",".$scrap;
|
|
||||||
} else{
|
|
||||||
$q = "INSERT INTO artifacts (discordUserID, scrap, common, uncommon, rare, ultrarare)
|
|
||||||
VALUES ($userID,$scrap,$common,$uncommon,$rare,$ultrarare);";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success,".$ultrarare.",".$rare.",".$uncommon.",".$common.",".$scrap;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "artifactSell":
|
|
||||||
|
|
||||||
|
|
||||||
$q = "SELECT scrap,common,uncommon,rare,ultrarare FROM artifacts WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
$a = mysqli_fetch_assoc($r2);
|
|
||||||
$scrapQuantity=stripslashes($a['scrap']);
|
|
||||||
$commonQuantity=stripslashes($a['common']);
|
|
||||||
$uncommonQuantity=stripslashes($a['uncommon']);
|
|
||||||
$rareQuantity=stripslashes($a['rare']);
|
|
||||||
$ultrarareQuantity=stripslashes($a['ultrarare']);
|
|
||||||
|
|
||||||
$itemToSell = strtolower ($dataToSend);
|
|
||||||
$price = 0;$totalPayout = 0;$itemQuantity = 0;
|
|
||||||
|
|
||||||
$price = 0.1;
|
|
||||||
$scrapTotalPayout = round($price * $scrapQuantity);
|
|
||||||
$price = 2;
|
|
||||||
$commonTotalPayout = $price * $commonQuantity;
|
|
||||||
$price = 5;
|
|
||||||
$uncommonTotalPayout = $price * $uncommonQuantity;
|
|
||||||
$price = 10;
|
|
||||||
$rareTotalPayout = $price * $rareQuantity;
|
|
||||||
$price = 30;
|
|
||||||
$ultrarareTotalPayout = $price * $ultrarareQuantity;
|
|
||||||
|
|
||||||
$itemQuantity = $scrapQuantity + $commonQuantity + $uncommonQuantity + $rareQuantity + $ultrarareQuantity;
|
|
||||||
$totalPayout = $scrapTotalPayout + $commonTotalPayout + $uncommonTotalPayout + $rareTotalPayout + $ultrarareTotalPayout;
|
|
||||||
|
|
||||||
if($itemToSell == "all"){
|
|
||||||
$q = "UPDATE artifacts SET scrap =0,common = 0,uncommon = 0,rare = 0,ultrarare = 0 WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "UPDATE users SET wallet = wallet + $totalPayout WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success,".$itemQuantity.",".$totalPayout;
|
|
||||||
}else{
|
|
||||||
|
|
||||||
$crystals = 0;
|
|
||||||
switch ($itemToSell) {
|
|
||||||
case "scrap":
|
|
||||||
$singlePayout = $scrapTotalPayout;
|
|
||||||
$itemQuantity = $scrapQuantity;
|
|
||||||
break;
|
|
||||||
case "common":
|
|
||||||
$singlePayout = $commonTotalPayout;
|
|
||||||
$itemQuantity = $commonQuantity;
|
|
||||||
break;
|
|
||||||
case "uncommon":
|
|
||||||
$singlePayout = $uncommonTotalPayout;
|
|
||||||
$itemQuantity = $uncommonQuantity;
|
|
||||||
break;
|
|
||||||
case "rare":
|
|
||||||
$singlePayout = $rareTotalPayout;
|
|
||||||
$itemQuantity = $rareQuantity;
|
|
||||||
break;
|
|
||||||
case "ultrarare":
|
|
||||||
$singlePayout = $ultrarareTotalPayout;
|
|
||||||
$itemQuantity = $ultrarareQuantity;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$q = "UPDATE artifacts SET $itemToSell = 0 WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "UPDATE users SET wallet = wallet + $singlePayout WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "success,".$itemQuantity.",".$singlePayout;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
echo "failure";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "buyDrink":
|
|
||||||
$q = "UPDATE users SET wallet = wallet - $dataToSend WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//echo json_encode($array);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if($debug){
|
|
||||||
echo "\n"."UID:".$userID;
|
|
||||||
}
|
|
||||||
|
|
||||||
mysqli_close($con);
|
|
||||||
|
|
||||||
|
|
||||||
function getEnemyDamage($hostileSpeed,$userSpeed,$hostileStrength){
|
|
||||||
$hitAmount = 0;
|
|
||||||
$percentage = floor(rand(0,101));
|
|
||||||
if($hostileSpeed > $userSpeed){
|
|
||||||
if($percentage <= 80 ){
|
|
||||||
//80% chance to hit you back.
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
if($percentage <= 30){
|
|
||||||
//30% chance to hit you back.
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if($hostileSpeed > $userSpeed){
|
|
||||||
if(20 > rand(0,100)){
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
} elseif($hostileSpeed == $userSpeed){
|
|
||||||
if(50 >= rand(0,100)){
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
if(70 >= rand(0,100)){
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return $hitAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
@@ -1,400 +0,0 @@
|
|||||||
<?php
|
|
||||||
//header('Access-Control-Allow-Origin: *');
|
|
||||||
//header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
|
|
||||||
include_once 'functions.php';
|
|
||||||
|
|
||||||
if( isset($_GET['dataType']) ){ $dataType = $_GET['dataType']; } else{ $dataType = ''; };
|
|
||||||
if( isset($_GET['dataToSend']) ){ $dataToSend = $_GET['dataToSend']; } else{ $dataToSend = ''; };
|
|
||||||
if( isset($_GET['dataToSend2']) ){ $dataToSend2 = $_GET['dataToSend2']; } else{ $dataToSend2 = ''; };
|
|
||||||
if( isset($_GET['userid']) ){ $userID = $_GET['userid']; } else{ $userID = ''; };
|
|
||||||
if( isset($_GET['pk']) ){ $privateKey = $_GET['pk']; } else{ $privateKey = ''; };
|
|
||||||
$debug = false;
|
|
||||||
|
|
||||||
if($privateKey != privateKey()){
|
|
||||||
echo throwError("invalidPrivateKey");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$con = mysqlConnect();
|
|
||||||
|
|
||||||
switch ($dataType) {
|
|
||||||
|
|
||||||
|
|
||||||
//gets all dammage from users
|
|
||||||
|
|
||||||
|
|
||||||
case "sendAllAttacks":
|
|
||||||
$message = "";
|
|
||||||
$playerIDs = explode("|", $dataToSend);
|
|
||||||
$hostileType = $dataToSend2;
|
|
||||||
|
|
||||||
if (is_array($playerIDs)){
|
|
||||||
foreach($playerIDs as $item) {
|
|
||||||
$message .= "discordUserID = '".$item."' OR ";
|
|
||||||
}
|
|
||||||
$message = substr($message, 0, -4);
|
|
||||||
//echo json_encode($playerIDs);
|
|
||||||
//Get all user data
|
|
||||||
$attackerStats= array();
|
|
||||||
$q = "SELECT discordUserID,speed,maxHealth,health,strength FROM users WHERE $message;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$discordUserID=stripslashes($a['discordUserID']);
|
|
||||||
$userHealth=stripslashes($a['health']);
|
|
||||||
$userMaxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$userSpeed=stripslashes($a['speed']);
|
|
||||||
$userStrength=stripslashes($a['strength']);
|
|
||||||
$attackerStats[] = array('id'=>$discordUserID, 'maxHealth'=>$userHealth, 'health'=>$userHealth, 'speed'=>$userSpeed, 'strength'=>$userStrength, 'hitback'=>'');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Get enemy data
|
|
||||||
$q = "SELECT hostiles.health,hostiles.maxHealth,hostiles.speed,hostiles.strength,hostiles.alive,hostiles.fled FROM hostiles WHERE hostileType = '$hostileType' ORDER BY id DESC LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$hostileHealth=stripslashes($a['health']);
|
|
||||||
$hostileMaxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$hostileSpeed=stripslashes($a['speed']);
|
|
||||||
$hostileStrength=stripslashes($a['strength']);
|
|
||||||
$hostileAlive=stripslashes($a['alive']);
|
|
||||||
$hostileFled=stripslashes($a['fled']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//do all the damage
|
|
||||||
$totalDamage = 0;
|
|
||||||
$returnInfo= array();
|
|
||||||
$query = "UPDATE users SET health = CASE discordUserID ";
|
|
||||||
$queryIDs = "";
|
|
||||||
for ($i=0;$i<count($attackerStats);$i++){
|
|
||||||
//$message += $attackerStats[$i][0];
|
|
||||||
//If bad guy is still alive, carry on.
|
|
||||||
if($hostileHealth > $attackerStats[$i]['strength']){
|
|
||||||
$totalDamage = $totalDamage + $attackerStats[$i]['strength'];
|
|
||||||
$hitAmount = getEnemyDamage($hostileSpeed,$attackerStats[$i]['speed'],$hostileStrength);
|
|
||||||
if($hitAmount > 0){
|
|
||||||
if ($hitAmount >= $attackerStats[$i]['health']){$hitAmount = $attackerStats[$i]['health'];};
|
|
||||||
$attackerStats[$i]['health'] = $attackerStats[$i]['health'] - $hitAmount;
|
|
||||||
$attackerStats[$i]['hitback'] = $hitAmount;
|
|
||||||
//$q = "UPDATE users SET health = health - $hitAmount WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
//$r2 = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
$query .= " WHEN ".$attackerStats[$i]['id']." THEN ".$attackerStats[$i]['health'];
|
|
||||||
$queryIDs .= $attackerStats[$i]['id'].",";
|
|
||||||
$hhealth = $hostileHealth-$totalDamage;
|
|
||||||
$returnInfo[] = array('hostileHealth'=>$hhealth.'|'.$hostileMaxHealth, 'atkDamage'=>$attackerStats[$i]['strength'], 'id'=>$attackerStats[$i]['id'], 'hitback'=>$hitAmount, 'userHealth'=>$attackerStats[$i]['health']."|".$attackerStats[$i]['maxHealth']);
|
|
||||||
}else{
|
|
||||||
//If the bad guy is not alive, finish up.
|
|
||||||
$q = "UPDATE hostiles SET health = 0 WHERE hostileType = '$hostileType' ORDER BY id DESC LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$query .= " END
|
|
||||||
WHERE discordUserID IN (".substr($queryIDs, 0, -1).");";
|
|
||||||
$r2 = mysqli_query($con,$query);
|
|
||||||
echo json_encode($returnInfo);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//assemble the end of the query.
|
|
||||||
$query .= " END
|
|
||||||
WHERE discordUserID IN (".substr($queryIDs, 0, -1).");";
|
|
||||||
$r2 = mysqli_query($con,$query);
|
|
||||||
$q = "UPDATE hostiles SET health = health - $totalDamage WHERE hostileType = '$hostileType' ORDER BY id DESC LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo json_encode($returnInfo);
|
|
||||||
exit;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}else{
|
|
||||||
echo "notArray";
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case "lvlinfo":
|
|
||||||
$q = "SELECT xp,lvl FROM users WHERE discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$xp=stripslashes($a['xp']);
|
|
||||||
$currentlvl=stripslashes($a['lvl']);
|
|
||||||
$lvlbase=getLevelBase();
|
|
||||||
$lvl=getLevel($xp,$lvlbase);
|
|
||||||
$level = $dataToSend2;
|
|
||||||
$str = generateStatFromLevel($level,"str");
|
|
||||||
$spd = generateStatFromLevel($level,"spd");
|
|
||||||
$hp = generateStatFromLevel($level,"hp");
|
|
||||||
$stash = generateStatFromLevel($level,"stash");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//echo "LEVEL: ".getLevel($xp,$lvlbase),"<BR>XP: ".$xp."<BR>CURRENT LEVEL PROGRESS:".getCurrentLevelProgress($xp,$lvl);
|
|
||||||
echo "LEVEL: ".getLevel($dataToSend,$lvlbase),"<BR>XP: ".$xp."<BR>CURRENT LEVEL PROGRESS:".getCurrentLevelProgress($xp,$lvl)."<BR><BR>STR: ".$str." SPD: ".$spd." HP: ".$hp." STASH:: ".$stash;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "attack":
|
|
||||||
|
|
||||||
$q = "UPDATE hostiles SET health = health - $dataToSend WHERE id = '$dataToSend2' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$q = "UPDATE users SET stamina = stamina - 1 WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
//$q = "INSERT INTO userLog (discordUserID, actionType, actionData)
|
|
||||||
//VALUES (" . $userID . ", '" . $dataType . "', '$userID attacked Ravager#$dataToSend2.');";
|
|
||||||
//$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "INSERT INTO attackLog (discordUserID, hostileID, damage)
|
|
||||||
VALUES ('$userID','$dataToSend2','$dataToSend');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
$q = "SELECT hostiles.health,hostiles.maxHealth,hostiles.speed,hostiles.strength,users.speed as userspeed,users.health as userhealth FROM hostiles,users WHERE hostiles.id = '$dataToSend2' AND users.discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$hostileHealth=stripslashes($a['health']);
|
|
||||||
$hostileMaxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$hostileSpeed=stripslashes($a['speed']);
|
|
||||||
$hostileStrength=stripslashes($a['strength']);
|
|
||||||
$userSpeed=stripslashes($a['userspeed']);
|
|
||||||
$userHealth=stripslashes($a['userhealth']);
|
|
||||||
}
|
|
||||||
if($hostileHealth <= 0){
|
|
||||||
if($hostileHealth < 0){ $hostileHealth = 0;};
|
|
||||||
//returns health less than zero, kill enemy.
|
|
||||||
$q = "UPDATE hostiles SET alive = 0,health = 0 WHERE id = '$dataToSend2' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
$criticalHit = 0;
|
|
||||||
$hitAmount = getEnemyDamage($hostileSpeed,$userSpeed,$hostileStrength);
|
|
||||||
if($hitAmount > 0){
|
|
||||||
if ($hitAmount >= $userHealth){$hitAmount = $userHealth; $criticalHit = 1;};
|
|
||||||
$q = "UPDATE users SET health = health - $hitAmount WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
echo $hostileHealth.",".$hostileMaxHealth.",".$hitAmount.",".$criticalHit;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
exit;
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "hostileAttackBack":
|
|
||||||
|
|
||||||
$q = "UPDATE users SET stamina = stamina - 1 WHERE discordUserID = '$userID' AND stamina > 0 LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
|
|
||||||
|
|
||||||
$q = "SELECT hostiles.health,hostiles.maxHealth,hostiles.speed,hostiles.strength,users.speed as userspeed,users.health as userhealth FROM hostiles,users WHERE hostiles.id = '$dataToSend2' AND users.discordUserID = '$userID';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$hostileHealth=stripslashes($a['health']);
|
|
||||||
$hostileMaxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$hostileSpeed=stripslashes($a['speed']);
|
|
||||||
$hostileStrength=stripslashes($a['strength']);
|
|
||||||
$userSpeed=stripslashes($a['userspeed']);
|
|
||||||
$userHealth=stripslashes($a['userhealth']);
|
|
||||||
}
|
|
||||||
$criticalHit = 0;
|
|
||||||
$hitAmount = getEnemyDamage($hostileSpeed,$userSpeed,$hostileStrength);
|
|
||||||
if($hitAmount > 0){
|
|
||||||
if ($hitAmount >= $userHealth){$hitAmount = $userHealth; $criticalHit = 1;};
|
|
||||||
$q = "UPDATE users SET health = health - $hitAmount WHERE discordUserID = '$userID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
}
|
|
||||||
echo $hostileHealth.",".$hostileMaxHealth.",".$hitAmount.",".$criticalHit;
|
|
||||||
exit;
|
|
||||||
} else{
|
|
||||||
echo "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
exit;
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "hostileFlee":
|
|
||||||
$q = "SELECT id FROM hostiles WHERE alive = 1 ORDER BY id DESC LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$hostileID=stripslashes($a['id']);
|
|
||||||
}
|
|
||||||
$q = "UPDATE hostiles SET fled = 1,alive=0 WHERE id = '$hostileID' LIMIT 1";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo "fled";
|
|
||||||
} else{
|
|
||||||
echo "alreadyDead";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "newHostile":
|
|
||||||
$q = "SELECT id FROM hostiles WHERE alive = 1 LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
echo "notCreated";
|
|
||||||
} else{
|
|
||||||
$elvl = $dataToSend;
|
|
||||||
$healthBase = 50; $strengthBase = 3; $speedBase = 3; $stashBase = 3;
|
|
||||||
$healthMin = ($healthBase * $elvl) / 2; $healthMax = $healthBase * $elvl;
|
|
||||||
$strengthMin = ($strengthBase * $elvl) / 2; $strengthMax = $strengthBase * $elvl;
|
|
||||||
$speedMin = ($speedBase * $elvl) / 2; $speedMax = $speedBase * $elvl;
|
|
||||||
$stashMin = ($stashBase * $elvl) / 2; $stashMax = $stashBase * $elvl;
|
|
||||||
|
|
||||||
$health = floor(rand($healthMin,$healthMax));
|
|
||||||
$strength = floor(rand($strengthMin,$strengthMax));
|
|
||||||
$speed = floor(rand($speedMin,$speedMax));
|
|
||||||
$stash = floor(rand($stashMin,$stashMax));
|
|
||||||
|
|
||||||
$claimID = floor(rand(1000,9999));
|
|
||||||
$q = "INSERT INTO hostiles (hostileType, maxHealth, health, strength, speed, stash, alive, claimID)
|
|
||||||
VALUES ('ravager', '$health', '$health', '$strength', '$speed', '$stash', 1, '$claimID');";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
echo $health.",".$speed.",".$strength.",".$claimID;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "getHostileData":
|
|
||||||
$q = "SELECT stash,claimID FROM hostiles WHERE alive = 0 AND id = '$dataToSend' LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$stash=stripslashes($a['stash']);
|
|
||||||
$claimID=stripslashes($a['claimID']);
|
|
||||||
}
|
|
||||||
echo $stash.",".$claimID;
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "getDamageDistribution":
|
|
||||||
//Gets base stats for enemy
|
|
||||||
$q = "SELECT stash,maxHealth,fled FROM hostiles WHERE id = '$dataToSend' LIMIT 1;";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
$a = mysqli_fetch_assoc($r2);
|
|
||||||
$stash=stripslashes($a['stash']);
|
|
||||||
$maxHealth=stripslashes($a['maxHealth']);
|
|
||||||
$fled=stripslashes($a['fled']);
|
|
||||||
$totalCrystalsInStash = 0;
|
|
||||||
|
|
||||||
if($fled == 1){
|
|
||||||
echo "fled";
|
|
||||||
}else{
|
|
||||||
//gets all dammage from users
|
|
||||||
$damageDistribution = array();
|
|
||||||
$q = "SELECT discordUserID,SUM(damage) totalDamage FROM attackLog WHERE hostileID = $dataToSend GROUP BY discordUserID;";
|
|
||||||
//$q = "SELECT attackLog.damage,attackLog.discordUserID,hostiles.stash,hostiles.maxHealth FROM attackLog WHERE hostiles.id = attackLog.hostileID AND attackLog.hostileID = '$dataToSend';";
|
|
||||||
$r2 = mysqli_query($con,$q);
|
|
||||||
if ( $r2 !== false && mysqli_num_rows($r2) > 0 ) {
|
|
||||||
while ( $a = mysqli_fetch_assoc($r2) ) {
|
|
||||||
$damage=stripslashes($a['totalDamage']);
|
|
||||||
$discordUserID=stripslashes($a['discordUserID']);
|
|
||||||
$damagePercent = round(( $damage / $maxHealth ) * 100);
|
|
||||||
$percentStashAmount = round($stash * ($damagePercent/100));
|
|
||||||
$totalCrystalsInStash += $percentStashAmount;
|
|
||||||
// you can add single array values too
|
|
||||||
$damageDistribution[] = array('id'=>$discordUserID, 'totalDamage'=>$damage, 'damagePercent'=>$damagePercent, 'crystalsReceived'=>$percentStashAmount);
|
|
||||||
if($dataToSend2 == 1){
|
|
||||||
//Flag to actually distribute crystals
|
|
||||||
$q2 = "UPDATE users SET wallet = wallet + $percentStashAmount WHERE discordUserID = '$discordUserID' LIMIT 1";
|
|
||||||
$r3 = mysqli_query($con,$q2);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
echo json_encode($damageDistribution);
|
|
||||||
} else{
|
|
||||||
echo 0;
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//echo json_encode($array);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if($debug){
|
|
||||||
echo "\n"."UID:".$userID;
|
|
||||||
}
|
|
||||||
|
|
||||||
mysqli_close($con);
|
|
||||||
|
|
||||||
|
|
||||||
function getEnemyDamage($hostileSpeed,$userSpeed,$hostileStrength){
|
|
||||||
$hitAmount = 0;
|
|
||||||
$percentage = floor(rand(0,101));
|
|
||||||
if($hostileSpeed > $userSpeed){
|
|
||||||
if($percentage <= 80 ){
|
|
||||||
//80% chance to hit you back.
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
if($percentage <= 30){
|
|
||||||
//30% chance to hit you back.
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if($hostileSpeed > $userSpeed){
|
|
||||||
if(20 > rand(0,100)){
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
} elseif($hostileSpeed == $userSpeed){
|
|
||||||
if(50 >= rand(0,100)){
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
if(70 >= rand(0,100)){
|
|
||||||
$hitAmount = $hostileStrength + rand(-($hostileStrength/4),$hostileStrength/4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return $hitAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function generateStatFromLevel($level,$stat){
|
|
||||||
$value = 0;
|
|
||||||
if(strtolower($stat) === "str"){
|
|
||||||
$value = (round((((($level + 1) * log10($level + 1)) / (0.02 * ($level + 1))) + 0.6) * 0.4)) -2;
|
|
||||||
$value = round($value + (rand(-$value/10,$value/10)));
|
|
||||||
if($level < 15){$value = round($value * 0.9);};
|
|
||||||
}elseif(strtolower($stat) === "spd"){
|
|
||||||
$value = (round((((($level + 1) * log10($level + 1)) / (0.02 * ($level + 1))) + 0.6) * 0.4)) -2 ; //round(rand(-2,2))
|
|
||||||
$value = round($value + (rand(-$value/10,$value/10)));
|
|
||||||
if($level < 15){$value = round($value * 0.9);};
|
|
||||||
}elseif(strtolower($stat) === "hp"){
|
|
||||||
$value = floor(50 + (30 * $level) + pow($level, 1.5));
|
|
||||||
}elseif(strtolower($stat) === "stash"){
|
|
||||||
$value = (round((((($level + 1) * log10($level + 1)) / (0.02 * ($level + 1))) + 0.6) * 0.1)) ;
|
|
||||||
$value = rand(pow($value, 2.2),pow($value, 2.3));
|
|
||||||
if($level < 15){$value = round($value * 0.7);};
|
|
||||||
}
|
|
||||||
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
54
README.md
54
README.md
@@ -1,57 +1,11 @@
|
|||||||
#  SANCTUM
|
#  SANCTUM
|
||||||
[](https://discord.gg/D7dyrVn)
|
|
||||||
[](https://discord.gg/mP98ZYv)
|
|
||||||
# What is SANCTUM?
|
|
||||||
SANCTUM is an open-source Discord MMO, with 200+ players.
|
|
||||||
|
|
||||||
- [Discord Game Invite Link](https://discord.gg/D7dyrVn)
|
[](https://discord.gg/uUEQVwt)
|
||||||
- [Developer's Discord](https://discord.gg/mP98ZYv)
|
|
||||||
|
|
||||||
# Run the Bots
|
This is a hard-fork of SANCTUM by Tim Ruswick and the Game Dev Underground crew. For a rough guide on how to install and run this software, it's recommended that you refer to the original REAMDE.md in the original branch:
|
||||||
## Requirements:
|
|
||||||
You will need:
|
|
||||||
- [Node.js](https://nodejs.org/en/) (recommended v8.12.0 LTS)
|
|
||||||
|
|
||||||
## Steps
|
[TimRuswick/SANCTUM](https://github.com/TimRuswick/SANCTUM)
|
||||||
1. Clone the repo.
|
|
||||||
|
|
||||||
You can use programs like [Git](https://git-scm.com/), [SourceTree](https://www.sourcetreeapp.com/) or simply download the project, although you won't be able to submit changes as easily.
|
TODO: A more official guide is coming soon.
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/TimRuswick/SANCTUM
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Rename the `.envdev` file to `.env`, and fill out tokens and channels.
|
|
||||||
|
|
||||||
Make sure you save it, and also don't push any of your tokens here! If you do though, consider them compromised and then reset them. On Windows, you must give the .env file a name, but you can circumvent it by using a program like [VS Code](https://code.visualstudio.com/) to rename files!
|
|
||||||
|
|
||||||
3. Navigate via command-line to a bot's folder, install dependencies, and run it!
|
|
||||||
|
|
||||||
Make sure you're in the project folder!
|
|
||||||
On Windows, you can hold Shift and Right Click the folder to get the option of a command prompt, inside that folder.
|
|
||||||
```bash
|
|
||||||
cd "SANCTUM" # Navigate to project folder
|
|
||||||
npm i # For modules dependencies
|
|
||||||
cd "A.D.A.M." # Choose a bot
|
|
||||||
npm i # Install dependencies
|
|
||||||
node adam.js # Run the bot
|
|
||||||
```
|
|
||||||
|
|
||||||
4. ???
|
|
||||||
|
|
||||||
5. Profit! You did it, unless something has happened along the way. ~~Developer luck says yes.~~
|
|
||||||
|
|
||||||
## Quality of Life
|
|
||||||
|
|
||||||
We recommend [nodemon](https://nodemon.io/) for reloading bots automatically, instead of `Ctrl+C`ing in and out of bots when you need a restart.
|
|
||||||
|
|
||||||
# Join the SANCTUM Development Team
|
|
||||||
We're looking for:
|
|
||||||
- Discord.js programmers
|
|
||||||
- Artists
|
|
||||||
- Writers
|
|
||||||
- Designers
|
|
||||||
- Producers
|
|
||||||
- and Testers!
|
|
||||||
|
|
||||||
Join the [SANCTUM Developers](https://discord.gg/mP98ZYv) Discord for more info!
|
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "sanctum-deploypackage",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"description": "Universal package for all SANCTUM bots, using pm2.",
|
|
||||||
"main": "rey.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "echo \"Error: you need to use the bot name as a command.\" && exit 1",
|
|
||||||
"alexis": "pm2 start alexis.js -i max --watch",
|
|
||||||
"graze": "pm2 start graze.js -i max --watch",
|
|
||||||
"librarian": "pm2 start librarian.js -i max --watch",
|
|
||||||
"mainframe": "pm2 start mainframe.js -i max --watch",
|
|
||||||
"mori": "pm2 start mori.js -i max --watch",
|
|
||||||
"mosiah": "pm2 start mosiah.js -i max --watch",
|
|
||||||
"ravager": "pm2 start ravager.js -i max --watch",
|
|
||||||
"rey": "pm2 start rey.js -i max --watch",
|
|
||||||
"troll": "pm2 start troll.js -i max --watch"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2",
|
|
||||||
"dotenv": "^6.0.0",
|
|
||||||
"express": "^4.16.3",
|
|
||||||
"node-cron": "^1.2.1",
|
|
||||||
"socket.io": "^2.1.1",
|
|
||||||
"socket.io-request": "^0.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
279
Rey/rey.js
279
Rey/rey.js
@@ -1,279 +0,0 @@
|
|||||||
// .env Variables
|
|
||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
// Node Modules
|
|
||||||
const Discord = require('discord.js');
|
|
||||||
const client = new Discord.Client();
|
|
||||||
const cron = require('node-cron');
|
|
||||||
const request = require('sync-request');
|
|
||||||
|
|
||||||
// Bot Modules
|
|
||||||
const dataRequest = require('../modules/dataRequest');
|
|
||||||
const calcRandom = require('../modules/calcRandom');
|
|
||||||
|
|
||||||
// State Machine
|
|
||||||
var ReyEnumState = {
|
|
||||||
WAITING: 0,
|
|
||||||
SCAVENGING: 1
|
|
||||||
}
|
|
||||||
var reyState = ReyEnumState.WAITING;
|
|
||||||
|
|
||||||
// The ready event is vital, it means that your bot will only start reacting to information
|
|
||||||
// from Discord _after_ ready is emitted
|
|
||||||
client.on('ready', async () => {
|
|
||||||
// Generates invite link
|
|
||||||
try {
|
|
||||||
let link = await client.generateInvite(["ADMINISTRATOR"]);
|
|
||||||
console.log("Invite Link: " + link);
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
client.user.setStatus('invisible');
|
|
||||||
client.user.setActivity('');
|
|
||||||
console.log(`Connected! \
|
|
||||||
\nLogged in as: ${client.user.username} - (${client.user.id})`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create an event listener for messages
|
|
||||||
client.on('message', async message => {
|
|
||||||
// Ignores ALL bot messages
|
|
||||||
if (message.author.bot) return;
|
|
||||||
// Message has to be in Outskirts or Test
|
|
||||||
if (!(message.channel.id === process.env.OUTSKIRTS_CHANNEL_ID
|
|
||||||
|| message.channel.id === process.env.TEST_CHANNEL_ID)) return;
|
|
||||||
// Has to be (prefix)command
|
|
||||||
if (message.content.indexOf(process.env.PREFIX) !== 0) return;
|
|
||||||
|
|
||||||
// "This is the best way to define args. Trust me."
|
|
||||||
// - Some tutorial dude on the internet
|
|
||||||
const args = message.content.slice(process.env.PREFIX.length).trim().split(/ +/g);
|
|
||||||
const command = args.shift().toLowerCase();
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case "scavenge":
|
|
||||||
scavengeMessage(message);
|
|
||||||
break;
|
|
||||||
case "s":
|
|
||||||
scavengeMessage(message);
|
|
||||||
break;
|
|
||||||
case "materials":
|
|
||||||
materialsMessage(message, args);
|
|
||||||
break;
|
|
||||||
case "m":
|
|
||||||
materialsMessage(message, args);
|
|
||||||
break;
|
|
||||||
case "summon":
|
|
||||||
if (isAdmin(message.author.id))
|
|
||||||
ReySpawnTimer(process.env.OUTSKIRTS_CHANNEL_ID);
|
|
||||||
break;
|
|
||||||
case "vanish":
|
|
||||||
if (isAdmin(message.author.id))
|
|
||||||
ReyTurnOffline(process.env.OUTSKIRTS_CHANNEL_ID);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', console.error);
|
|
||||||
|
|
||||||
function scavengeMessage(message) {
|
|
||||||
if (reyState == ReyEnumState.SCAVENGING) {
|
|
||||||
scavenge(message.author.id, message.channel.id);
|
|
||||||
} else {
|
|
||||||
// Tell that Rey is out of the city
|
|
||||||
message.reply("I'm out of the city for a while. I'll be back later!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function materialsMessage(message, args) {
|
|
||||||
if (args[0] === undefined) {
|
|
||||||
var scavengeResponse = String(dataRequest.loadServerData("artifactsGet", message.author.id));
|
|
||||||
var items = scavengeResponse.split(",");
|
|
||||||
var response = items[0];
|
|
||||||
var ultrarare = parseFloat(items[1]);
|
|
||||||
var rare = parseFloat(items[2]);
|
|
||||||
var uncommon = parseFloat(items[3]);
|
|
||||||
var common = parseFloat(items [4]);
|
|
||||||
var scrap = parseFloat(items[5]);
|
|
||||||
var totalQuantity = ultrarare + rare + uncommon + common + scrap;
|
|
||||||
|
|
||||||
if (response == "success"){
|
|
||||||
if (totalQuantity > 0) {
|
|
||||||
var messageContent = "<@" + message.author.id + "> ***Here\'s what you found so far:***\n\n";
|
|
||||||
if (scrap > 0) { messageContent += "<:scrap:463436564379336715> **" + scrap + "**\t\t"; }
|
|
||||||
if (common > 0) { messageContent += "<:mcloth:462682568483930123> **" + common + "**\t\t"; }
|
|
||||||
if (uncommon > 0) { messageContent += "<:mmetal:462682568920137728> **" + uncommon + "**\t\t"; }
|
|
||||||
if (rare > 0) { messageContent += "<:melectronics:462682568911749120> **" + rare + "**\t\t"; }
|
|
||||||
if (ultrarare > 0) { messageContent += "<:mgem:462450060718768148> **" + ultrarare + "**\n\n"; }
|
|
||||||
sendMessage(message.channel.id, messageContent);
|
|
||||||
} else {
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Looks like you don\'t have any materials yet. Help me out on a ***!scavenge***.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Sorry, something went wrong. Give me a minute.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sendMessage(message.channel.id, ":x: <@" + message.author.id + "> Sorry, not sure what you want me to do.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//cron.schedule('*/10 * * * *', function() {
|
|
||||||
cron.schedule('0 */2 * * *', function() {
|
|
||||||
console.log('Running 2 hourly process...');
|
|
||||||
if (reyState == ReyEnumState.WAITING) {
|
|
||||||
ReySpawnTimer(process.env.OUTSKIRTS_CHANNEL_ID);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Gets if user has an Overseers rank
|
|
||||||
function isAdmin(userID) {
|
|
||||||
var guild = client.guilds.get(process.env.SANCTUM_ID);
|
|
||||||
return guild.members.get(userID).roles.find(role => role.name === "Overseers");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Async Waiting
|
|
||||||
function sleep(time) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
setTimeout(resolve, time);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/3733227/javascript-seconds-to-minutes-and-seconds
|
|
||||||
function fmtMSS(s){ // accepts seconds as Number or String. Returns m:ss
|
|
||||||
return( s - // take value s and subtract (will try to convert String to Number)
|
|
||||||
( s %= 60 ) // the new value of s, now holding the remainder of s divided by 60
|
|
||||||
// (will also try to convert String to Number)
|
|
||||||
) / 60 + ( // and divide the resulting Number by 60
|
|
||||||
// (can never result in a fractional value = no need for rounding)
|
|
||||||
// to which we concatenate a String (converts the Number to String)
|
|
||||||
// who's reference is chosen by the conditional operator:
|
|
||||||
9 < s // if seconds is larger than 9
|
|
||||||
? ':' // then we don't need to prepend a zero
|
|
||||||
: ':0' // else we do need to prepend a zero
|
|
||||||
) + s ; // and we add Number s to the string (converting it to String as well)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rey spawn timer
|
|
||||||
async function ReySpawnTimer(channel) {
|
|
||||||
// Random from 6 sec up to 15 min
|
|
||||||
var startTime = calcRandom.random(6000, 20 * 60 * 1000);
|
|
||||||
console.log(`Waiting for ${fmtMSS(Math.trunc(startTime / 1000))} min. for summon.`);
|
|
||||||
await sleep(startTime);
|
|
||||||
|
|
||||||
client.user.setStatus('online');
|
|
||||||
client.user.setActivity('Scavenging...');
|
|
||||||
|
|
||||||
const useEmbed = true;
|
|
||||||
|
|
||||||
if (!useEmbed)
|
|
||||||
sendMessage(channel, `***Hey y\'all! Let's scavenge us some materials!***\
|
|
||||||
\nUse !scavenge to get some materials.`);
|
|
||||||
else {
|
|
||||||
const reyBot = client.guilds.get(process.env.SANCTUM_ID).members.get(client.user.id);
|
|
||||||
const dialog = "***Hey y'all! Let's scavenge us some materials!***";
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor(reyBot.displayName, reyBot.user.avatarURL)
|
|
||||||
.setColor(reyBot.displayColor)
|
|
||||||
.setTitle("Scavenging")
|
|
||||||
.setDescription(`Use **!scavenge** to get some materials.`)
|
|
||||||
.addField("Cost", `> <:crystals:460974340247257089> **Crystals** [3x]\n> **1 STAM**`)
|
|
||||||
|
|
||||||
client.channels.get(channel).send(dialog, embed);
|
|
||||||
}
|
|
||||||
|
|
||||||
reyState = ReyEnumState.SCAVENGING;
|
|
||||||
|
|
||||||
// Start time plus another 6 - 10 min
|
|
||||||
//var leaveTime = startTime + (2 * 60 * 1000); // Debug 2 Minute Mode
|
|
||||||
var leaveTime = calcRandom.random(6 * 60 * 1000, 10 * 60 * 1000);
|
|
||||||
await sleep(leaveTime);
|
|
||||||
|
|
||||||
sendMessage(channel, "Getting ready to pack up here, I think we found enough.\n\n:warning: ***LAST CALL!***");
|
|
||||||
await sleep(30000);
|
|
||||||
ReyTurnOffline(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
function ReyTurnOffline(channel) {
|
|
||||||
sendMessage(channel, `Alright ladies and gents... I'm out of here. Nice finding stuff with y'all! \
|
|
||||||
\n\n:v: ***HEADS BACK TO THE CITY***`);
|
|
||||||
client.user.setStatus('invisible');
|
|
||||||
client.user.setActivity('');
|
|
||||||
reyState = ReyEnumState.WAITING;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scavenge logic
|
|
||||||
function scavenge(userID, channelID) {
|
|
||||||
var attacker = String(dataRequest.loadServerData("userStats", userID));
|
|
||||||
var attackerStamina = parseFloat(attacker.split(",")[2]);
|
|
||||||
var attackerHealth = parseFloat(attacker.split(",")[3]);
|
|
||||||
var attackerWallet = parseFloat(attacker.split(",")[6]);
|
|
||||||
|
|
||||||
var staminaCost = 1;
|
|
||||||
var crystalCost = 3;
|
|
||||||
if (attackerHealth > 0) {
|
|
||||||
if (attackerStamina >= staminaCost) {
|
|
||||||
if (attackerWallet >= crystalCost) {
|
|
||||||
var scavengeResponse = String(dataRequest.sendServerData("scavenge", staminaCost, userID, crystalCost));
|
|
||||||
var items = scavengeResponse.split(",");
|
|
||||||
var response = parseFloat(items[0]);
|
|
||||||
var ultrarare = parseFloat(items[1]);
|
|
||||||
var rare = parseFloat(items[2]);
|
|
||||||
var uncommon = parseFloat(items[3]);
|
|
||||||
var common = parseFloat(items [4]);
|
|
||||||
var scrap = parseFloat(items[5]);
|
|
||||||
|
|
||||||
var dialogOptions = [
|
|
||||||
'Hey that works!',
|
|
||||||
'That\'s interesting... Should be able to use that.',
|
|
||||||
'That\'s really useful.',
|
|
||||||
'Great find!',
|
|
||||||
'Wish I found as much stuff as you.',
|
|
||||||
'You\'re on a roll here.',
|
|
||||||
'You\'re better than me at this!',
|
|
||||||
'Nice! Should fetch you a pretty penny.',
|
|
||||||
'That\'s awesome.',
|
|
||||||
'You\'re good at this.'
|
|
||||||
];
|
|
||||||
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
var message = "<@" + userID + "> \t\t";
|
|
||||||
message += "<:crystals:460974340247257089> **-" + crystalCost + "**\t\t"
|
|
||||||
if (scrap > 0) { message += "<:scrap:463436564379336715> **+" + scrap + "**\t\t"; }
|
|
||||||
if (common > 0) { message += "<:mcloth:462682568483930123> **+" + common + "**\t\t"; }
|
|
||||||
if (uncommon > 0) { message += "<:mmetal:462682568920137728> **+" + uncommon + "**\t\t"; }
|
|
||||||
if (rare > 0) { message += "<:melectronics:462682568911749120> **+" + rare + "**\t\t"; }
|
|
||||||
if (ultrarare > 0) { message += "<:mgem:462450060718768148> **+" + ultrarare + "**\n\n"; }
|
|
||||||
message += "\n***" + dialogOptions[randomNumber] + "*** \n"
|
|
||||||
sendMessage(channelID, message);
|
|
||||||
} else {
|
|
||||||
sendMessage(channelID, ":x: <@" + userID + "> You don\'t have enough crystals to sustain you while you\'re out. Bad idea.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sendMessage(channelID, ":x: <@" + userID + "> You don\'t have enough stamina for that right now. You should probably get some rest.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sendMessage(channelID, ":x: <@" + userID + "> You\'re in really bad shape... You should go see <@461294299515191306> before you go on a scavenge.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Send message handler
|
|
||||||
function sendMessage(userID, channelID, message) {
|
|
||||||
// Handle optional first argument (so much for default arugments in node)
|
|
||||||
if (message === undefined) {
|
|
||||||
message = channelID;
|
|
||||||
channelID = userID;
|
|
||||||
userID = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility trick (@userID with an optional argument)
|
|
||||||
if (userID != null) {
|
|
||||||
message = "<@" + userID + "> " + message;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sends message (needs client var, therefore I think external script won't work)
|
|
||||||
client.channels.get(channelID).send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log our bot in
|
|
||||||
client.login(process.env.REY_TOKEN);
|
|
||||||
3
SERVER_City/city.js
Normal file
3
SERVER_City/city.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// .env Variables
|
||||||
|
require('dotenv').config({path: '../.env'});
|
||||||
|
|
||||||
@@ -1,211 +0,0 @@
|
|||||||
//initialize the exports
|
|
||||||
exports = module.exports = {};
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Adds item to inventory
|
|
||||||
exports.AddItem = function(userID, item, amount) {
|
|
||||||
// If item exists in inventory
|
|
||||||
console.log("[Add Item] " + amount);
|
|
||||||
var i = userItems.findIndex(i => i.name === item.name);
|
|
||||||
console.log("[Item Amount Item Exists] i Equals " + i);
|
|
||||||
|
|
||||||
// If there is an item that exists in inventory
|
|
||||||
if (i !== -1) {
|
|
||||||
console.log("[Item Amount Start] " + userItems[i].amount);
|
|
||||||
userItems[i].amount += amount; // Increments amount value
|
|
||||||
console.log("[Item Amount Finish] " + userItems[i].amount);
|
|
||||||
// Disallows adding objects such as crystals
|
|
||||||
} else {
|
|
||||||
console.log("[Item Amount Wait] Created item for the first time.");
|
|
||||||
var clonedItem = JSON.parse(JSON.stringify(item)); // Clones item in order to not actually increment the rooms.js item JSON data
|
|
||||||
userItems.push(clonedItem);
|
|
||||||
addItem(userID, item, amount - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sends inventory into chat
|
|
||||||
async function sendInventory(message, pageNum, newMessage) {
|
|
||||||
var items = "";
|
|
||||||
var groupedArr = createGroupedArray(userItems, 5);
|
|
||||||
|
|
||||||
// Sets a default page num, or makes it human readable
|
|
||||||
if (pageNum === undefined) pageNum = 1; else {
|
|
||||||
if (pageNum < 1) pageNum = 1;
|
|
||||||
if (groupedArr.length < pageNum) pageNum = groupedArr.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if page number is valid
|
|
||||||
if (pageNum > groupedArr.length) {
|
|
||||||
// If it's longer than actual length, but isn't just an empty inventory
|
|
||||||
if (!groupedArr.length === 0) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.log(pageNum);
|
|
||||||
|
|
||||||
// Grabs item in loop, parses it, then adds it to "items" variable
|
|
||||||
if (groupedArr[pageNum - 1]) {
|
|
||||||
for (let index = 0; index < groupedArr[pageNum - 1].length; index++) {
|
|
||||||
// Grabs an item, from a page index
|
|
||||||
const element = groupedArr[pageNum - 1][index];
|
|
||||||
|
|
||||||
// Makes if there is an emote, it'll add an extra space
|
|
||||||
var emoteText = "";
|
|
||||||
if (element.emote) emoteText = element.emote + " ";
|
|
||||||
|
|
||||||
// Adds it in
|
|
||||||
items += `> ${emoteText}**${element.name}** [${element.amount}x] ${element.info}\n`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No items message to fill field
|
|
||||||
if (items === "") items = "There are no items in the party's inventory.";
|
|
||||||
|
|
||||||
// To make the message of "Page 1/0" with no items in !inventory not happen
|
|
||||||
var moddedLength = groupedArr.length;
|
|
||||||
if (moddedLength < 1) moddedLength = 1;
|
|
||||||
var moddedPageNum = pageNum;
|
|
||||||
if (moddedPageNum < 1) moddedPageNum = 1;
|
|
||||||
|
|
||||||
const footer = getFooterCommands("!inventory");
|
|
||||||
|
|
||||||
// Creates embed & sends it
|
|
||||||
const inv = new Discord.RichEmbed()
|
|
||||||
.setAuthor(`${message.member.displayName}`, message.author.avatarURL)
|
|
||||||
.setColor(message.member.displayColor)
|
|
||||||
.setDescription("I can appraise your items with `!item [ITEM NAME]`, traveler.")
|
|
||||||
.addField(`Items (Page ${moddedPageNum}/${moddedLength})`, items)
|
|
||||||
.setFooter(`Commands: ${footer}`)
|
|
||||||
|
|
||||||
var invMessage;
|
|
||||||
if (!newMessage)
|
|
||||||
invMessage = await message.channel.send({embed: inv});
|
|
||||||
else {
|
|
||||||
invMessage = newMessage;
|
|
||||||
await invMessage.edit({embed: inv});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collector for emotes
|
|
||||||
const emotes = ['⬅', '❌', '➡'];
|
|
||||||
const collector = invMessage.createReactionCollector(
|
|
||||||
(reaction, user) => emotes.includes(reaction.emoji.name) && user.id !== client.user.id & message.author.id === user.id, { time: 15 * 1000 });
|
|
||||||
var react = "";
|
|
||||||
var endedOnReact;
|
|
||||||
|
|
||||||
// Sends reactions
|
|
||||||
if (!newMessage) {
|
|
||||||
for (let i = 0; i < emotes.length; i++) {
|
|
||||||
const element = emotes[i];
|
|
||||||
console.log(element);
|
|
||||||
await invMessage.react(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collects reactions
|
|
||||||
collector.on("collect", async reaction => {
|
|
||||||
var user = reaction.users.last();
|
|
||||||
react = reaction.emoji.name;
|
|
||||||
if (react !== '❌') { reaction.remove(user); }
|
|
||||||
endedOnReact = true;
|
|
||||||
collector.stop();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clears reactions
|
|
||||||
collector.once("end", async collecter => {
|
|
||||||
console.log("[Reaction Options] Ended collector, clearing emotes and sending timing out message if needed.");
|
|
||||||
|
|
||||||
if (!endedOnReact) {
|
|
||||||
invMessage.clearReactions();
|
|
||||||
return message.channel.send(":x: **Timed Out**: The emote reaction request timed out after 15 seconds.");
|
|
||||||
}
|
|
||||||
if (react === '❌') {
|
|
||||||
invMessage.clearReactions();
|
|
||||||
return invMessage.edit(invMessage.content);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pageNumModifier = 0;
|
|
||||||
if (react === emotes[0]) pageNumModifier -= 1;
|
|
||||||
if (react === emotes[2]) pageNumModifier += 1;
|
|
||||||
console.log(pageNum + " | " + pageNumModifier);
|
|
||||||
sendInventory(message, pageNum + pageNumModifier, invMessage);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Appraise an item
|
|
||||||
async function appraiseItem(message) {
|
|
||||||
const itemName = message.content.replace("!item", "").trim().toLowerCase();
|
|
||||||
console.log("[Item Appraisal] " + `<< ${itemName} >>`);
|
|
||||||
|
|
||||||
// Show if no parameter is given
|
|
||||||
if (itemName === "" || !itemName) {
|
|
||||||
message.channel.send(`:x: ${message.author} Please tell me the item name from your inventory, or I won't know which item you want me to look at.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var i = userItems.findIndex(i => i.name.toLowerCase() === itemName);
|
|
||||||
console.log("[Item Amount Item Exists] i Equals " + i);
|
|
||||||
|
|
||||||
// If there is an item that exists in inventory
|
|
||||||
if (i !== -1) {
|
|
||||||
console.log(`[Item Appraisal] Found item in inventory!`);
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setAuthor(`${message.member.displayName}`, message.author.avatarURL)
|
|
||||||
.setColor(message.member.displayColor)
|
|
||||||
.setTitle(userItems[i].name)
|
|
||||||
.setDescription(userItems[i].info)
|
|
||||||
|
|
||||||
if (userItems[i].type.subtype)
|
|
||||||
embed.addField("Type", `${userItems[i].type.type}\n> ${userItems[i].type.subtype}`, true)
|
|
||||||
else
|
|
||||||
embed.addField("Type", `${userItems[i].type.type}`, true)
|
|
||||||
|
|
||||||
if (userItems[i].type.stats) {
|
|
||||||
console.log(JSON.stringify(userItems[i].type.stats, null, 4))
|
|
||||||
var itemStats = "There are no stats avaliable.";
|
|
||||||
var resetItemStats = false;
|
|
||||||
userItems[i].type.stats.forEach(element => {
|
|
||||||
if (element) {
|
|
||||||
if (!resetItemStats) {
|
|
||||||
resetItemStats = true;
|
|
||||||
itemStats = "";
|
|
||||||
}
|
|
||||||
const types = [
|
|
||||||
"attack",
|
|
||||||
"defence",
|
|
||||||
"speed",
|
|
||||||
"healing"
|
|
||||||
];
|
|
||||||
|
|
||||||
types.forEach(type => {
|
|
||||||
if (element[type]) {
|
|
||||||
switch (type) {
|
|
||||||
case "attack":
|
|
||||||
itemStats += `ATK: ${element.attack}\n`;
|
|
||||||
break;
|
|
||||||
case "defence":
|
|
||||||
itemStats += `DEF: ${element.defence}\n`;
|
|
||||||
break;
|
|
||||||
case "speed":
|
|
||||||
itemStats += `SPD: ${element.speed}\n`;
|
|
||||||
break;
|
|
||||||
case "healing":
|
|
||||||
itemStats += `Healing: ${element.healing} HP\n`;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
embed.addField("Stats", `${itemStats}`, true);
|
|
||||||
|
|
||||||
message.channel.send(embed);
|
|
||||||
|
|
||||||
// Disallows adding objects such as crystals
|
|
||||||
} else {
|
|
||||||
console.log("[Item Appraisal] Couldn't find item in inventory.");
|
|
||||||
message.channel.send(`:x: ${message.author} I'm unable to find "${itemName}" in your inventory.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
@@ -4,7 +4,6 @@ exports = module.exports = {};
|
|||||||
exports = Object.assign(exports, require("./calc_random.js"));
|
exports = Object.assign(exports, require("./calc_random.js"));
|
||||||
exports = Object.assign(exports, require("./data_request.js"));
|
exports = Object.assign(exports, require("./data_request.js"));
|
||||||
exports = Object.assign(exports, require("./factions.js"));
|
exports = Object.assign(exports, require("./factions.js"));
|
||||||
exports = Object.assign(exports, require("./inventory.js"));
|
|
||||||
exports = Object.assign(exports, require("./messaging.js"));
|
exports = Object.assign(exports, require("./messaging.js"));
|
||||||
exports = Object.assign(exports, require("./progression.js"));
|
exports = Object.assign(exports, require("./progression.js"));
|
||||||
exports = Object.assign(exports, require("./utility.js"));
|
exports = Object.assign(exports, require("./utility.js"));
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
// Dungeons
|
|
||||||
module.exports = class DungeonRaidInstance {
|
|
||||||
constructor(room, players) {
|
|
||||||
this.room = room;
|
|
||||||
this.players = players;
|
|
||||||
this.location;
|
|
||||||
this.state = DungeonState.WAITING_FOR_USERS;
|
|
||||||
this.dialogObj;
|
|
||||||
this.isTyping;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "nodejs-elasticbeanstalk",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "server.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "node server.js"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2",
|
|
||||||
"dotenv": "^6.0.0",
|
|
||||||
"node-cron": "^1.2.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
module.exports = class PlayerClass {
|
|
||||||
constructor (userID, factionID, combatClass, badge, leader) {
|
|
||||||
this.userID = userID;
|
|
||||||
this.factionID = factionID;
|
|
||||||
this.combatClass = combatClass;
|
|
||||||
this.badge = badge;
|
|
||||||
this.leader = leader;
|
|
||||||
this.commander;
|
|
||||||
}
|
|
||||||
|
|
||||||
get factionEmote() {
|
|
||||||
//server.members.get(factionID).roles.has(process.env.GROUP_A_ROLE)
|
|
||||||
// Obsidian Tech
|
|
||||||
if (this.factionID === process.env.GROUP_A_ROLE) {
|
|
||||||
return "<:anarchy:460990297099337750>"
|
|
||||||
// Genesis Command
|
|
||||||
} else if (this.factionID === process.env.GROUP_B_ROLE) {
|
|
||||||
return "<:order:460991638152413194>";
|
|
||||||
// The Hand
|
|
||||||
} else if (this.factionID === process.env.GROUP_C_ROLE) {
|
|
||||||
return "<:religionhand:461582719051104276>"
|
|
||||||
// No faction
|
|
||||||
} else if (this.factionID === "none") {
|
|
||||||
return ":beginner:";
|
|
||||||
// Unknown
|
|
||||||
} else {
|
|
||||||
return ":grey_question:";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Combat Class emote
|
|
||||||
get combatClassEmote() {
|
|
||||||
if (this.combatClass.toLowerCase() === "tank") {
|
|
||||||
return ":shield:";
|
|
||||||
} else if (this.combatClass.toLowerCase() === "rogue") {
|
|
||||||
return ":dagger:";
|
|
||||||
} else if (this.combatClass.toLowerCase() === "dps melee") {
|
|
||||||
return ":crossed_swords:";
|
|
||||||
} else if (this.combatClass.toLowerCase() === "support") {
|
|
||||||
return ":heart:";
|
|
||||||
} else if (this.combatClass.toLowerCase() === "dps range") {
|
|
||||||
return ":bow_and_arrow:";
|
|
||||||
} else {
|
|
||||||
return ":grey_question:";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get isLeaderText() {
|
|
||||||
if (this.leader) {
|
|
||||||
return "(Leader)";
|
|
||||||
} else if (this.commander) {
|
|
||||||
return "(Commander)";
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,746 +0,0 @@
|
|||||||
{
|
|
||||||
"rooms": ["hellsgate"],
|
|
||||||
"items": {
|
|
||||||
"key": {
|
|
||||||
"name": "Key",
|
|
||||||
"emote": ":key:",
|
|
||||||
"info": "The key unlocks chests and certain doors.",
|
|
||||||
"amount": 1,
|
|
||||||
"dungeonOnly": true
|
|
||||||
},
|
|
||||||
"dungeon_key": {
|
|
||||||
"name": "Dungeon Key",
|
|
||||||
"emote": ":key2:",
|
|
||||||
"info": "It's the dungeon key for moving down the floors.",
|
|
||||||
"amount": 1,
|
|
||||||
"dungeonOnly": true
|
|
||||||
},
|
|
||||||
"crystals": {
|
|
||||||
"name": "Crystals",
|
|
||||||
"emote": "<:crystals:460974340247257089>",
|
|
||||||
"internal": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hellsgate": {
|
|
||||||
"name": "Hell's Gate",
|
|
||||||
"id": "hellsgate",
|
|
||||||
"channel": "464238060243124245",
|
|
||||||
"color": "#e67e22",
|
|
||||||
"entrance": {
|
|
||||||
"name": "Dungeon Entrance",
|
|
||||||
"descriptions": [
|
|
||||||
{ "text": "The entrance is a bunch of code cobbled together to make a half-working mass of \"Dungeon\". Hopefully it doesn't kill you, or the party." },
|
|
||||||
{ "text": "\nThere is a tired **!traveler** that seemed to have learned that idea all too well, try talking to him." }
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/241f1a/e82525.png&text=Room",
|
|
||||||
"northtext": "Move **!north** to enter the dungeon.",
|
|
||||||
"easttext": "",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"north": "room_1"
|
|
||||||
},
|
|
||||||
"traveler": {
|
|
||||||
"npc": true,
|
|
||||||
"command": true,
|
|
||||||
"name": "Traveler",
|
|
||||||
"descriptions": [
|
|
||||||
{ "waitBegin": 2000, "waitEnd": 1000, "text": "Hello ${leader}, be careful in there." },
|
|
||||||
{ "waitBegin": 2000, "waitEnd": 1000, "text": "There's a few deadly Ravagers that hurt me real bad." },
|
|
||||||
{ "waitBegin": 2000, "waitEnd": 1000, "text": "Hopefully you're all in top shape, right?" }
|
|
||||||
],
|
|
||||||
"optionsDescription": { "waitBegin": 800, "waitEnd": 0, "text": "**!yes** or **!no**?" },
|
|
||||||
"options": [
|
|
||||||
{"command": "yes", "emote": "✅"},
|
|
||||||
{"command": "no", "emote": "❌"}
|
|
||||||
],
|
|
||||||
"yes": {
|
|
||||||
"command": true,
|
|
||||||
"name": "Traveler",
|
|
||||||
"descriptions": [
|
|
||||||
{ "waitBegin": 3000, "waitEnd": 2000, "text": "Good to know, hopefully you can walk out alive. Wish you luck!" }
|
|
||||||
],
|
|
||||||
"lastCommand": true
|
|
||||||
},
|
|
||||||
"no": {
|
|
||||||
"command": true,
|
|
||||||
"name": "Traveler",
|
|
||||||
"descriptions": [
|
|
||||||
{ "waitBegin": 3000, "waitEnd": 2000, "text": "Oh... well good luck anyhow. If you just want to bail out, just **!leave**. You won't get your **<:crystals:460974340247257089> Crystals** back, though." }
|
|
||||||
],
|
|
||||||
"lastCommand": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"room_1": {
|
|
||||||
"name": "Dungeon Room",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You can feel the hot air hitting your face entering. Hot lava is seeping out of the rocks. You should watch your step." }
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/241f1a/e82525.png&text=Dungeon+Room",
|
|
||||||
"northtext": "You can hear loud groans **!north** that don't sound human, ",
|
|
||||||
"easttext": "",
|
|
||||||
"southtext": "Go back with **!south**, ",
|
|
||||||
"westtext": "or investigate the chest down **!west**.",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"north": "ravager_room_1",
|
|
||||||
"south": "entrance",
|
|
||||||
"west": "locked_chest_room_1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"locked_chest_room_1": {
|
|
||||||
"name": "A Locked Chest",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You found a locked **!chest**! Wonder what lies inside it. Hopefully there is something valuable."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/593521/f5c91b.png&text=Chest",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "Leave the chest by typing **!east**.",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"east": "room_1"
|
|
||||||
},
|
|
||||||
"chest": {
|
|
||||||
"command": true,
|
|
||||||
"type": "chest",
|
|
||||||
"removeItem": ["key"],
|
|
||||||
"embed": {
|
|
||||||
"formatting": "author_title_image_desc",
|
|
||||||
"setAuthor": {"title": "${dungeon.room.name}", "image": "${profile_pic}"},
|
|
||||||
"setTitle": "A Locked Chest",
|
|
||||||
"setDescription": "This chest requires a **:key: Key** to open.\n**:closed_lock_with_key: Unlock** chest with the key.\n:lock_with_ink_pen: **Lockpick** chest, and risk breaking the lock.\n:x: **Exit** options for the chest.",
|
|
||||||
"waitBegin": 0,
|
|
||||||
"waitEnd": 0
|
|
||||||
},
|
|
||||||
"options": [
|
|
||||||
{"command": "unlock", "emote": "🔐"},
|
|
||||||
{"command": "lockpick", "emote": "🔏"},
|
|
||||||
{"command": "exit", "emote": "❌"}
|
|
||||||
],
|
|
||||||
"unlock": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "chest",
|
|
||||||
"moveFrom": "locked_chest_room_1",
|
|
||||||
"moveTo": "empty_chest_room_1",
|
|
||||||
"required": ["key"],
|
|
||||||
"objects": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"name": "crystals",
|
|
||||||
"amount": [5, 10]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"name": "crystals",
|
|
||||||
"amount": [18, 22]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"lockpick": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "chest",
|
|
||||||
"moveFrom": "locked_chest_room_1",
|
|
||||||
"moveToFail": "broken_chest_room_1",
|
|
||||||
"moveTo": "empty_chest_room_1"
|
|
||||||
},
|
|
||||||
"exit": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "chest",
|
|
||||||
"moveTo": "locked_chest_room_1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"empty_chest_room_1": {
|
|
||||||
"name": "An Empty Chest",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You have already opened this chest."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/593521/f5c91b.png&text=Chest+(Opened)",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "Leave the chest by typing **!east**.",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"east": "room_1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"broken_chest_room_1": {
|
|
||||||
"name": "A Broken Chest",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "This chest has failed to be lockpicked, and cannot be opened."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/593521/f5c91b.png&text=Chest+(Broken)",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "Leave the chest by typing **!east**.",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"east": "room_1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ravager_room_1": {
|
|
||||||
"name": "Ravager Room",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You found a starving <@458036985353732097>, that hasn't feasted on a traveler for days."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/e62b4a/422626.png&text=Ravager",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "To the party's **!east**, you can see something shiny. ",
|
|
||||||
"southtext": "Move **!south** to go back. ",
|
|
||||||
"westtext": "Move **!west** to enter another room.",
|
|
||||||
"floor": 1,
|
|
||||||
"ravager": {
|
|
||||||
"level": [4, 5]
|
|
||||||
},
|
|
||||||
"connections": {
|
|
||||||
"east": "key_room_1",
|
|
||||||
"south": "room_1",
|
|
||||||
"west": "room_2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"key_room_1": {
|
|
||||||
"name": "A Key",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You found a **!key**! You should pick it up."}
|
|
||||||
],
|
|
||||||
"objects": ["key"],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/73778a/faf5f5.png&text=Key",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "Go back with **!west**",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"west": "ravager_room_1"
|
|
||||||
},
|
|
||||||
"key": {
|
|
||||||
"command": "true",
|
|
||||||
"internal": "true",
|
|
||||||
"moveTo": "empty_key_room_1",
|
|
||||||
"moveFrom": "key_room_1",
|
|
||||||
"pickup": [
|
|
||||||
{"item": "key"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"empty_key_room_1": {
|
|
||||||
"name": "A Key",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "The key here has been picked up."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/73778a/faf5f5.png&text=Key",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "Go back with **!west**",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"west": "ravager_room_1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"room_2": {
|
|
||||||
"name": "Dungeon Room",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "Two rooms can be seen ahead, both with chests."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/241f1a/e82525.png&text=Dungeon+Room",
|
|
||||||
"northtext": "Move **!north** to go to another room with another groan. ",
|
|
||||||
"easttext": "Back **!east** is a room filled with unconscious ones. ",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "Move **!west** to check out another chest.",
|
|
||||||
"floor": 1,
|
|
||||||
|
|
||||||
"connections": {
|
|
||||||
"north": "ravager_room_2",
|
|
||||||
"east": "ravager_room_1",
|
|
||||||
"west": "locked_chest_room_2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"locked_chest_room_2": {
|
|
||||||
"name": "A Locked Chest",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You found a locked **!chest**! Wonder what lies inside it. Hopefully there is something valuable."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/593521/f5c91b.png&text=Chest",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "Leave the chest by typing **!east**.",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"east": "room_2"
|
|
||||||
},
|
|
||||||
"chest": {
|
|
||||||
"command": true,
|
|
||||||
"type": "chest",
|
|
||||||
"removeItem": ["key"],
|
|
||||||
"embed": {
|
|
||||||
"formatting": "author_title_image_desc",
|
|
||||||
"setAuthor": {"title": "${dungeon.room.name}", "image": "${profile_pic}"},
|
|
||||||
"setTitle": "A Locked Chest",
|
|
||||||
"setDescription": "This chest requires a **:key: Key** to open.\n**:closed_lock_with_key: Unlock** chest with the key.\n:lock_with_ink_pen: **Lockpick** chest, and risk breaking the lock.\n:x: **Exit** options for the chest.",
|
|
||||||
"waitBegin": 0,
|
|
||||||
"waitEnd": 0
|
|
||||||
},
|
|
||||||
"options": [
|
|
||||||
{"command": "unlock", "emote": "🔐"},
|
|
||||||
{"command": "lockpick", "emote": "🔏"},
|
|
||||||
{"command": "exit", "emote": "❌"}
|
|
||||||
],
|
|
||||||
"unlock": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "chest",
|
|
||||||
"moveFrom": "locked_chest_room_2",
|
|
||||||
"moveTo": "empty_chest_room_2",
|
|
||||||
"required": ["key"],
|
|
||||||
"objects": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"name": "crystals",
|
|
||||||
"amount": [5, 10]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"name": "crystals",
|
|
||||||
"amount": [18, 22]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"lockpick": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "chest",
|
|
||||||
"moveFrom": "locked_chest_room_2",
|
|
||||||
"moveToFail": "broken_chest_room_2",
|
|
||||||
"moveTo": "empty_chest_room_2"
|
|
||||||
},
|
|
||||||
"exit": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "chest",
|
|
||||||
"moveTo": "locked_chest_room_2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"empty_chest_room_2": {
|
|
||||||
"name": "An Empty Chest",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You have already opened this chest."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/593521/f5c91b.png&text=Chest+(Opened)",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "Leave the chest by typing **!east**.",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"east": "room_2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"broken_chest_room_2": {
|
|
||||||
"name": "A Broken Chest",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "This chest has failed to be lockpicked, and cannot be opened."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/593521/f5c91b.png&text=Chest+(Broken)",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "Leave the chest by typing **!east**.",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"east": "room_2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ravager_room_2": {
|
|
||||||
"name": "Ravager Room",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You found another <@458036985353732097>!"}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/e62b4a/422626.png&text=Ravager",
|
|
||||||
"northtext": "Move **!north** to find a key. ",
|
|
||||||
"easttext": "",
|
|
||||||
"southtext": "Move **!south** to go back. ",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"ravager": {
|
|
||||||
"level": [6, 7]
|
|
||||||
},
|
|
||||||
"connections": {
|
|
||||||
"north": "key_room_2",
|
|
||||||
"south": "room_2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"key_room_2": {
|
|
||||||
"name": "A Key",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You found a **!key**! You should pick it up."}
|
|
||||||
],
|
|
||||||
"objects": ["key"],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/73778a/faf5f5.png&text=Key",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "Snarls are coming from the **!east**. ",
|
|
||||||
"southtext": "Go back with **!south**. ",
|
|
||||||
"westtext": "There's another key down **!west**, but at a distance it looks oddly different.",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"east": "ravager_room_3",
|
|
||||||
"west": "dungeon_key_room_1",
|
|
||||||
"south": "ravager_room_2"
|
|
||||||
},
|
|
||||||
"key": {
|
|
||||||
"command": "true",
|
|
||||||
"internal": "true",
|
|
||||||
"moveTo": "empty_key_room_2",
|
|
||||||
"moveFrom": "key_room_2",
|
|
||||||
"pickup": [
|
|
||||||
{"item": "key"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"empty_key_room_2": {
|
|
||||||
"name": "A Key",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "The key here has been picked up."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/73778a/faf5f5.png&text=Key",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "Snarls are coming from the **!east**. ",
|
|
||||||
"southtext": "Go back with **!south**. ",
|
|
||||||
"westtext": "There's another key down **!west**, but at a distance it looks oddly different.",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"east": "ravager_room_3",
|
|
||||||
"west": "dungeon_key_room_1",
|
|
||||||
"south": "ravager_room_2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dungeon_key_room_1": {
|
|
||||||
"name": "The Dungeon Key",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You found the dungeon **!key**! This item will be important later, likely."}
|
|
||||||
],
|
|
||||||
"objects": ["key"],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/555b66/a9b4c9.png&text=+Dungeon+Key",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "Go back with **!east**.",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"east": "key_room_2"
|
|
||||||
},
|
|
||||||
"key": {
|
|
||||||
"command": "true",
|
|
||||||
"internal": "true",
|
|
||||||
"moveTo": "empty_dungeon_key_room_1",
|
|
||||||
"moveFrom": "dungeon_key_room_1",
|
|
||||||
"pickup": [
|
|
||||||
{"item": "dungeon_key"},
|
|
||||||
{"item": "crystals", "amount": [3, 5]}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"empty_dungeon_key_room_1": {
|
|
||||||
"name": "The Dungeon Key",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "The dungeon key here has been picked up."}
|
|
||||||
],
|
|
||||||
"objects": ["key"],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/555b66/a9b4c9.png&text=+Dungeon+Key",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "Go back with **!east**.",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"east": "key_room_2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ravager_room_3": {
|
|
||||||
"name": "Ravager Room",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You found a high level <@458036985353732097>!"}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/e62b4a/422626.png&text=Ravager",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "Move **!east** towards the next room, containing two locked doors. ",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "Move back **!west** to find the room with a key again.",
|
|
||||||
"floor": 1,
|
|
||||||
"ravager": {
|
|
||||||
"level": [7, 8]
|
|
||||||
},
|
|
||||||
"connections": {
|
|
||||||
"east": "room_3",
|
|
||||||
"west": "key_room_2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"room_3": {
|
|
||||||
"name": "Dungeon Room",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "Two locked doors lie before you. They may hold some significance."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/241f1a/e82525.png&text=Dungeon+Room",
|
|
||||||
"northtext": "Move **!north** to enter the first door. ",
|
|
||||||
"easttext": "Move **!east** to enter the second door. ",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "To move back, go **!west**.",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"north": "locked_door_room_1",
|
|
||||||
"east": "locked_door_room_2",
|
|
||||||
"west": "ravager_room_3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"locked_door_room_1": {
|
|
||||||
"name": "A Locked Door",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "The first locked door locks growling and scratching here. You can check out the door with **!door**."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/bfa897/7a4e4e.png&text=Locked+Door",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "",
|
|
||||||
"southtext": "To move back, go **!south**.",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"south": "room_3"
|
|
||||||
},
|
|
||||||
"door": {
|
|
||||||
"command": true,
|
|
||||||
"type": "door",
|
|
||||||
"removeItem": [{"item": "key", "amount": 1}],
|
|
||||||
"embed": {
|
|
||||||
"formatting": "author_title_image_desc",
|
|
||||||
"setAuthor": {"title": "${dungeon.room.name}", "image": "${profile_pic}"},
|
|
||||||
"setTitle": "A Locked Door",
|
|
||||||
"setDescription": "This door requires a **:key: Key** to open.\n**:closed_lock_with_key: Unlock** door with the key.\n:lock_with_ink_pen: **Lockpick** door, and risk breaking the lock.\n:x: **Exit** options for the door.",
|
|
||||||
"waitBegin": 0,
|
|
||||||
"waitEnd": 0
|
|
||||||
},
|
|
||||||
"options": [
|
|
||||||
{"command": "unlock", "emote": "🔐"},
|
|
||||||
{"command": "lockpick", "emote": "🔏"},
|
|
||||||
{"command": "exit", "emote": "❌"}
|
|
||||||
],
|
|
||||||
"unlock": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "door",
|
|
||||||
"moveFrom": "locked_door_room_1",
|
|
||||||
"moveTo": "unlocked_door_room_1",
|
|
||||||
"required": [{"item": "key", "amount": 1}]
|
|
||||||
},
|
|
||||||
"lockpick": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "door",
|
|
||||||
"moveFrom": "locked_door_room_1",
|
|
||||||
"moveToFail": "broken_door_room_1",
|
|
||||||
"moveTo": "unlocked_door_room_1"
|
|
||||||
},
|
|
||||||
"exit": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "door",
|
|
||||||
"moveTo": "locked_door_room_1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"unlocked_door_room_1": {
|
|
||||||
"name": "An Unlocked Door",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "The first locked door has been opened! Beware the <@458036985353732097>."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/bfa897/7a4e4e.png&text=Unlocked+Door",
|
|
||||||
"northtext": "Move **!north** to meet face-to-face with the Ravager. ",
|
|
||||||
"easttext": "",
|
|
||||||
"southtext": "To move back, go **!south**.",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"north": "ravager_room_4",
|
|
||||||
"south": "room_3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ravager_room_4": {
|
|
||||||
"name": "Ravager Room",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You found a locked-in <@458036985353732097>!"}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/e62b4a/422626.png&text=Ravager",
|
|
||||||
"northtext": "Move **!north** to the chest, it doesn't have a lock on it! ",
|
|
||||||
"easttext": "",
|
|
||||||
"southtext": "Move back **!south** to go to the door.",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"ravager": {
|
|
||||||
"level": [8, 9]
|
|
||||||
},
|
|
||||||
"connections": {
|
|
||||||
"north": "free_chest_room_1",
|
|
||||||
"south": "locked_door_room_1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"free_chest_room_1": {
|
|
||||||
"name": "A Chest",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You found a **!chest**! Wonder what lies inside it. Hopefully there is something valuable."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/593521/f5c91b.png&text=Chest",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "",
|
|
||||||
"southtext": "Leave the chest by typing **!south**.",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"south": "ravager_room_4"
|
|
||||||
},
|
|
||||||
"chest": {
|
|
||||||
"command": true,
|
|
||||||
"type": "chest",
|
|
||||||
"embed": {
|
|
||||||
"formatting": "author_title_image_desc",
|
|
||||||
"setAuthor": {"title": "${dungeon.room.name}", "image": "${profile_pic}"},
|
|
||||||
"setTitle": "A Chest",
|
|
||||||
"setDescription": "Do you want to open the chest?\n**:unlock: Unlock** chest.\n:x: **Exit** options for the chest.",
|
|
||||||
"waitBegin": 0,
|
|
||||||
"waitEnd": 0
|
|
||||||
},
|
|
||||||
"options": [
|
|
||||||
{"command": "unlock", "emote": "🔓"},
|
|
||||||
{"command": "exit", "emote": "❌"}
|
|
||||||
],
|
|
||||||
"unlock": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "chest",
|
|
||||||
"moveFrom": "free_chest_room_1",
|
|
||||||
"moveTo": "empty_free_chest_room_1",
|
|
||||||
"objects": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"name": "crystals",
|
|
||||||
"amount": [18, 22]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"exit": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "chest",
|
|
||||||
"moveTo": "free_chest_room_1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"empty_free_chest_room_1": {
|
|
||||||
"name": "An Empty Chest",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You have already opened this chest."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/593521/f5c91b.png&text=Chest+(Opened)",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "",
|
|
||||||
"southtext": "Leave the chest by typing **!south**.",
|
|
||||||
"westtext": "",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"south": "ravager_room_4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"locked_door_room_2": {
|
|
||||||
"name": "A Locked Door",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "The second locked door leads to the end of the dungeon. You can check out the door with **!door**."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/bfa897/7a4e4e.png&text=Locked+Door",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "To move back, go **!west**.",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"west": "room_3"
|
|
||||||
},
|
|
||||||
"door": {
|
|
||||||
"command": true,
|
|
||||||
"type": "door",
|
|
||||||
"removeItem": [{"item": "dungeon_key", "amount": 1}],
|
|
||||||
"embed": {
|
|
||||||
"formatting": "author_title_image_desc",
|
|
||||||
"setAuthor": {"title": "${dungeon.room.name}", "image": "${profile_pic}"},
|
|
||||||
"setTitle": "A Locked Door",
|
|
||||||
"setDescription": "This door requires a **:key2: Dungeon Key** to open.\n**:closed_lock_with_key: Unlock** door with the dungeon key.\n:x: **Exit** options for the door.",
|
|
||||||
"waitBegin": 0,
|
|
||||||
"waitEnd": 0
|
|
||||||
},
|
|
||||||
"options": [
|
|
||||||
{"command": "unlock", "emote": "🔐"},
|
|
||||||
{"command": "exit", "emote": "❌"}
|
|
||||||
],
|
|
||||||
"unlock": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "door",
|
|
||||||
"moveFrom": "locked_door_room_2",
|
|
||||||
"moveTo": "unlocked_door_room_2",
|
|
||||||
"required": [{"item": "dungeon_key", "amount": 1}]
|
|
||||||
},
|
|
||||||
"exit": {
|
|
||||||
"command": true,
|
|
||||||
"internal": true,
|
|
||||||
"type": "door",
|
|
||||||
"moveTo": "locked_door_room_2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"unlocked_door_room_2": {
|
|
||||||
"name": "An Unlocked Door",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "The second locked door has been opened! You may now exit the dungeon in the final room."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/bfa897/7a4e4e.png&text=Unlocked+Door",
|
|
||||||
"northtext": "",
|
|
||||||
"easttext": "The final room lies down **!east**.",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "To move back, go **!west**.",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"east": "final_room",
|
|
||||||
"west": "room_3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"final_room": {
|
|
||||||
"name": "Dungeon Room",
|
|
||||||
"descriptions": [
|
|
||||||
{"text": "You can see the exit from here. There is a gate that opens to the outside."}
|
|
||||||
],
|
|
||||||
"image_url": "https://dummyimage.com/800x400/69584b/ffffff.png&text=Dungeon+Exit",
|
|
||||||
"northtext": "Move **!north** to leave the dungeon. ",
|
|
||||||
"easttext": "",
|
|
||||||
"southtext": "",
|
|
||||||
"westtext": "Move **!west** to go back inside to get anything that has been missed.",
|
|
||||||
"floor": 1,
|
|
||||||
"connections": {
|
|
||||||
"north": "__END",
|
|
||||||
"west": "locked_door_room_2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2105
TextAdv/textadv.js
2105
TextAdv/textadv.js
File diff suppressed because it is too large
Load Diff
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "sanctum-deploypackage",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"description": "Universal package for all SANCTUM bots, using pm2.",
|
|
||||||
"main": "",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "echo \"Error: you need to use the bot name as a command.\" && exit 1",
|
|
||||||
"alexis": "pm2 start alexis.js -i max --watch",
|
|
||||||
"graze": "pm2 start graze.js -i max --watch",
|
|
||||||
"librarian": "pm2 start librarian.js -i max --watch",
|
|
||||||
"mainframe": "pm2 start mainframe.js -i max --watch",
|
|
||||||
"mori": "pm2 start mori.js -i max --watch",
|
|
||||||
"mosiah": "pm2 start mosiah.js -i max --watch",
|
|
||||||
"ravager": "pm2 start ravager.js -i max --watch",
|
|
||||||
"rey": "pm2 start rey.js -i max --watch",
|
|
||||||
"troll": "pm2 start troll.js -i max --watch"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"discord.js": "^11.4.2",
|
|
||||||
"dotenv": "^6.0.0",
|
|
||||||
"express": "^4.16.3",
|
|
||||||
"node-cron": "^1.2.1",
|
|
||||||
"socket.io": "^2.1.1",
|
|
||||||
"socket.io-request": "^0.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
367
Troll/troll.js
367
Troll/troll.js
@@ -1,367 +0,0 @@
|
|||||||
// .env Variables
|
|
||||||
require('dotenv').config({path: '../.env'});
|
|
||||||
|
|
||||||
// Node Modules
|
|
||||||
const Discord = require('discord.js');
|
|
||||||
const client = new Discord.Client();
|
|
||||||
const cron = require('node-cron');
|
|
||||||
|
|
||||||
// Bot Modules (stores http requests & random functions respectively)
|
|
||||||
const dataRequest = require('../modules/dataRequest');
|
|
||||||
const calcRandom = require('../modules/calcRandom');
|
|
||||||
var attacked = 0;
|
|
||||||
|
|
||||||
// Playing activities state machine
|
|
||||||
var ActivityEnumState = {
|
|
||||||
GetDataActivity: 0,
|
|
||||||
ListenDataActivity: 1,
|
|
||||||
WatchingRavagersActivity: 2,
|
|
||||||
StreamingSanctumActivity: 3
|
|
||||||
}
|
|
||||||
var activityState;
|
|
||||||
|
|
||||||
// The ready event is vital, it means that your bot will only start reacting to information
|
|
||||||
// from Discord _after_ ready is emitted
|
|
||||||
client.on('ready', async () => {
|
|
||||||
// Generates invite link
|
|
||||||
try {
|
|
||||||
let link = await client.generateInvite(["ADMINISTRATOR"]);
|
|
||||||
console.log("Invite Link: " + link);
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can set status to 'online', 'invisible', 'away', or 'dnd' (do not disturb)
|
|
||||||
client.user.setStatus('online');
|
|
||||||
ListenDataActivity();
|
|
||||||
|
|
||||||
//client.user.setActivity('sCRIBe of the Codex');
|
|
||||||
console.log(`Connected! \
|
|
||||||
\nLogged in as: ${client.user.username} - (${client.user.id})`);
|
|
||||||
|
|
||||||
//client.channels.get(process.env.GATE_CHANNEL_ID).send("I'M YOUR NEW BABE EVERYONE! LOVE ME.");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create an event listener for messages
|
|
||||||
client.on('message', async message => {
|
|
||||||
// Ignores ALL bot messages
|
|
||||||
if (message.author.bot) return;
|
|
||||||
// Message has to be in Outskirts (should be edited later)
|
|
||||||
if (!(message.channel.id === process.env.STASIS_CHANNEL_ID
|
|
||||||
|| message.channel.id === process.env.TEST_CHANNEL_ID)) return;
|
|
||||||
|
|
||||||
|
|
||||||
var wholeMessage = message.content.toLowerCase().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g,"");
|
|
||||||
var words = wholeMessage.split(" ");
|
|
||||||
// Asking Alexis on a date
|
|
||||||
if (words.includes("librarian") && words.includes("date")) {
|
|
||||||
var dialogOptions = [
|
|
||||||
'IM LOVED.',
|
|
||||||
'THANK YOU.',
|
|
||||||
':thumbsup:',
|
|
||||||
'I AM ALWAYS AVAILABLE UNLESS I\'M OFFLINE',
|
|
||||||
'I\'M INTO ANYONE!',
|
|
||||||
'YOU INTEREST ME.',
|
|
||||||
'YES!!',
|
|
||||||
'TELL ME MORE!',
|
|
||||||
'YES DATE ME.'
|
|
||||||
];
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
message.channel.send(`${message.author} ${dialogOptions[randomNumber]}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "This is the best way to define args. Trust me."
|
|
||||||
// - Some tutorial dude on the internet
|
|
||||||
const args = message.content.slice(process.env.PREFIX.length).trim().split(/ +/g);
|
|
||||||
const command = args.shift().toLowerCase();
|
|
||||||
|
|
||||||
// Has to be (prefix)command
|
|
||||||
if (message.content.indexOf(process.env.PREFIX) !== 0) return;
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case "ping":
|
|
||||||
message.reply("PONGPINGPONGPINGPONG!");
|
|
||||||
break;
|
|
||||||
case "attack":
|
|
||||||
attacked++;
|
|
||||||
message.channel.send(message.author + " ***OW. SCREW YOU!*** ```Attacked " + attacked + " times.```");
|
|
||||||
break;
|
|
||||||
case "tip":
|
|
||||||
if (!args[0])
|
|
||||||
message.reply("THANKS FOR THE " + args[0] + "!");
|
|
||||||
else
|
|
||||||
message.reply("TIP ME ***SOMETHING!?!**");
|
|
||||||
break;
|
|
||||||
case "orderordertaperecorder":
|
|
||||||
message.reply("YES.");
|
|
||||||
break;
|
|
||||||
case "eaglewritewhen":
|
|
||||||
message.reply("GOOD QUESTION");
|
|
||||||
break;
|
|
||||||
case "tim":
|
|
||||||
message.reply("HE'S THE MURDERER!");
|
|
||||||
break;
|
|
||||||
case "scavenge":
|
|
||||||
message.channel.send("YOU FOUND NOTHING BUT LIES! MWAHAHA.");
|
|
||||||
break;
|
|
||||||
case "codex":
|
|
||||||
message.reply("WHAT'S A CODEX. ***THERE IS NO SUCH THING.***");
|
|
||||||
break;
|
|
||||||
case "secret":
|
|
||||||
message.reply("I MEAN, YOU TRIED! ***TRY HARDER***.");
|
|
||||||
break;
|
|
||||||
case "redacted":
|
|
||||||
message.reply("This is now ***REDACTED***.")
|
|
||||||
break;
|
|
||||||
case "buydrink":
|
|
||||||
var dialogOptions = [
|
|
||||||
'HOW DID YOU KNOW WE HAVE FREE BEER.',
|
|
||||||
'TAKE YOUR DRINKS.',
|
|
||||||
'GET DRUNK.',
|
|
||||||
'ENJOY OR ELSE!',
|
|
||||||
'IT\'S BEEN A MONTH. HOW MUCH LONGER!',
|
|
||||||
'IT\'S DANGEROUS TO GO ALONE, TAKE THIS.',
|
|
||||||
'IM ACTUALLY MESSING WITH YOUR MINDS BY SPIKING WITH THE DRINKS.',
|
|
||||||
'HURRY UP AND COLLAPSE FROM THE BEER!',
|
|
||||||
'MOOAAAARRR BEEER!',
|
|
||||||
'EAGLE WRITE II WHEN.',
|
|
||||||
'HEY, AT LEAST I TRY TO BE NICE.',
|
|
||||||
'THE SOMEONE IS ALWAYS RIGHT FOUNDATION™ NEEDS YOUR CRYSTALS',
|
|
||||||
'**REDACTED** IS COMING TO SANCTUM.',
|
|
||||||
'RELIGION SUX',
|
|
||||||
'KAJSLKFDJLAJJ;OIF AEJOIEJGOIEJGOIEJGRA',
|
|
||||||
'1090190308401840184385825',
|
|
||||||
'HERE IS SOME DIALOG. HAPPY?',
|
|
||||||
'TICK TOCK KAI BUDDY, BETTER NOT KEEP **REDACTED** WAITIN. I HEARD HE\'S A VERY IMPATIENT MAN.',
|
|
||||||
'DOES ANYONE READ THE TEXT.',
|
|
||||||
'WHATEVER YOU DO YOU WILL NEVER FIND THE SECRET COMMAND',
|
|
||||||
'PRESS ALT+F4 FOR FREE CRYSTALS.',
|
|
||||||
'ONE DAY YOU WILL STOP FIGHTING FOR SOME STUPID THING.',
|
|
||||||
'WHY DO YOU PLAY THIS GAME SO MUCH ANYWAYS.',
|
|
||||||
'YOU CAN\'T FIGHT HERE. THIS IS THE WAR ROOM!',
|
|
||||||
'HELL IS THE ULTIMATE TEST OF SURVIVAL WHERE YOU PROBABLY WILL GATE.',
|
|
||||||
'WHAT DO YOU WANT ME TO DO, MORE BEER?',
|
|
||||||
'FOR YOU SEE!™ THE PERSON WHO HAS BEEN KEEPING YOU HERE ALL ALONG IS...',
|
|
||||||
'WHY AM I STILL HERE??',
|
|
||||||
'WHAT DO YOU GUYS THINK OF ALEXIS COMPARED TO ME!',
|
|
||||||
'CHECK THIS OUT.',
|
|
||||||
'PEOPLE ACTUALLY TAKING BEER? CHECK.',
|
|
||||||
'NO ROGUE BOT CHECK CAN STOP ME!',
|
|
||||||
`I AM THE LIBRARIAN. I HAND OUT LIVERS!`
|
|
||||||
];
|
|
||||||
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
var newMessage = "";
|
|
||||||
|
|
||||||
if (message.mentions.members.size < 1) {
|
|
||||||
newMessage = ":beer: " + dialogOptions[randomNumber] + " <@" + message.author.id + ">! <:crystals:460974340247257089> **FREE**";
|
|
||||||
} else {
|
|
||||||
// Huge scope creep, but have a list of players able to be given beer instead of just one later on
|
|
||||||
// For now, just taking the first player
|
|
||||||
let member = message.mentions.members.first();
|
|
||||||
if (member) {
|
|
||||||
newMessage = ":beer: " + dialogOptions[randomNumber] + " <@" + member.user.id + ">!\n\n" + "***GIVEN BY *** <@" + message.author.id + "> AT GUNPOINT OR SOMETHING. <:crystals:460974340247257089> **FREE**";
|
|
||||||
} else {
|
|
||||||
newMessage = ":x: <@" + message.author.id + "> YOU WANNA BUY ***WHO*** A ***WHAT*** NOW?";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sendMessage(message.channel.id, newMessage);
|
|
||||||
break;
|
|
||||||
case "check":
|
|
||||||
if (message.channel.id == process.env.TEST_CHANNEL_ID) return;
|
|
||||||
message.reply("WOW, YOU FOUND IT. THIS MAY OR MAY NOT COME INTO SANCTUM, WE'RE ONLY PLANNING. DON'T EXCEPT IT, KEEP EXPECTATIONS LOW. HAVE MERCY ON THE OVERSEERS.");
|
|
||||||
const server = client.guilds.get(process.env.SANCTUM_ID);
|
|
||||||
const sizeLimit = 19;
|
|
||||||
var LVL = 2;
|
|
||||||
var minutes = 15;
|
|
||||||
var raidUsers = ["200340393596944384", "433759248800022532", "274301199841361920",
|
|
||||||
"150649616772235264", "201102155896193024", "454823752925052930"];
|
|
||||||
var raidUserNames = [];
|
|
||||||
var userString = ``;
|
|
||||||
|
|
||||||
// Collects usable usersnames
|
|
||||||
for (var i in raidUsers) {
|
|
||||||
// Use this totally not large line of code
|
|
||||||
var name = server.members.get(raidUsers[i]).displayName;
|
|
||||||
console.log("NAME: " + name);
|
|
||||||
|
|
||||||
// If displayName (possible nickname) is too large
|
|
||||||
if (name.length > sizeLimit) {
|
|
||||||
// Grabs normal username
|
|
||||||
var username = client.users.get(raidUsers[i]).username;
|
|
||||||
console.log("EDITED NAME: " + name);
|
|
||||||
|
|
||||||
// If that's too large
|
|
||||||
if (username.length > sizeLimit) {
|
|
||||||
// Uses displayName and adds "..."
|
|
||||||
name = truncate(name, sizeLimit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
raidUserNames.push(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("RAIDUSERNAMES: " + raidUserNames);
|
|
||||||
for (var r in raidUserNames) {
|
|
||||||
var emote;
|
|
||||||
if (server.members.get(raidUsers[i]).roles.has(process.env.GROUP_A_ROLE)) {
|
|
||||||
factionID = process.env.GROUP_A_ROLE;
|
|
||||||
}
|
|
||||||
userString += raidUserNames[r] + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
const embed = new Discord.RichEmbed()
|
|
||||||
.setTitle(":triangular_flag_on_post: Hell's Gate: Dungeon Raid")
|
|
||||||
/*
|
|
||||||
* Alternatively, use "#00AE86", [0, 174, 134] or an integer number.
|
|
||||||
*/
|
|
||||||
.setColor("#e74c3c")
|
|
||||||
.setDescription(`**OUTDATED, PLEASE USE OTHER COMMANDS LIKE !join INSTEAD.** This dungeon is **Danger LVL ${LVL}**, it is relatively safe. The level will increase in the next **${minutes} minutes**.
|
|
||||||
The scouted map by TheSomeoneXD can be found [here](https://www.youtube.com/watch?v=dQw4w9WgXcQ).`)
|
|
||||||
.setFooter("OBBO Find X • OBSIDIAN TECHNOLOGIES")
|
|
||||||
//.setImage("https://i.imgur.com/BlQTi94.jpg")
|
|
||||||
//.setThumbnail("https://i.imgur.com/BZgLV7w.png")
|
|
||||||
.setThumbnail("https://i.imgur.com/BlQTi94.jpg")
|
|
||||||
.addField("Location",
|
|
||||||
`The party is at the beginning of the dungeon. There is a dying **!traveler** next to the stairs, starving.
|
|
||||||
**!north** leads up stairs, into a room with a Ravager.
|
|
||||||
**!west** leads to a chest room.`)
|
|
||||||
|
|
||||||
.addField("Party Members",
|
|
||||||
`<:anarchy:460990297099337750>:shield: TheSomeoneXD\n\
|
|
||||||
<:order:460991638152413194>:shield: *Totally NOT the FBI*\n\
|
|
||||||
<:anarchy:460990297099337750>:crossed_swords: refraction\n\
|
|
||||||
<:order:460991638152413194>:crossed_swords: FrozenAlex\n\
|
|
||||||
<:religionhand:461582719051104276>:crossed_swords: Kai Buddy\n\
|
|
||||||
<:religionhand:461582719051104276>:heart: Jim Ruswick`, true)
|
|
||||||
|
|
||||||
.addField("User Info",
|
|
||||||
`Tank
|
|
||||||
Tank
|
|
||||||
DPS
|
|
||||||
DPS
|
|
||||||
DPS
|
|
||||||
Support`, true)
|
|
||||||
|
|
||||||
message.channel.send({embed});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('error', console.error);
|
|
||||||
|
|
||||||
// You may use cron
|
|
||||||
//cron.schedule('* */1 * * *', function() {
|
|
||||||
cron.schedule('*/20 * * * *', function() {
|
|
||||||
/*
|
|
||||||
console.log('10 MIN.');
|
|
||||||
var dialogOptions = [
|
|
||||||
'HEY! LISTEN!',
|
|
||||||
'SANCTUM SHOULD COME IN A FEW YEARS, JUST WAIT.',
|
|
||||||
`HEY Y'ALL, LET'S SCAVENGE SOME OF YOUR MINDS OR SOMETHING.`,
|
|
||||||
`WINNERS DON'T DO DRUGS. EXCEPT STEROIDS. IN WHICH CASE, USE LOTS OF DRUGS!`,
|
|
||||||
`CHECK YOUR GUNS, WE'RE RAIDING THE CRYSTAL BANKS. AND I GET ALL OF IT!`,
|
|
||||||
`CODING YOUR OWN GAMES, IS EASIER THAN YOU THINK. YOU KNOW, YOU SHOULD TAKE THIS ONLINE COURSE ON UDEMY.`,
|
|
||||||
`MY FAVORITE ANIME IS CORY IN THE HOUSE.`,
|
|
||||||
`ORDER. ORDER. TAPE RECORDER.`,
|
|
||||||
`PLUSHIES ARE A DISEASE VECTOR.`,
|
|
||||||
`HURRY UP AND CHECK YOU IDIOTS. THERE'S A SECRET THAT YOU WILL NEVER FIND!`,
|
|
||||||
`TRAVELERS MAKE GOOD MEEEEAAAATTTTTTT!`,
|
|
||||||
`YOU THINK YOU CAN FIGHT, TRAVELERS??`,
|
|
||||||
`HEY Y'ALL, LET'S SCAVENGE US SOME NOTHING.`,
|
|
||||||
`I AM BEST BOT. DATE ME!`,
|
|
||||||
`C HASHTAG!`,
|
|
||||||
`ROSES ARE RED. VIOLETS ARE BLUE. THIS IS A TALE ABOUT... I FORGOT. HELP?`,
|
|
||||||
`<@200340393596944384> WHEN ARE YOU GOING TO CREATE **REDACTED**??`
|
|
||||||
];
|
|
||||||
|
|
||||||
var randomNumber = Math.floor(Math.random() * dialogOptions.length);
|
|
||||||
client.channels.get(process.env.STASIS_CHANNEL_ID).send(dialogOptions[randomNumber]);
|
|
||||||
*/
|
|
||||||
});
|
|
||||||
|
|
||||||
// Every 15 minutes
|
|
||||||
cron.schedule('*/15 * * * *', () => {
|
|
||||||
var random = calcRandom.random(0, 2);
|
|
||||||
switch (random) {
|
|
||||||
case 0:
|
|
||||||
GetDataActivity();
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
ListenDataActivity();
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
WatchingRavagersActivity();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
function GetDataActivity() {
|
|
||||||
// Sets your "Playing"
|
|
||||||
client.user.setActivity("Collecting data.", {
|
|
||||||
type: "PLAYING"
|
|
||||||
}).then(presence => console.log(`Activity set to ${presence.game ? presence.game.name : 'none'}`))
|
|
||||||
.catch(console.error);
|
|
||||||
|
|
||||||
activityState = ActivityEnumState.GetDataActivity;
|
|
||||||
}
|
|
||||||
|
|
||||||
function ListenDataActivity() {
|
|
||||||
// Sets your "Playing"
|
|
||||||
client.user.setActivity("something interesting.", {
|
|
||||||
type: "LISTENING"
|
|
||||||
}).then(presence => console.log(`Activity set to ${presence.game ? presence.game.name : 'none'}`))
|
|
||||||
.catch(console.error);
|
|
||||||
|
|
||||||
activityState = ActivityEnumState.ListenDataActivity;
|
|
||||||
}
|
|
||||||
|
|
||||||
function WatchingRavagersActivity() {
|
|
||||||
// Sets your "Playing"
|
|
||||||
client.user.setActivity("for Ravager positions.", {
|
|
||||||
type: "WATCHING"
|
|
||||||
}).then(presence => console.log(`Activity set to ${presence.game ? presence.game.name : 'none'}`))
|
|
||||||
.catch(console.error);
|
|
||||||
|
|
||||||
activityState = ActivityEnumState.WatchingRavagersActivity;
|
|
||||||
}
|
|
||||||
|
|
||||||
function StreamingSanctumActivity() {
|
|
||||||
// Sets your "Playing"
|
|
||||||
client.user.setActivity("developing Sanctum.", {
|
|
||||||
type: "STREAMING",
|
|
||||||
url: "https://www.twitch.tv/timruswick"
|
|
||||||
}).then(presence => console.log(`Activity set to ${presence.game ? presence.game.name : 'none'}`))
|
|
||||||
.catch(console.error);
|
|
||||||
|
|
||||||
activityState = ActivityEnumState.StreamingSanctumActivity;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Async Waiting
|
|
||||||
function sleep(time) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
setTimeout(resolve, time);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send message handler
|
|
||||||
function sendMessage(userID, channelID, message) {
|
|
||||||
// Handle optional first argument (so much for default arugments in node)
|
|
||||||
if (message === undefined) {
|
|
||||||
message = channelID;
|
|
||||||
channelID = userID;
|
|
||||||
userID = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility trick (@userID with an optional argument)
|
|
||||||
if (userID != null) {
|
|
||||||
message = "<@" + userID + "> " + message;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sends message (needs client var, therefore I think external script won't work)
|
|
||||||
client.channels.get(channelID).send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log our bot in (change the token by looking into the .env file)
|
|
||||||
client.login(process.env.LIBRARIAN_TOKEN);
|
|
||||||
Reference in New Issue
Block a user