Skip to content

Commit

Permalink
Ironman mode (oldschoolgg#169)
Browse files Browse the repository at this point in the history
* Ironmode not yet working

* ironmode->ironman, reset mess fix, data schema unfixed

* added ironman to userschema

* missed ironmode->ironman

* extra line

* missed a tab

* Linted

* grammar changes

* Requested changes

* lint

* added QP reset

lmk if you want me to clean up the mess of commits. atm to tired to care

* Grammar changes & Caps

Fixes grammar but now fails during swap

* rename Ironman -> isIronman/ironman

* change warning msg, dont sync

* add ironCantUser inhibitor

* add ironman icon, fix incorrect casing

* do the resetting in a single call

* fix up daily a bit

* fix grammar

* use extendable for minion name everywhere

Co-authored-by: gc <gc@users.noreply.github.com>
  • Loading branch information
duracell33 and gc committed Mar 31, 2020
1 parent 9bacc99 commit fdf27b6
Show file tree
Hide file tree
Showing 18 changed files with 182 additions and 60 deletions.
25 changes: 18 additions & 7 deletions src/commands/Minion/daily.ts
Expand Up @@ -127,6 +127,11 @@ export default class DailyCommand extends BotCommand {
// Ensure amount of GP is an integer
loot[COINS_ID] = Math.floor(loot[COINS_ID]);

// Check to see if user is iron and remove GP if true.
if (user.isIronman) {
loot[COINS_ID] = 0;
}

const correct = triviaCorrect ? 'correct' : 'incorrect';
const reward = triviaCorrect
? "I've picked you some random items as a reward..."
Expand All @@ -138,7 +143,9 @@ export default class DailyCommand extends BotCommand {

if (triviaCorrect && roll(13)) {
const pet = pets[Math.floor(Math.random() * pets.length)];
const userPets = { ...user.settings.get(UserSettings.Pets) };
const userPets = {
...user.settings.get(UserSettings.Pets)
};
if (!userPets[pet.id]) userPets[pet.id] = 1;
else userPets[pet.id]++;

Expand All @@ -148,12 +155,16 @@ export default class DailyCommand extends BotCommand {
dmStr += `\n**${pet.name}** pet! ${pet.emoji}`;
}

const dailiesAmount = this.client.settings.get(ClientSettings.EconomyStats.DailiesAmount);
const dividedAmount = loot[COINS_ID] / 1_000_000;
this.client.settings.update(
ClientSettings.EconomyStats.DailiesAmount,
Math.floor(dailiesAmount + Math.round(dividedAmount * 100) / 100)
);
if (loot[COINS_ID] > 0) {
const dailiesAmount = this.client.settings.get(
ClientSettings.EconomyStats.DailiesAmount
);
const dividedAmount = loot[COINS_ID] / 1_000_000;
this.client.settings.update(
ClientSettings.EconomyStats.DailiesAmount,
Math.floor(dailiesAmount + Math.round(dividedAmount * 100) / 100)
);
}

// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
Expand Down
4 changes: 3 additions & 1 deletion src/commands/Minion/dice.ts
Expand Up @@ -14,11 +14,13 @@ export default class extends BotCommand {
description: 'Simulates dice rolls from Runescape.',
usage: '[amount:int{1}]',
requiredPermissions: ['EMBED_LINKS'],
oneAtTime: true
oneAtTime: true,
ironCantUse: true
});
}

async run(msg: KlasaMessage, [amount]: [number]) {
if (msg.author.isIronman) throw `You're an ironman and you cant play dice.`;
const roll = rand(1, 100);

const embed = new MessageEmbed()
Expand Down
5 changes: 4 additions & 1 deletion src/commands/Minion/duel.ts
Expand Up @@ -22,7 +22,8 @@ export default class extends BotCommand {
usageDelim: ' ',
cooldown: 5,
oneAtTime: true,
altProtection: true
altProtection: true,
ironCantUse: true
});
}

Expand All @@ -40,6 +41,8 @@ export default class extends BotCommand {
);
}

