Add -yvariables decorator to allow repeat roll button to work consistently

This commit is contained in:
Ean Milligan 2025-07-22 23:31:47 -04:00
parent d2692f1805
commit d6c5dfee77
9 changed files with 78 additions and 14 deletions

View File

@ -58,6 +58,7 @@
"xdydz", "xdydz",
"xdydzracsq", "xdydzracsq",
"xovady", "xovady",
"yvar" "yvar",
"yvariables"
] ]
} }

View File

@ -201,6 +201,7 @@ The Artificer comes with a few supplemental commands to the main rolling command
* `-nv` or `-vn` - Number Variables - Adds `xN` before each roll command in the details section for debug reasons * `-nv` or `-vn` - Number Variables - Adds `xN` before each roll command in the details section for debug reasons
* `-cd` - Custom Dice shapes - Allows a list of `name:[side1,side2,...,sideN]` separated by `;` to be passed to create special shaped dice * `-cd` - Custom Dice shapes - Allows a list of `name:[side1,side2,...,sideN]` separated by `;` to be passed to create special shaped dice
* `-ns` - No Spaces - Removes the default padding added space between rolls (`[[d4]][[d4]]` will output `22` instead of `2 2`) * `-ns` - No Spaces - Removes the default padding added space between rolls (`[[d4]][[d4]]` will output `22` instead of `2 2`)
* `-yvariables y0,y1,...,yN` - Y Variables - Intended for internal use only, but is mentioned here since it is available externally. Takes a comma separated list of numbers. Unlike other decorators, this one will not be shown in the raw output.
* The results have some formatting applied on them to provide details on what happened during this roll. * The results have some formatting applied on them to provide details on what happened during this roll.
* Critical successes will be **bolded** * Critical successes will be **bolded**
* Critical fails will be <ins>underlined</ins> * Critical fails will be <ins>underlined</ins>

View File

@ -3,15 +3,17 @@ import { log, LogTypes as LT } from '@Log4Deno';
import { SolvedRoll } from 'artigen/artigen.d.ts'; import { SolvedRoll } from 'artigen/artigen.d.ts';
import { tokenizeCmd } from 'artigen/cmdTokenizer.ts'; import { tokenizeCmd } from 'artigen/cmdTokenizer.ts';
import { Modifiers } from 'artigen/dice/getModifiers.ts';
import { loopCountCheck } from 'artigen/managers/loopManager.ts'; import { loopCountCheck } from 'artigen/managers/loopManager.ts';
import { QueuedRoll } from 'artigen/managers/manager.d.ts'; import { QueuedRoll } from 'artigen/managers/manager.d.ts';
import { reduceCountDetails } from 'artigen/utils/counter.ts'; import { reduceCountDetails } from 'artigen/utils/counter.ts';
import { cmdSplitRegex, escapeCharacters } from 'artigen/utils/escape.ts'; import { cmdSplitRegex, escapeCharacters, withYVarsDash } from 'artigen/utils/escape.ts';
import { loggingEnabled } from 'artigen/utils/logFlag.ts'; import { loggingEnabled } from 'artigen/utils/logFlag.ts';
import { assertPrePostBalance } from 'artigen/utils/parenBalance.ts'; import { assertPrePostBalance } from 'artigen/utils/parenBalance.ts';
import { reduceRollDistMaps } from 'artigen/utils/rollDist.ts'; import { reduceRollDistMaps } from 'artigen/utils/rollDist.ts';
import { compareTotalRolls, compareTotalRollsReverse } from 'artigen/utils/sortFuncs.ts'; import { compareTotalRolls, compareTotalRollsReverse, sortYVars } from 'artigen/utils/sortFuncs.ts';
import { translateError } from 'artigen/utils/translateError.ts'; import { translateError } from 'artigen/utils/translateError.ts';
// runCmd(rollRequest) // runCmd(rollRequest)
@ -51,7 +53,12 @@ export const runCmd = (rollRequest: QueuedRoll): SolvedRoll => {
// Remove any floating spaces from originalCommand // Remove any floating spaces from originalCommand
// Escape any | and ` chars in originalCommand to prevent spoilers and code blocks from acting up // Escape any | and ` chars in originalCommand to prevent spoilers and code blocks from acting up
const rawCmd = escapeCharacters(rollRequest.originalCommand.trim(), '|').replace(/`/g, ''); let rawCmd = escapeCharacters(rollRequest.originalCommand.trim(), '|').replace(/`/g, '');
// Remove yvariables from the rawCmd since this is intended for internal use only
if (rawCmd.includes(Modifiers.YVars)) {
rawCmd = rawCmd.replaceAll(new RegExp(`( ${Modifiers.YVars} (\\d+,)+\\d+)`, 'g'), '');
}
let line1 = ''; let line1 = '';
let line2 = ''; let line2 = '';
@ -84,6 +91,17 @@ export const runCmd = (rollRequest: QueuedRoll): SolvedRoll => {
line1 = ` rolled:\n\`${rawCmd}\``; line1 = ` rolled:\n\`${rawCmd}\``;
} }
if (rollRequest.modifiers.yVars.size) {
line1 += `\n${withYVarsDash} With yVars: ${
rollRequest.modifiers.yVars
.entries()
.toArray()
.sort((a, b) => sortYVars(a[0], b[0]))
.map((yVar) => `\`${yVar[0]}=${yVar[1]}\``)
.join(' ')
}`;
}
// List number of iterations on simulated nominals // List number of iterations on simulated nominals
if (rollRequest.modifiers.simulatedNominal) line2 += `Iterations performed per roll: \`${rollRequest.modifiers.simulatedNominal}\`\n`; if (rollRequest.modifiers.simulatedNominal) line2 += `Iterations performed per roll: \`${rollRequest.modifiers.simulatedNominal}\`\n`;

