diff --git a/README.md b/README.md index f731ba5..433dabf 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,14 @@ The Artificer comes with a few supplemental commands to the main rolling command | cfq or cf=q | Optional | Yes | changes crit fail to q | | cfq | Optional | Yes | changes crit fail to be greater than or equal to q | - | ! | Optional | No | exploding, rolls another dy for every crit roll | + | ! | Optional | No | exploding, rolls another dy for every crit success | + | !o | Optional | No | exploding once, rolls another dy for each original crit success | + | !=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]", + value: "Explode on `u` and greater, rolls another `dy` for every die that lands on `u` or greater", + inline: true + }, { + name: "`!u` [Optional]", + value: "Explode Once on `u` and greater, rolls another `dy` for each original die that landed on `u` or greater", + inline: true + }, { + name: "`!o ({ export const generateReport = (msg: string) => ({ embeds: [{ - fields: [{ - name: "USER REPORT:", - value: msg || "No message" - }] + title: "USER REPORT:", + description: msg || "No message" }] }); @@ -419,19 +437,15 @@ export const generateStats = (guildCount: number, channelCount: number, memberCo export const generateApiFailed = (args: string) => ({ embeds: [{ - fields: [{ - name: `Failed to ${args} API rolls for this guild.`, - value: "If this issue persists, please report this to the developers." - }] + title: `Failed to ${args} API rolls for this guild.`, + description: "If this issue persists, please report this to the developers." }] }); export const generateApiStatus = (banned: boolean, active: boolean) => ({ embeds: [{ - fields: [{ - name: `The Artificer's API is ${config.api.enable ? "currently enabled" : "currently disabled"}.`, - value: banned ? "API rolls are banned from being used in this guild.\n\nThis will not be reversed." : `API rolls are ${active ? "allowed" : "blocked from being used"} in this guild.` - }] + title: `The Artificer's API is ${config.api.enable ? "currently enabled" : "currently disabled"}.`, + description: banned ? "API rolls are banned from being used in this guild.\n\nThis will not be reversed." : `API rolls are ${active ? "allowed" : "blocked from being used"} in this guild.` }] }); @@ -443,10 +457,8 @@ export const generateApiSuccess = (args: string) => ({ export const generateDMFailed = (user: string) => ({ embeds: [{ - fields: [{ - name: `WARNING: ${user} could not be messaged.`, - value: "If this issue persists, make sure direct messages are allowed from this server." - }] + title: `WARNING: ${user} could not be messaged.`, + description: "If this issue persists, make sure direct messages are allowed from this server." }] }); diff --git a/src/solver/roller.ts b/src/solver/roller.ts index d9b0333..d46eed4 100644 --- a/src/solver/roller.ts +++ b/src/solver/roller.ts @@ -138,7 +138,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea case "ro": case "ro=": rollConf.reroll.once = true; - // falls through as ro/ro= functions the same as r + // falls through as ro/ro= functions the same as r/r= in this context case "r": case "r=": // Configure Reroll (this can happen multiple times) @@ -147,7 +147,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea break; case "ro>": rollConf.reroll.once = true; - // falls through as ro> functions the same as r + // falls through as ro> functions the same as r> in this context case "r>": // Configure reroll for all numbers greater than or equal to tNum (this could happen multiple times, but why) rollConf.reroll.on = true; @@ -158,7 +158,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea break; case "ro<": rollConf.reroll.once = true; - // falls through as ro< functions the same as r + // falls through as ro< functions the same as r< in this context case "r<": // Configure reroll for all numbers less than or equal to tNum (this could happen multiple times, but why) rollConf.reroll.on = true; @@ -211,10 +211,49 @@ 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 "!": // Configure Exploding rollConf.exploding.on = true; - afterNumIdx = 1; + if (afterNumIdx > 0) { + // User gave a number to explode on, save it + rollConf.exploding.nums.push(tNum); + } else { + // User did not give number, use cs + afterNumIdx = 1; + } + break; + case "!o=": + rollConf.exploding.once = true; + // falls through as !o= functions the same as != in this context + 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 "!>": + // 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++) { + log(LT.LOG, `Handling roll ${rollStr} | Parsing !> ${i}`); + rollConf.exploding.nums.push(i); + } + break; + case "!o<": + rollConf.exploding.once = true; + // falls through as !o< functions the same as !< in this context + 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++) { + log(LT.LOG, `Handling roll ${rollStr} | Parsing !< ${i}`); + rollConf.exploding.nums.push(i); + } break; default: // Throw error immediately if unknown op is encountered @@ -342,7 +381,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // If we need to reroll this roll, flag its been replaced and... // This big boolean statement first checks if reroll is on, if the roll is within the reroll range, and finally if ro is ON, make sure we haven't already rerolled the roll - if (rollConf.reroll.on && rollConf.reroll.nums.indexOf(rollSet[i].roll) >= 0 && (!rollConf.reroll.once || rollConf.reroll.once && !rollSet[i ? (i - 1) : i].rerolled)) { + if (rollConf.reroll.on && rollConf.reroll.nums.indexOf(rollSet[i].roll) >= 0 && (!rollConf.reroll.once || !rollSet[i ? (i - 1) : i].rerolled)) { rollSet[i].rerolled = true; // Copy the template to fill out for this iteration @@ -365,8 +404,9 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Slot this new roll in after the current iteration so it can be processed in the next loop rollSet.splice(i + 1, 0, newRoll); - } else if (rollConf.exploding.on && !rollSet[i].rerolled && rollSet[i].critHit) { - //If it exploded, we keep both, so no flags need to be set + } else if (rollConf.exploding.on && !rollSet[i].rerolled && (rollConf.exploding.nums.length ? rollConf.exploding.nums.indexOf(rollSet[i].roll) >= 0 : rollSet[i].critHit) && (!rollConf.exploding.once || !rollSet[i].exploding)) { + // If we have exploding.nums set, use those to determine the exploding range, and make sure if !o is on, make sure we don't repeatedly explode + // If it exploded, we keep both, so no flags need to be set // Copy the template to fill out for this iteration const newRoll = JSON.parse(JSON.stringify(templateRoll));