if (msg.author.isIronman) throw `You can't duel someone as an ironman.`;
if (user.isIronman) throw `You can't duel someone as an ironman.`;
if (!(user instanceof User)) throw `You didn't mention a user to duel.`;
if (user.id === msg.author.id) throw `You cant duel yourself.`;
if (user.bot) throw `You cant duel a bot.`;
Expand Down
111 changes: 98 additions & 13 deletions src/commands/Minion/minion.ts
Expand Up @@ -6,7 +6,6 @@ import { Tasks, Activity, Emoji, Time, Events } from '../../lib/constants';
import {
stringMatches,
formatDuration,
getMinionName,
randomItemFromArray,
findMonster,
isWeekend,
Expand Down Expand Up @@ -54,7 +53,8 @@ export default class extends BotCommand {
cooldown: 1,
aliases: ['m'],
usage:
'[clues|k|kill|setname|buy|clue|kc|pat|stats|mine|smith|quest|qp|chop] [quantity:int{1}|name:...string] [name:...string]',
'[clues|k|kill|setname|buy|clue|kc|pat|stats|mine|smith|quest|qp|chop|ironman] [quantity:int{1}|name:...string] [name:...string]',

usageDelim: ' ',
subcommands: true
});
Expand All @@ -67,6 +67,91 @@ export default class extends BotCommand {
return msg.send(msg.author.minionStatus);
}

async ironman(msg: KlasaMessage) {
if (!msg.author.hasMinion) {
throw hasNoMinion(msg.cmdPrefix);
}

if (msg.author.minionIsBusy) {
return msg.send(msg.author.minionStatus);
}

/**
* If the user is an ironman already, lets ask them if they want to de-iron.
*/
if (msg.author.isIronman) {
await msg.send(
`Would you like to stop being an ironman? You will keep all your items and stats but you will have to start over if you want to play as an ironman again. Please say \`deiron\` to confirm.`
);
try {
await msg.channel.awaitMessages(
answer =>
answer.author.id === msg.author.id &&
answer.content.toLowerCase() === 'deiron',
{
max: 1,
time: 15000,
errors: ['time']
}
);
await msg.author.settings.update(UserSettings.Minion.Ironman, false);
return msg.send('You are no longer an ironman.');
} catch (err) {
return msg.channel.send('Cancelled de-ironning.');
}
}

await msg.send(
`Are you sure you want to start over and play as an ironman?
:warning: **Read the following text before confirming. This is your only warning. ** :warning:
The following things will be COMPLETELY reset/wiped from your account, with no chance of being recovered: Your entire bank, collection log, GP/Coins, QP/Quest Points, Clue Scores, Monster Scores, all XP. If you type \`confirm\`, they will all be wiped.
After becoming an ironman:
- You will no longer be able to receive GP from \`+daily\`
- You will no longer be able to use \`+pay\`, \`+duel\`, \`+sellto\`, \`+sell\`, \`+dice\`
- You can de-iron at any time, and keep all your stuff acquired while playing as an ironman.
Type \`confirm\` if you understand the above information, and want to become an ironman now.`
);

try {
await msg.channel.awaitMessages(
answer =>
answer.author.id === msg.author.id &&
answer.content.toLowerCase() === 'confirm',
{
max: 1,
time: 15000,
errors: ['time']
}
);

msg.author.log(
`just became an ironman, previous settings: ${JSON.stringify(
msg.author.settings.toJSON()
)}`
);

await msg.author.settings.reset([
UserSettings.Bank,
UserSettings.CollectionLogBank,
UserSettings.GP,
UserSettings.QP,
UserSettings.MonsterScores,
UserSettings.ClueScores,
'stats',
'skills'
]);

await msg.author.settings.update(UserSettings.Minion.Ironman, true);
return msg.send('You are now an ironman.');
} catch (err) {
return msg.channel.send('Cancelled ironman swap.');
}
}