View File

@ -25,6 +25,7 @@ export const Modifiers = Object.freeze({
VariablesNumber: '-vn', VariablesNumber: '-vn',
CustomDiceShapes: '-cd', CustomDiceShapes: '-cd',
NoSpaces: '-ns', NoSpaces: '-ns',
YVars: '-yvariables',
}); });
// args will look like this: ['-sn', ' ', '10'] as spaces/newlines are split on their own // args will look like this: ['-sn', ' ', '10'] as spaces/newlines are split on their own
@ -204,6 +205,15 @@ export const getModifiers = (args: string[]): [RollModifiers, string[]] => {
case Modifiers.NoSpaces: case Modifiers.NoSpaces:
modifiers.noSpaces = true; modifiers.noSpaces = true;
break; break;
case Modifiers.YVars: {
// Shift the -yvariables out of the array so the next item is the first yVar
args.splice(i, 2);
const yVars = args[i].split(',');
yVars.forEach((yVar, idx) => {
modifiers.yVars.set(`y${idx}`, parseFloat(yVar));
});
break;
}
default: default:
// Default case should not mess with the array // Default case should not mess with the array
defaultCase = true; defaultCase = true;

View File

@ -41,3 +41,6 @@ export const internalWrapRegex = new RegExp(`([${openInternal}${closeInternal}])
export const openInternalGrp = '\u2e20'; export const openInternalGrp = '\u2e20';
export const closeInternalGrp = '\u2e21'; export const closeInternalGrp = '\u2e21';
export const internalGrpWrapRegex = new RegExp(`([${openInternalGrp}${closeInternalGrp}])`, 'g'); export const internalGrpWrapRegex = new RegExp(`([${openInternalGrp}${closeInternalGrp}])`, 'g');
// Marker to look for when repeating a roll AND it was from a SLASH COMMAND alias run command
export const withYVarsDash = '\u2043';

View File

@ -49,3 +49,12 @@ export const compareOrigIdx = (a: RollSet | ReturnData, b: RollSet | ReturnData)
} }
return 0; return 0;
}; };
// Sort yVars by their name
export const sortYVars = (a: string, b: string) => {
if (a.length < b.length) return -1;
if (a.length > b.length) return 1;
if (a < b) return -1;
if (a > b) return 1;
return 0;
};

View File

@ -10,6 +10,7 @@ import { sendRollRequest } from 'artigen/managers/queueManager.ts';
import { cmdSplitRegex } from 'artigen/utils/escape.ts'; import { cmdSplitRegex } from 'artigen/utils/escape.ts';
import { assertPrePostBalance, getMatchingPostfixIdx } from 'artigen/utils/parenBalance.ts'; import { assertPrePostBalance, getMatchingPostfixIdx } from 'artigen/utils/parenBalance.ts';
import { sortYVars } from 'artigen/utils/sortFuncs.ts';
import { ReservedWords } from 'commands/aliasCmd/reservedWords.ts'; import { ReservedWords } from 'commands/aliasCmd/reservedWords.ts';
@ -26,14 +27,6 @@ interface QueryShape {
aliasName: string; aliasName: string;
} }
const sortYVars = (a: string, b: string) => {
if (a.length < b.length) return -1;
if (a.length > b.length) return 1;
if (a < b) return -1;
if (a > b) return 1;
return 0;
};
const handleAddUpdate = async ( const handleAddUpdate = async (
msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId, msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId,
guildMode: boolean, guildMode: boolean,

View File

@ -207,6 +207,20 @@ Removes the default padding added space between rolls.`,
], ],
}, },
], ],
[
'-yvariables',
{
name: 'Y Variables',
description: `**Usage:** \`-yvariables y0,y1,...,yN\`
Intended for internal use only, but it's implementation makes it accessible publicly, so this documentation explains what its for and why it exists.
Allows a comma separated list of number to be passed in for y variables, see \`Miscellaneous Features>Variables\` and \`Roll Alias System>Add New Alias\` for what y variables are.
This decorator exists to allow for the Repeat Roll button to work consistently.`,
example: ['`[[d20+y0+y1]] -yvariables 10,37` => `[[d20+10+37]]` => [15]+10+37 = 62'],
},
],
]); ]);
export const DecoratorsHelpPages: HelpPage = { export const DecoratorsHelpPages: HelpPage = {

View File

@ -15,10 +15,12 @@ import {
} from '@discordeno'; } from '@discordeno';
import { log, LogTypes as LT } from '@Log4Deno'; import { log, LogTypes as LT } from '@Log4Deno';
import { Modifiers } from 'artigen/dice/getModifiers.ts';
import { repeatRollCustomId } from 'artigen/managers/handler/workerComplete.ts'; import { repeatRollCustomId } from 'artigen/managers/handler/workerComplete.ts';
import { toggleWebView, webViewCustomId } from 'artigen/utils/embeds.ts'; import { toggleWebView, webViewCustomId } from 'artigen/utils/embeds.ts';
import { argSpacesSplitRegex } from 'artigen/utils/escape.ts'; import { argSpacesSplitRegex, withYVarsDash } from 'artigen/utils/escape.ts';
import { commands, slashCommandDetails } from 'commands/_index.ts'; import { commands, slashCommandDetails } from 'commands/_index.ts';
@ -104,7 +106,20 @@ export const interactionCreateHandler = async (interaction: Interaction) => {
if (botMsg && botMsg.embeds.length) { if (botMsg && botMsg.embeds.length) {
const rollEmbed = botMsg.embeds[0].description ?? ''; const rollEmbed = botMsg.embeds[0].description ?? '';
const rollStrStartIdx = rollEmbed.indexOf('`') + 1; const rollStrStartIdx = rollEmbed.indexOf('`') + 1;
const rollStr = rollEmbed.substring(rollStrStartIdx, rollEmbed.indexOf('`', rollStrStartIdx)); let rollStr = rollEmbed.substring(rollStrStartIdx, rollEmbed.indexOf('`', rollStrStartIdx));
// Since we're dealing with a slash command, we can't get the original command (as far as I know), so rebuild the yVars for an alias using what is in the response message
if (rollEmbed.includes(withYVarsDash)) {
const yVarStartIdx = rollEmbed.indexOf(withYVarsDash) + 1;
const yVarStr = rollEmbed.substring(rollEmbed.indexOf(':', yVarStartIdx) + 1, rollEmbed.indexOf('\n', yVarStartIdx)).trim();
const yVars = yVarStr.split(' ').filter((x) => x);
const yVarVals: string[] = [];
for (const yVar of yVars) {
const [_yVarName, yVarVal] = yVar.split('=');
yVarVals.push(yVarVal);
}
rollStr += ` ${Modifiers.YVars} ${yVarVals.join(',')}`;
}
commands.roll(interaction, rollStr.split(argSpacesSplitRegex), ''); commands.roll(interaction, rollStr.split(argSpacesSplitRegex), '');
return; return;
} }