From 5366206951657caa1261abe74ba9a14f77d66ead Mon Sep 17 00:00:00 2001 From: "Ean Milligan (Bastion)" Date: Tue, 5 Jul 2022 21:47:37 -0400 Subject: [PATCH] Begin adding support for penetrating and compounding explosions Added rollDecorators help command to make [[?? small enough to fit in discord Added documentation on penetrating and compounding --- README.md | 14 ++++- db/populateDefaults.ts | 2 +- mod.ts | 8 +++ src/commands/_index.ts | 2 + src/commands/help.ts | 5 ++ src/commands/rollDecorators.ts | 71 ++++++++++++++++++++++ src/commands/rollHelp.ts | 107 +++++++++++++++------------------ src/solver/roller.ts | 49 +++++++++++---- src/solver/solver.d.ts | 2 + 9 files changed, 186 insertions(+), 74 deletions(-) create mode 100644 src/commands/rollDecorators.ts diff --git a/README.md b/README.md index ae870c6..300dbde 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,10 @@ The Artificer comes with a few supplemental commands to the main rolling command * `[[help` or `[[h` or `[[?` * Provides a message similar to this available commands block. -* `[[rollhelp` or `[[??` +* `[[rollhelp` or `[[??` or `[[rh` or `[[hr` * Details on how to use the roll command, listed as `[[xdy...]]` below. +* `[[rolldecorators` or `[[???` or `[[rd` or `[[dr` + * Details on how to use decorators on the roll command. * `[[api [subcommand]` * Administrative tools for the bots's API. These commands may only be used by the Owner or Admins of your guild. * Available Subcommands: @@ -66,7 +68,7 @@ The Artificer comes with a few supplemental commands to the main rolling command | Paramater | Required? | Repeatable? | Description | |---------------|-------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------| - | x | Optional | No | number of dice to roll, if omitted, 1 is used, additionally, replace x with `F` to roll the dice as Fate dice | + | x | Optional | No | number of dice to roll, if omitted, 1 is used, additionally, replace x with `F` to roll the dice as Fate dice | | dy | Required | No | size of dice to roll, d20 = 20 sided die | | dz or dlz | Optional | No | drops the lowest z dice, cannot be used with any other drop or keep options | | kz or khz | Optional | No | keeps the highest z dice, cannot be used with any other drop or keep options | @@ -86,12 +88,20 @@ The Artificer comes with a few supplemental commands to the main rolling command | cf>q | Optional | Yes | changes crit fail to be greater than or equal to q | | ! | Optional | No | exploding, rolls another dy for every crit success | | !o | Optional | No | exploding once, rolls another dy for each original crit success | + | !p | Optional | No | penetrating explosion, rolls one dy for each crit success, but subtracts one from each resulting explosion | + | !! | Optional | No | compounding explosion, rolls one dy for each crit success, but adds the resulting explosion to the die that caused this explosion | | !=u | Optional | Yes | exploding, rolls another dy for every die that lands on u | | !>u | Optional | Yes | exploding, rolls another dy for every die that lands on u or greater | | ! | Optional | Yes | exploding, rolls another dy for every die that lands on u or less | | !o=u | Optional | Yes | exploding once, rolls another dy for each original die that landed on u | | !o>u | Optional | Yes | exploding once, rolls another dy for each original die that landed on u or greater | | !ou | Optional | Yes | penetrating explosion, rolls one dy for each die that lands on u or greater, but subtracts one from each resulting explosion | + | !pu | Optional | Yes | compounding explosion, rolls one dy for each die that lands on u or greater, but adds the resulting explosion to the die that caused this explosion | + | !! { console.log(`Failed to insert ${command} into database`, e); diff --git a/mod.ts b/mod.ts index c7dd574..f369ae3 100644 --- a/mod.ts +++ b/mod.ts @@ -157,6 +157,14 @@ startBot({ // Help command specifically for the roll command commands.rollHelp(message); break; + case 'rolldecorators': + case 'rd': + case 'dr': + case '???': + // [[rollDecorators or [[rd or [[dr or [[??? + // Help command specifically for the roll command decorators + commands.rollDecorators(message); + break; case 'help': case 'h': case '?': diff --git a/src/commands/_index.ts b/src/commands/_index.ts index e0388e9..6f3dc19 100644 --- a/src/commands/_index.ts +++ b/src/commands/_index.ts @@ -1,6 +1,7 @@ import { ping } from './ping.ts'; import { rip } from './rip.ts'; import { rollHelp } from './rollHelp.ts'; +import { rollDecorators } from './rollDecorators.ts'; import { help } from './help.ts'; import { info } from './info.ts'; import { privacy } from './privacy.ts'; @@ -18,6 +19,7 @@ export default { ping, rip, rollHelp, + rollDecorators, help, info, privacy, diff --git a/src/commands/help.ts b/src/commands/help.ts index a6ed395..e4ce8ec 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -26,6 +26,11 @@ export const help = (message: DiscordenoMessage) => { value: `Details on how to use the roll command, listed as \`${config.prefix}xdy...${config.postfix}\` below`, inline: true, }, + { + name: `\`${config.prefix}rollDecorators\` or \`${config.prefix}???\``, + value: `Details on how to use decorators on the roll command`, + inline: true, + }, { name: `\`${config.prefix}api [subcommand]\``, value: `Administrative tools for the bots's API, run \`${config.prefix}api help\` for more details`, diff --git a/src/commands/rollDecorators.ts b/src/commands/rollDecorators.ts new file mode 100644 index 0000000..a1dfb25 --- /dev/null +++ b/src/commands/rollDecorators.ts @@ -0,0 +1,71 @@ +import config from '../../config.ts'; +import { dbClient, queries } from '../db.ts'; +import { + // Discordeno deps + DiscordenoMessage, +} from '../../deps.ts'; +import { infoColor2 } from '../commandUtils.ts'; +import utils from '../utils.ts'; + +export const rollDecorators = (message: DiscordenoMessage) => { + // Light telemetry to see how many times a command is being run + dbClient.execute(queries.callIncCnt('rollDecorators')).catch((e) => utils.commonLoggers.dbError('rollHelp.ts:15', 'call sproc INC_CNT on', e)); + + message.send({ + embeds: [ + { + color: infoColor2, + title: 'Roll Command Decorators:', + description: `This command also has some useful decorators that can used. These decorators simply need to be placed after all rolls in the message. + +Examples: \`${config.prefix}d20${config.postfix} -nd\`, \`${config.prefix}d20${config.postfix} -nd -s\`, \`${config.prefix}d20${config.postfix} ${config.prefix}d20${config.postfix} ${config.prefix}d20${config.postfix} -o a\``, + fields: [ + { + name: '`-nd` - No Details', + value: 'Suppresses all details of the requested roll', + inline: true, + }, + { + name: '`-snd` - Super No Details', + value: 'Suppresses all details of the requested roll and hides no details message', + inline: true, + }, + { + name: '`-s` - Spoiler', + value: 'Spoilers all details of the requested roll', + inline: true, + }, + { + name: '`-m` - Maximize Roll', + value: 'Rolls the theoretical maximum roll, cannot be used with -n', + inline: true, + }, + { + name: '`-n` - Nominal Roll', + value: 'Rolls the theoretical nominal roll, cannot be used with -m', + inline: true, + }, + { + name: '`-gm @user1 @user2 @usern` - GM Roll', + value: 'Rolls the requested roll in GM mode, suppressing all publicly shown results and details and sending the results directly to the specified GMs', + inline: true, + }, + { + name: '`-c` - Count Rolls', + value: 'Shows the Count Embed, containing the count of successful rolls, failed rolls, rerolls, drops, and explosions', + inline: true, + }, + { + name: '`-o [direction]` - Order Roll', + value: `Rolls the requested roll and orders the results in the requested direction + +Available directions: +\`a\` - Ascending (least to greatest) +\`d\` - Descending (greatest to least)`, + inline: true, + }, + ], + }, + ], + }).catch((e: Error) => utils.commonLoggers.messageSendError('rollHelp.ts:247', message, e)); +}; diff --git a/src/commands/rollHelp.ts b/src/commands/rollHelp.ts index b2e794a..f114dd4 100644 --- a/src/commands/rollHelp.ts +++ b/src/commands/rollHelp.ts @@ -20,7 +20,9 @@ export const rollHelp = (message: DiscordenoMessage) => { This command also can fully solve math equations with parenthesis. -The Artificer supports most of the [Roll20 formatting](https://artificer.eanm.dev/roll20). More details and examples can be found [here](https://artificer.eanm.dev/roll20).`, +The Artificer supports most of the [Roll20 formatting](https://artificer.eanm.dev/roll20). More details and examples can be found [here](https://artificer.eanm.dev/roll20). + +Run \`[[???\` or \`[[rollDecorators\` for details on the roll decorators.`, }, { color: infoColor2, @@ -131,6 +133,16 @@ Additionally, replace \`x\` with \`F\` to roll Fate dice`, value: 'Exploding Once, rolls one `dy` for each original crit success', inline: true, }, + { + name: '`!p` [Optional]', + value: 'Penetrating Explosion, rolls one `dy` for each crit success, but subtracts one from each resulting explosion', + inline: true, + }, + { + name: '`!!` [Optional]', + value: 'Compounding Explosion, rolls one `dy` for each crit success, but adds the resulting explosion to the die that caused this explosion', + inline: true, + }, { name: '`!=u` [Optional]', value: 'Explode on `u`, rolls another `dy` for every die that lands on `u`', @@ -141,6 +153,11 @@ Additionally, replace \`x\` with \`F\` to roll Fate dice`, value: 'Explode on `u` and greater, rolls another `dy` for every die that lands on `u` or greater', inline: true, }, + ], + }, + { + color: infoColor2, + fields: [ { name: '`!u` [Optional]', value: 'Explode Once on `u` and greater, rolls another `dy` for each original die that landed on `u` or greater', @@ -166,6 +178,36 @@ Additionally, replace \`x\` with \`F\` to roll Fate dice`, value: 'Explode Once on `u` and under, rolls another `dy` for each original die that landed on `u` or less', inline: true, }, + { + name: '`!p=u` [Optional]', + value: 'Penetrating Explosion on `u`, rolls one `dy` for each die that lands on `u`, but subtracts one from each resulting explosion', + inline: true, + }, + { + name: '`!p>u` [Optional]', + value: 'Penetrating Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but subtracts one from each resulting explosion', + inline: true, + }, + { + name: '`!pu` [Optional]', + value: 'Compounding Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but adds the resulting explosion to the die that caused this explosion', + inline: true, + }, + { + name: '`!! [], }, }; @@ -261,10 +263,10 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea rollConf.critFail.range.push(i); } break; - case '!o': - rollConf.exploding.once = true; - // falls through as !o functions the same as ! in this context case '!': + case '!o': + case '!p': + case '!!': // Configure Exploding rollConf.exploding.on = true; if (afterNumIdx > 0) { @@ -275,18 +277,18 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea afterNumIdx = 1; } break; - case '!o=': - rollConf.exploding.once = true; - // falls through as !o= functions the same as != in this context case '!=': + case '!o=': + case '!p=': + case '!!=': // Configure Exploding (this can happen multiple times) rollConf.exploding.on = true; rollConf.exploding.nums.push(tNum); break; - case '!o>': - rollConf.exploding.once = true; - // falls through as !o> functions the same as !> in this context case '!>': + case '!o>': + case '!p>': + case '!!>': // Configure Exploding for all numbers greater than or equal to tNum (this could happen multiple times, but why) rollConf.exploding.on = true; for (let i = tNum; i <= rollConf.dieSize; i++) { @@ -294,10 +296,10 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea rollConf.exploding.nums.push(i); } break; - case '!o<': - rollConf.exploding.once = true; - // falls through as !o< functions the same as !< in this context case '!<': + case '!o<': + case '!p<': + case '!!<': // Configure Exploding for all numbers less than or equal to tNum (this could happen multiple times, but why) rollConf.exploding.on = true; for (let i = 1; i <= tNum; i++) { @@ -309,6 +311,29 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Throw error immediately if unknown op is encountered throw new Error(`UnknownOperation_${tSep}`); } + + // Exploding flags get set in their own switch statement to avoid weird duplicated code + switch (tSep) { + case '!o': + case '!o=': + case '!o>': + case '!o<': + rollConf.exploding.once = true; + break; + case '!p': + case '!p=': + case '!p>': + case '!p<': + rollConf.exploding.penetrating = true; + break; + case '!!': + case '!!=': + case '!!>': + case '!!<': + rollConf.exploding.compounding = true; + break; + } + // Finally slice off everything else parsed this loop remains = remains.slice(afterNumIdx); } diff --git a/src/solver/solver.d.ts b/src/solver/solver.d.ts index c5804d3..194e09e 100644 --- a/src/solver/solver.d.ts +++ b/src/solver/solver.d.ts @@ -95,6 +95,8 @@ export type RollConf = { exploding: { on: boolean; once: boolean; + compounding: boolean; + penetrating: boolean; nums: number[]; }; };