async pat(msg: KlasaMessage) {
if (!msg.author.hasMinion) {
throw hasNoMinion(msg.cmdPrefix);
Expand All @@ -76,7 +161,7 @@ export default class extends BotCommand {
return msg.send(msg.author.minionStatus);
}

return msg.send(randomPatMessage(getMinionName(msg.author)));
return msg.send(randomPatMessage(msg.author.minionName));
}

async stats(msg: KlasaMessage) {
Expand Down Expand Up @@ -106,7 +191,7 @@ ${Emoji.QuestIcon} QP: ${msg.author.settings.get(UserSettings.QP)}

const monsterScores = msg.author.settings.get(UserSettings.MonsterScores);

let res = `**${getMinionName(msg.author)}'s KCs:**\n\n`;
let res = `**${msg.author.minionName}'s KCs:**\n\n`;
for (const [monID, monKC] of Object.entries(monsterScores)) {
const mon = killableMonsters.find(m => m.id === parseInt(monID));
res += `${mon!.emoji} **${mon!.name}**: ${monKC}\n`;
Expand Down Expand Up @@ -134,7 +219,7 @@ ${Emoji.QuestIcon} QP: ${msg.author.settings.get(UserSettings.QP)}
const clueScores = msg.author.settings.get(UserSettings.ClueScores);
if (Object.keys(clueScores).length === 0) throw `You haven't done any clues yet.`;

let res = `${Emoji.Casket} **${getMinionName(msg.author)}'s Clue Scores:**\n\n`;
let res = `${Emoji.Casket} **${msg.author.minionName}'s Clue Scores:**\n\n`;
for (const [clueID, clueScore] of Object.entries(clueScores)) {
const clue = clueTiers.find(c => c.id === parseInt(clueID));
res += `**${clue!.name}**: ${clueScore}\n`;
Expand Down Expand Up @@ -289,9 +374,9 @@ ${Emoji.QuestIcon} QP: ${msg.author.settings.get(UserSettings.QP)}

let duration = clueTier.timeToFinish * quantity;
if (duration > Time.Minute * 30) {
throw `${getMinionName(
msg.author
)} can't go on Clue trips longer than 30 minutes, try a lower quantity. The highest amount you can do for ${
throw `${
msg.author.minionName
} can't go on Clue trips longer than 30 minutes, try a lower quantity. The highest amount you can do for ${
clueTier.name
} is ${Math.floor((Time.Minute * 30) / clueTier.timeToFinish)}.`;
}
Expand Down Expand Up @@ -326,7 +411,7 @@ ${Emoji.QuestIcon} QP: ${msg.author.settings.get(UserSettings.QP)}
await addSubTaskToActivityTask(this.client, Tasks.ClueTicker, data);
msg.author.incrementMinionDailyDuration(duration);
return msg.send(
`${getMinionName(msg.author)} is now completing ${data.quantity}x ${
`${msg.author.minionName} is now completing ${data.quantity}x ${
clueTier.name
} clues, it'll take around ${formatDuration(duration)} to finish.`
);
Expand Down Expand Up @@ -401,9 +486,9 @@ ${Emoji.QuestIcon} QP: ${msg.author.settings.get(UserSettings.QP)}

let duration = timeToFinish * quantity;
if (duration > Time.Minute * 30) {
throw `${getMinionName(
msg.author
)} can't go on PvM trips longer than 30 minutes, try a lower quantity. The highest amount you can do for ${
throw `${
msg.author.minionName
} can't go on PvM trips longer than 30 minutes, try a lower quantity. The highest amount you can do for ${
monster.name
} is ${Math.floor((Time.Minute * 30) / timeToFinish)}.`;
}
Expand All @@ -430,7 +515,7 @@ ${Emoji.QuestIcon} QP: ${msg.author.settings.get(UserSettings.QP)}
await addSubTaskToActivityTask(this.client, Tasks.MonsterKillingTicker, data);
msg.author.incrementMinionDailyDuration(duration);

let response = `${getMinionName(msg.author)} is now killing ${data.quantity}x ${
let response = `${msg.author.minionName} is now killing ${data.quantity}x ${
monster.name
}, it'll take around ${formatDuration(duration)} to finish.`;

Expand Down
5 changes: 4 additions & 1 deletion src/commands/Minion/pay.ts
Expand Up @@ -12,13 +12,16 @@ export default class extends BotCommand {
usageDelim: ' ',
oneAtTime: true,
cooldown: 5,
altProtection: true
altProtection: true,
ironCantUse: true
});
}

async run(msg: KlasaMessage, [user, amount]: [KlasaUser, number]) {
await msg.author.settings.sync(true);
const GP = msg.author.settings.get(UserSettings.GP);
if (msg.author.isIronman) throw `Iron players can't send money.`;
if (user.isIronman) throw `Iron players can't receive money.`;
if (GP < amount) throw `You don't have enough GP.`;
if (this.client.oneCommandAtATimeCache.has(user.id)) throw `That user is busy right now.`;
if (user.id === msg.author.id) throw `You can't send money to yourself.`;
Expand Down
4 changes: 3 additions & 1 deletion src/commands/Minion/sell.ts
Expand Up @@ -20,11 +20,13 @@ export default class extends BotCommand {
cooldown: 1,
usage: '<quantity:int{1}> <itemname:...string>',
usageDelim: ' ',
oneAtTime: true
oneAtTime: true,
ironCantUse: true
});
}

async run(msg: KlasaMessage, [quantity, itemName]: [number, string]) {
if (msg.author.isIronman) throw `Iron players can't sell items.`;
const osItem = Items.get(cleanItemName(itemName));
if (!osItem) throw `That item doesnt exist.`;
if (!itemIsTradeable(osItem.id)) {
Expand Down
5 changes: 4 additions & 1 deletion src/commands/Minion/sellto.ts
Expand Up @@ -23,14 +23,17 @@ export default class extends BotCommand {
usage:
'<member:member> <price:int{1,100000000000}> <quantity:int{1,2000000}> <itemname:...string>',
usageDelim: ' ',
oneAtTime: true
oneAtTime: true,
ironCantUse: true
});
}

async run(
msg: KlasaMessage,
[buyerMember, price, quantity, itemName]: [GuildMember, number, number, string]
) {
if (msg.author.isIronman) throw `Iron players can't sell items.`;
if (buyerMember.user.isIronman) throw `Iron players can't be sold items.`;
if (buyerMember.user.id === msg.author.id) throw `You can't trade yourself.`;
if (buyerMember.user.bot) throw `You can't trade a bot.`;
if (buyerMember.user.isBusy) {
Expand Down
9 changes: 7 additions & 2 deletions src/extendables/UserExtendables.ts
Expand Up @@ -46,6 +46,10 @@ export default class extends Extendable {
);
}

public get isIronman(this: User) {
return this.settings.get(UserSettings.Minion.Ironman);
}

/**
* Toggle whether this user is busy or not, this adds another layer of locking the user
* from economy actions.
Expand Down Expand Up @@ -261,9 +265,10 @@ export default class extends Extendable {

public get minionName(this: User): string {
const name = this.settings.get(UserSettings.Minion.Name);
const prefix = this.settings.get(UserSettings.Minion.Ironman) ? Emoji.Ironman : '';
return name
? `${Emoji.Minion} **${Util.escapeMarkdown(name)}**`
: `${Emoji.Minion} Your minion`;
? `${prefix} ${Emoji.Minion} **${Util.escapeMarkdown(name)}**`
: `${prefix} ${Emoji.Minion} Your minion`;
}

public get hasMinion(this: User) {
Expand Down
10 changes: 10 additions & 0 deletions src/inhibitors/ironCantUse.ts
@@ -0,0 +1,10 @@
import { Inhibitor, KlasaMessage, Command } from 'klasa';
import { UserSettings } from '../lib/UserSettings';

export default class extends Inhibitor {
public async run(msg: KlasaMessage, command: Command) {
if (command.ironCantUse && msg.author.settings.get(UserSettings.Minion.Ironman)) {
throw `Ironman players can't use this command.`;
}
}
}
13 changes: 12 additions & 1 deletion src/lib/BotCommand.ts
Expand Up @@ -5,6 +5,7 @@ export abstract class BotCommand extends Command {
public guildOnly: boolean;
public oneAtTime: boolean;
public perkTier?: number;
public ironCantUse?: boolean;

public constructor(
store: CommandStore,
Expand All @@ -16,12 +17,21 @@ export abstract class BotCommand extends Command {
store,
file,
directory,
util.mergeDefault({ altProtection: false, oneAtTime: false, guildOnly: false }, options)
util.mergeDefault(
{
altProtection: false,
oneAtTime: false,
guildOnly: false,
ironCantUse: false
},
options
)
);
this.altProtection = options.altProtection!;
this.oneAtTime = options.oneAtTime!;
this.guildOnly = options.guildOnly!;
this.perkTier = options.perkTier;
this.ironCantUse = options.ironCantUse;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -40,4 +50,5 @@ export interface BotCommandOptions extends CommandOptions {
oneAtTime?: boolean;
guildOnly?: boolean;
perkTier?: number;
ironCantUse?: boolean;
}
1 change: 1 addition & 0 deletions src/lib/UserSettings.ts
Expand Up @@ -37,6 +37,7 @@ export namespace UserSettings {

export const HasBought = T<boolean>('minion.hasBought');
export const DailyDuration = T<number>('minion.dailyDuration');
export const Ironman = T<boolean>('minion.ironman');
}

export namespace Skills {
Expand Down

0 comments on commit fdf27b6

Please sign in to comment.