#D6 Legends Roller macro
1 messages ยท Page 1 of 1 (latest)
// Dice Roll and Success Check Macro with Dice So Nice
// Prompts the player to enter a number of dice, rolls the dice with 3D effects, and counts the successes.
(async () => {
// Prompt the user for the number of dice
let diceRoll = new Dialog({
title: "Dice Roll",
content: `<p>Enter the number of dice:</p><input type="number" id="numDice" value="1" min="1">`,
buttons: {
roll: {
label: "Roll",
callback: async (html) => {
try {
// Retrieve the number of dice from the input
let numDice = parseInt(html.find("#numDice").val());
// Roll the specified number of d6 minus 1
let roll = new Roll(`${numDice - 1}d6`);
await roll.evaluate({async: true});
if (game.dice3d) {
await game.dice3d.showForRoll(roll, game.user, true);
}
// Count the number of successes
let diceResults = roll.dice[0].results;
let successes = diceResults.filter(die => die.result > 3).length;
// Report the results of the initial roll
let messageContent = `<p>Rolled ${numDice - 1}d6: ${diceResults.map(die => die.result).join(', ')}</p>`;
messageContent += `<p>Initial Successes: ${successes}</p>`;
// Roll the Wild Die
let wildDieRoll = new Roll(`1d6`);
await wildDieRoll.evaluate({async: true});
if (game.dice3d) {
await game.dice3d.showForRoll(wildDieRoll, game.user, true);
}
let wildDieResult = wildDieRoll.dice[0].results[0].result;
messageContent += `<p>Wild Die: ${wildDieResult}</p>`;
// Check the result of the Wild Die
if (wildDieResult > 3) {
successes += 1;
messageContent += `<p>Wild Die Success! Total Successes: ${successes}</p>`;
// Roll again if the Wild Die is 6
while (wildDieResult === 6) {
wildDieRoll = new Roll(`1d6`);
await wildDieRoll.evaluate({async: true});
if (game.dice3d) {
await game.dice3d.showForRoll(wildDieRoll, game.user, true);
}
wildDieResult = wildDieRoll.dice[0].results[0].result;
messageContent += `<p>Wild Die Reroll: ${wildDieResult}</p>`;
if (wildDieResult > 3) {
successes += 1;
messageContent += `<p>Additional Wild Die Success! Total Successes: ${successes}</p>`;
}
}
}
// Report the final number of successes
messageContent += `<p>Final Successes: ${successes}</p>`;
// Send the results to chat
ChatMessage.create({
user: game.user.id,
content: messageContent
});
} catch (error) {
console.error("Error during dice roll:", error);
}
}
}
}
}).render(true);
})();
One small improvement that can be done: you could take the promises of the dice3d, store them, and wait on the final. This means that it will roll the second while the first is still rolling in the canvas, which could make the roll "faster"
I also realized that I didn't make the Wild Die Roll SUBTRACT if ut scored a 1 per rule system, darnit.
I have utterly NO IDEA how to do that. Could you provide an example of how to do that?
The code is big and discord doesn't allow me to share it here. So, here is a gist on github with the changes: https://gist.github.com/Cussa/895eec9a35e60fdb4a0f464672b722ab
Basically I:
- created an array called
tasks - replaced the
await game.dice3d.showForRoll(<any>roll, game.user, true);bytasks.push(game.dice3d.showForRoll(<any>roll, game.user, true));. This adds the roll animations to the array. - added a
await Promise.all(tasks);before theChatMessage.create. This way, it will do all the processing while the animations are running, that it will hold the message until the animation finished, and then show the message.
Some other things it can be improved:
- You are doing the explosion of the dice manually. The dice parser does that too, which could be better.
- You mentioned the wild die, which is quite similar to SWADE, it seems.
- The advantage of using the dice parser to do that for you as that you can simple create a message with the rolls, and the default css from Foundry will show the rolls.
Based on all the above, your macro could be something like this:
(async () => {
// Prompt the user for the number of dice
let diceRoll = new Dialog({
title: "Dice Roll",
content: `<p>Enter the number of dice:</p><input type="number" id="numDice" value="1" min="1">`,
buttons: {
roll: {
label: "Roll",
callback: async (html) => {
try {
// Retrieve the number of dice from the input
let numDice = parseInt(html.find("#numDice").val());
// Roll the specified number of d6 minus 1
let roll = new Roll(`{${numDice - 1}d6cs>3[white], 1d6x6cs>3[black]}`);
await roll.evaluate();
let chatContent = "";
// Send the results to chat
roll.toMessage({
speaker: ChatMessage.getSpeaker(),
flavor: chatContent
});
} catch (error) {
console.error("Error during dice roll:", error);
}
}
}
}
}).render(true);
})();
Just explaning the formula for the dice roll:
THe first part {${numDice - 1}d6cs>3[white] is what you did, but saying to count the results that are greater than 3, and says to roll these dices with the white color.
The second part seems more complex... 1d6x6 says to roll 1d6 and keep exploding on the 6s. The cs>3 says to count all results that are greater than 6s. And then we say to roll this as black dice.
And we use the roll.toMessage to send it to chat, as this handles the dice so nice and the presentation of the chat.
You can add some content using the flavor, but it accepts html, so you can do basically whatever you want there.
Hope this helps you ๐
The good point about using the parser directly is that you can simple add some modifiers to add this.
let roll = new Roll(`{${numDice - 1}d6cs>3df=1[white], 1d6x6cs>3df=1[black]}`);
If this is just in the wild roll, remove the df=1 from the first die parameter
This works like charm ๐
Another small improvement, but with big QOL changes, is to set the roll as default button, so you can press enter and it will roll the dices. So, here is the final version:
(async () => {
// Prompt the user for the number of dice
let diceRoll = new Dialog({
title: "Dice Roll",
content: `<p>Enter the number of dice:</p><input type="number" id="numDice" value="1" min="1">`,
default: "roll",
buttons: {
roll: {
label: "Roll",
callback: async (html) => {
try {
// Retrieve the number of dice from the input
let numDice = parseInt(html.find("#numDice").val());
// Roll the specified number of d6 minus 1
let roll = new Roll(`{${numDice - 1}d6cs>3[white], 1d6x6cs>3df=1[black]}`);
await roll.evaluate();
let chatContent = "<h1>This is the roll</h1>";
// Send the results to chat
roll.toMessage({
speaker: ChatMessage.getSpeaker(),
flavor: chatContent
});
} catch (error) {
console.error("Error during dice roll:", error);
}
}
}
}
}).render(true);
})();
If you want to check, here you can see the dice modifiers you can use:
https://foundryvtt.com/article/dice-modifiers/
The official website and community for Foundry Virtual Tabletop.
Wow!!! Thank you so much! This is amazing. I don't suppose you got the subtraction of a success if a 1 is rolled on the wild die, did you? (This is truly phenomenal and I can't thank you enough)
Yes, the latest version already subtracts the success if it rolls a 1 on the wild die ๐
1d6x6cs>3df=1
roll 1d6, explode every 6, count the dices that are greater than 3, subtract dice equals to 1
Which means that if you roll a 6, it will explode. if the new dice is a one, the success of the 6 is "eliminated". Don't know if this is how the rules works, but this is how it will run the macro ๐
And I was checking here again... There is some other small improvement it could be done...
new Dialog({
title: "Dice Roll",
content: `<p>Enter the number of dice:</p><input type="number" id="numDice" value="1" min="1">`,
default: "roll",
buttons: {
roll: {
label: "Roll",
callback: async (html) => {
try {
// Retrieve the number of dice from the input
let numDice = parseInt(html.find("#numDice").val());
// Roll the specified number of d6 minus 1
let roll = new Roll(`{${numDice - 1}d6cs>3[white], 1d6x6cs>3df=1[black]}`);
await roll.evaluate();
let chatContent = "<h1>This is the roll</h1>";
// Send the results to chat
roll.toMessage({
speaker: ChatMessage.getSpeaker(),
flavor: chatContent
});
} catch (error) {
console.error("Error during dice roll:", error);
}
}
}
}
}).render(true);
We don't need to have the async in the beginning because we are just creating the Dialog, which is not an async operation. The important async would be the callback, as we left it. And we don't need to asign it to a variable, as we were not using the dialog itself. So, this is a smaller version ๐
@twin kettle this shows the sucess being removed if rolling a 1 on the wild dice
A-friggin'-MAZING!!!!
Thank you so much! This also helps any who may want to play D6 Legends in the Future! I very much appreciate it, CussaMitre!
You just need to fill the chatContent with the HTML you want to show in the message. But it will do everything for you ๐
I don't know if I am seeing the correct rulebook.. but if I am, the correct should be cs>=3, no?
It is but I changed it for my game. But yeah, those are rules as written.
I loved the way you made the wild die a different color! This is amazing.
I am amazed you can do so much with so little coding. You really know your stuff! ๐
This coding is ceritified ELEGANT in how much it accomplishes without the janky mess I made! ๐
Is there a way to make it not display the formula every time?
You could hide it using some custom css. Per default, the roll chat message always show the Formula.
If you use some module for custom css, you could hide the formula with something like:
.dice-roll .dice-result .dice-formula {
display: none;
}
Where would that go in the code?
Let me just point out that you made what you need to do. That is not a problem at all. I am still learning new things everyday in Foundry ๐
Before the let chatContent line, correct?
Easiest way would be to install this module: https://foundryvtt.com/packages/custom-css/
Custom CSS, an Add-on Module for Foundry Virtual Tabletop
and use the code I sent to hide the formula. But it will hide all the formulas, ok?
Oh, no way to do it in the Macro itself, then?
I don't think so, unfortunatelly, as we are using the default template from Foundry, which always show the formula. The way to avoid that would be to "rollback" to creating the message by yourself, instaed of using the roll.toMessage
Aah.