HARD FORK: slashed and burned everything that isn't immedately needed or working

This commit is contained in:
2018-10-28 19:35:41 +11:00
parent 3a2d5dc2fb
commit ba4316ef3d
49 changed files with 30 additions and 10848 deletions

75
.envdev
View File

@@ -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=""

View File

@@ -1,6 +0,0 @@
require('dotenv').config({path: '../.env'});
module.exports = {
token: process.env.GHOST_TOKEN,
botChannel: ""
}

View File

@@ -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"
}
}

View File

@@ -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);

View File

@@ -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"
}
}

View File

@@ -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);

View File

@@ -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"
}
}

View File

@@ -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);

View File

@@ -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
}

View File

@@ -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"
}
}

View File

@@ -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);

View File

@@ -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
}

View File

@@ -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"
}
}

View File

@@ -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);

View File

@@ -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
}

View File

@@ -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"
}
}

View File

@@ -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);

View File

@@ -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
}

View File

@@ -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"
}
}

View File

@@ -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);

View File

@@ -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"
}
}

View File

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

View File

@@ -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);

View File

@@ -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"
}
}

View File

@@ -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);

View File

@@ -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"
}
}

View File

@@ -1,2 +0,0 @@
#.htaccess
Options -Indexes

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -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
);

View File

@@ -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;
}
?>

View File

@@ -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);
?>

View File

@@ -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;
}
?>

View File

@@ -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;
}
?>

View File

@@ -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;
}
?>

View File

@@ -1,57 +1,11 @@
# ![SANCTUM Logo](https://i.imgur.com/yZI3Am9.png) SANCTUM # ![SANCTUM Logo](https://i.imgur.com/yZI3Am9.png) SANCTUM
[![SANCTUM Discord](https://img.shields.io/badge/sanctum-discord-%237289DA.svg?logo=discord)](https://discord.gg/D7dyrVn)
[![SANCTUM Developers](https://img.shields.io/badge/sanctum-developers-%237289DA.svg?logo=discord)](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) [![SANCTUM Discord](https://img.shields.io/badge/sanctum-discord-%237289DA.svg?logo=discord)](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!

View File

@@ -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"
}
}

View File

@@ -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
View File

@@ -0,0 +1,3 @@
// .env Variables
require('dotenv').config({path: '../.env'});

View File

@@ -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.`);
}
}
*/

View File

@@ -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"));

View File

@@ -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;
}
}

View File

@@ -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": {}
}

View File

@@ -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 "";
}
}
}

View File

@@ -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"
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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"
}
}

View File

@@ -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);