Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

One Die A Time

Greetings all! I'm messing around with creating a character sheet for Night's Black Agents: Solo and Cthulhu Confidential, both GUMSHOE One-To-One games.  Now it works mechanically is that the player is given a target number that is their Advance target. There is a setback number that they don't know. In between the setback and the advance is the hold.  They have a number of d6's they can roll. Their goal is exceed or get as close to that advance number with their dice.  The trick is, that they are supposed to roll the dice one at a time. Because if they meet their target number and they have dice left over, they get a bonus called a push. So if a player has 3 dice and their Advance number is a 7...it would go like this... Die 1 rolls a 3, total 7. GM, you have 2 dice left, do you want to roll the next one or keep? Player rolls the next die. Die 2 rolls a 5, total 8. The player met the Advance number and has 1 die left over so gets a Push. If die 2 rolled a 3, then they'd roll that 3rd die, and maybe roll at 3, and they'd make their number, but they 'd have no dice left over, so they don't get the push. Is there a way to replicate this using...something/anything in Roll20? Script Cards, regular macros, roll templates, something? Thanks in advance!
1718837289
GiGs
Pro
Sheet Author
API Scripter
There are probably multiple ways to kind of replicate it, but all of them will treat each single die roll as its own event. You'd have to go through each player clicking a button (or drawing a card or whatever) to roll each die, ask you what that means, then roll the next die (now clicking the base roll or push button). There's a bunch of mechanics that would need to be explained more exhautively to suggest a method, but that might point you in the right dircetion.
Mechanically it is pretty simple. If you have 3d6 to roll you roll them one at a time because if you reach your target number before you finish the 3 dice you get to take a token. Alternately, after you finish rolling your 3 dice (or 2, or however many you have), if you don't make the number, you might be able to get an extra die to add to the roll by taking an extra problem, etc.  So really, what I need is a way to have a running count of the die total, and be able to add new dice to that total. Which...I'm going to guess is something I'm going to have to do with Script Cards rather then the regular rolltemplates?
1718878309

Edited 1718904969
GiGs
Pro
Sheet Author
API Scripter
You won't be able to do it with ScriptCards, if you want to get user input on each die before proceding with the next. That is the stumbling block, and Roll20 doesn't work like that. If you want to keep a running total that players can then supplement with new rolls, you can do that with ScriptCards, or any custom script. It needs to be a script because default systems in roll20 don't allow you to store a running total (outside of one specific and very clunky hack, using the Turn Order, but if you already use the turn order for, say, initiative you can't use that hack).
What is the Turn Order Hack?
1718905096
GiGs
Pro
Sheet Author
API Scripter
Here's my earlier description And some more: <a href="https://wiki.roll20.net/Turn_Tracker/Tricks" rel="nofollow">https://wiki.roll20.net/Turn_Tracker/Tricks</a>
Thanks so much! Now I have some fun things to look into!
1718994914
timmaugh
Pro
API Scripter
I have mocked something up that can do this using the Metascript Toolbox set of scripts. You can find the Metascript Toolbox in the 1-click. Once the scripts are installed, open the character that you want to be able to do this with. I named mine "MuleCharacter," but you can replace every instance of that name in the command line with the name of your character. Also, since I didn't know the game system you mentioned, I just used names like "ThisSkill" and "ThatSkill". You'll want to replace those (and flesh out the list with all of the skills you want to use), but that will make more sense in a minute. Go to the Attributes &amp; Abilities tab on MuleCharacter (or your character, if you are doing the name replacement) and create 3 Abilities. Name them: CarriedTotal CarriedTotalFirstRoll CarriedTotalRollN Open CarriedTotal, and enter four lines for each skill you want to use with this die-rolling mechanic. These are the lines for "ThisSkill": StartingDice=4 RemainingDice=0 RunningTotal=0 TargetNumber=0 The StartingDice value is the only variable that needs a non-zero value. This line represents the number of d6 the character has for the skill "ThisSkill". For now, we'll hard-code it to something (I arbitrarily chose 4). Later, this could be expanded to read the value from an attribute on your character. Save CarriedTotal and close it, then open CarriedTotalFirstRoll . Enter this text and save it: !{{(^) &nbsp; set.MuleCharacter.CarriedTotal.CurrentSkill=?{Skill|ThisSkill|ThatSkill}/set &nbsp; set.MuleCharacter.CarriedTotal.TargetNumber=?{Target Number?|0}/set &nbsp; set.MuleCharacter.CarriedTotal.StartingDice=?{Starting Dice|1|2|3|4|5|6|7|8|9|10}/set &nbsp; set.MuleCharacter.CarriedTotal.RemainingDice=?{Starting Dice}/set &nbsp; set.MuleCharacter.CarriedTotal.RunningTotal=0/set &nbsp; {^&amp;template:default} ({)name=?{Skill} Incremental Rolls(}) {\\^&amp;global ([GlobNewTotal] [\\^][\\^] get^.MuleCharacter.CarriedTotal.RunningTotal/get + $^[^[0^]^].value \\^]\\^]) ([GlobRemainingDice] {^&amp;math get^.MuleCharacter.CarriedTotal.RemainingDice/get - 1}) ([GlobTargetNumber] ?{Target Number?}) ([GlobPreviousTotal] [\\^][\\^]get^.MuleCharacter.CarriedTotal.RunningTotal/get\\^]\\^]) ([GlobStartingDice] get^.MuleCharacter.CarriedTotal.StartingDice/get) } ({)Target=GlobTargetNumber(}) ({)Previous Total=GlobPreviousTotal(}) ({)This Roll=[^[^1d6^]^](}) ({)----------(}) ({)New Total=**GlobNewTotal** (}) {\\^&amp; if GlobNewTotal &gt;= GlobTargetNumber} ({)Target Number Reached!=GlobRemainingDice Pushes Earned(}) {\\^&amp;else} {\\^&amp;if GlobRemainingDice &gt; 0} ({)Dice Left=GlobRemainingDice / GlobStartingDice(}) ({) [Roll 1d6](~MuleCharacter|CarriedTotalRollN)(}) {\\^&amp;else} ({)No More Dice!=Target number not reached.(}) {\\^&amp;end} {\\^&amp;end} {\\^&amp;if GlobRemainingDice &gt;= 0} set^\\\.MuleCharacter.CarriedTotal.RemainingDice=GlobRemainingDice/set set^\\\.MuleCharacter.CarriedTotal.RunningTotal=$[^[^0^]^].value/set{\\^&amp;end} }} Finally, open CarriedTotalRollN and enter the following text, then save and close it: !&amp;{template:default} {{name=get.MuleCharacter.CarriedTotal.CurrentSkill/get Incremental Rolls}} {\&amp;global ([GlobNewTotal] [\][\]get.MuleCharacter.CarriedTotal.RunningTotal/get + $[[0]].value \]\]) ([GlobRemainingDice] {&amp;math get.MuleCharacter.CarriedTotal.RemainingDice/get - 1}) ([GlobTargetNumber] get.MuleCharacter.CarriedTotal.TargetNumber/get) ([GlobPreviousTotal] [\][\]get.MuleCharacter.CarriedTotal.RunningTotal/get\]\]) ([GlobStartingDice] get.MuleCharacter.CarriedTotal.StartingDice/get) } {{Target=GlobTargetNumber}} {{Previous Total=GlobPreviousTotal}} {{This Roll=[[1d6]]}} {{----------}} {{New Total=**GlobNewTotal** }} {\\&amp; if GlobNewTotal.value &gt;= GlobTargetNumber} {{Target Number Reached!=GlobRemainingDice Pushes Earned}} {\\&amp;else} {\\&amp;if GlobRemainingDice &gt; 0} {{Dice Left=GlobRemainingDice / GlobStartingDice}} {{ [Roll 1d6](~MuleCharacter|CarriedTotalRollN)}} {\\&amp;else} {{No More Dice!=Target number not reached.}} {\\&amp;end} {\\&amp;end} {\\&amp;if GlobRemainingDice &gt;= 0} set\\\.MuleCharacter.CarriedTotal.RemainingDice=GlobRemainingDice/set set\\\.MuleCharacter.CarriedTotal.RunningTotal=get.MuleCharacter.CarriedTotal.RunningTotal/get + $[[0]].value/set{\\&amp;end} {&amp;simple} Usage Run the CarriedTotalFirstRoll ability (you can make it a token action or add it to your bar, or click it from the sheet). The display will tell you whether you made your Target Number. If so, it will report how many pushes were earned. If the Target Number was not met and there are still more d6 available to roll, you'll have a button to run the next command (and roll the next d6). The Output After running the first command (and entering 5 for the number of starting dice, "ThisSkill" for the skill, and 15 for the Target Number), you should see something like this: You can see that I rolled a 5 with my first d6, and now have a total of 5. I have 4 out of 5 dice left, so I click the button to continue: In fact, I had to roll 2 additional times before I reached the Target Number of 15. With 1 die left, it tells me that I not only reached the Target Number, but I also earned 1 push. Each of these intermediate steps show the previous total as well as the current/new total counting the most recent 1d6 roll. If I do not make the Target Number within the number of dice I have, I will instead see a message noting that I failed: What is Happening The CarriedTotal ability is acting as a mule table, where we can store information. Here we are going to store our starting number of d6, how many d6 we have left, our previous total (actually the numbers that create the total), and our Target Number for the try. The CarriedTotalFirstRoll and CarriedTotalRollN abilities then make rolls and perform the necessary functions to track the values (reducing the remaining dice by 1, concatenating the latest-rolled-value to the values already rolled, etc.) There's a lot more in terms of metascript interplay going on that I can get into, but I'll wait to see if you actually want that part to be explained before I subject you to the deeper ends of the metascipt pool. =D Expanding and Making It Your Own Obviously, you're going to want to make this your own, if you decide to implement it. As mentioned, change "MuleCharacter" to whatever character will house the abilities you create. Change the ?{Skill} roll query in the CarriedTotalFirstRoll ability (the second line) to be a list of skills that fit your game (removing "ThisSkill" and "ThatSkill" and adding the ones that come from your game system) Ideally, you would be pulling the number of d6 in your pool from some attribute on your character sheet. If so, you will likely want to tie that retrieval to the ?{Skill} query (i.e., if you note this is "Sleuthing", then your sheet would ideally have a Sleuthing attribute set to the value of d6). If your ?{Skill} query contains the actual names of the attributes, then you can use the query return in a Fetch construction (another metascipt) to get the value: @(MuleCharacter.?{Skill}) You would use that to set both the StartingDice and RemainingDice variables in the CarriedTotalFirstRoll ability. If you can't see how, I can help. Also, since we use the ?{Skill} query to present the title of the templated output, you might be "prettifying" the attribute name (i.e., listing the skill as "This Skill" rather than "ThisSkill", as it appears on the sheet). In that case, we can still translate it and make it work. Also-also, if the attribute actually says something like "4d6" rather than "4"... we can work with that, too, but you'll just have to share the state of things before I can tell you exactly what we need to do. Basically, this is just a proof of concept that something like what you're looking for is possible, but as there are many different ways your game could diverge from any assumptions I would make, I'll hold off getting too specific about any of the changes until you post back.
1719056856
David M.
Pro
API Scripter
Just because GiGs said it couldn't be done with Scriptcards j/k ;) I think this does what you want, if I'm understanding the mechanics. It doesn't rely on storing results on a character sheet. Rather, it uses a feature in SC called reentrant buttons, in which the current status of the procedure is stored in the State object. Normally, you pass a parameter back into the macro via the reentrant button, but in our case we just pass a dummy value, since the current values of our rollTotal and diceRemaining variables are still held in memory. The --:Resolve code block is written in long form since SC cannot handle nested conditionals.&nbsp; !script {{ --#title|Skill Challenge --=diceRemaining|?{How many dice?|3} --=target|?{Target # for Advance?|7} --#leftsub|Advance target: [$target] --#rightsub|Dice Pool: [$diceRemaining] --#reentrant|[&amp;SendingPlayerID] --#titlecardbackgroundimage|linear-gradient(to bottom, #666666, #000000) --#oddRowBackground|#dddddd --#evenRowBackground|#aaaaaa --#diceFontColor|#000000 --#buttonFontSize|18px --#bodyFontSize|18px --#diceFontSize|36px --#buttonBackgroundImage|linear-gradient(to bottom, #666666, #000000) --:THIS IS THE REENTRANT POINT FOR REROLLS| --:ReentryReroll| --=thisRoll|1d6 --=diceRemaining|[$diceRemaining] - 1 --=rollTotal|[$rollTotal] + [$thisRoll] --&amp;thisRollStr|[d6][$thisRoll.Raw][/d6] --&amp;allRolls|+[&amp;thisRollStr] --+|[&amp;allRolls] --+Current Total|[$rollTotal] --+Num Dice Remaining|[$diceRemaining] --?[$diceRemaining] -gt 0|[ --+Roll again?|[rbutton]Yes::ReentryReroll;dummy[/rbutton] / [rbutton]No::Resolve;dummy[/rbutton] --]|[ --^Resolve| goto Resolve branch --]| --X| End macro --:Resolve| --+Result:|[$rollTotal] vs Target [$target] --?[$rollTotal] -ge [$target] -and [$diceRemaining] -eq 0|[ --+[#009900][b]Advance![/b][/#]| --]| --?[$rollTotal] -ge [$target] -and [$diceRemaining] -gt 0|[ --+[#009900][b]Advance![/b][/#]| --+Gained a Push!| --]| --?[$rollTotal] -lt [$target]|[ --+[#990000][b]Did not advance[/b][/#]| --]| }} Here's sample output for an Advance with earning a push. We rolled a 4, then another 4, vs a target of 7. We click "No" and it gives us the final result. Here's an example of failing the check because we run out of dice before hitting the target of 18.
1719085446
GiGs
Pro
Sheet Author
API Scripter
David M. said: Just because GiGs said it couldn't be done with Scriptcards j/k ;) That's kind of flattering, actually. And if anyone can do it with ScriptCards, it's you.
1719091562

Edited 1719091939
David M. said: Just because GiGs said it couldn't be done with Scriptcards j/k ;) Oh neat! I was just looking at reentrant buttons and trying to figure out it they would work. This example is super helpful! I think the one thing I'd need to do is to ask the player at then end if they have any extra dice to add that weren't part of the initial pool or if they are done. The mechanics you all have built are how it is done...but the one little wrinkle is that after you are done with the dice you start with, if you don't like what score you got...you can possibly take on an extra problem for an extra die...but if you do that, you are definitely not getting a push.&nbsp; So...something like an "add an extra die or end?" Prompt once the initial dice pool is done would basically finish it. So...random question I was going to experiment with...but maybe you all already know the answer.&nbsp; All the ScriptCards macros I've experimented with (which is mostly for 2d6 dungeon at the moment), are macros I built in the macro tab and just had show up in the macro bar. For Night's Black Agents, I'm building a character sheet. Can I have a roll/action button on the character sheet call a scriptcards macro? I mean...that makes sense, right? I assume that is doable? ETA: Oh, David! I used some of your posts to figure out how to do the 2d6 Dungeon macros to show a variable number of dice. Thank you for that post you did back when! My current project with that is to figure out how to to do d66 rolls and have them show up and read from a rollable table...because...that isn't quite standard.
1719140526
David M.
Pro
API Scripter
Ok, try the version below. The biggest change is instead of passing a dummy value from the reentrant button, we are passing a 0 or 1 to indicate whether the die roll is an extra die (1) or a regular dice pool roll (0). This is the line that reads the reentry parameter/argument. Note that in other applications this argument could be any string. For example, a comma-delimited string that you could read into an array, etc. For our case it's just a simple binary value, and we assign the numeric string value to a roll variable. &nbsp; --=extraDie|[&amp;reentryval] There's obviously also some modified logic in there now to handle this new variable. If this doesn't work exactly how you envisioned, it should at least give you an idea of how you might approach it.&nbsp; !script {{ --#title|Skill Challenge --=diceRemaining|?{How many dice?|3} --=target|?{Target # for Advance?|7} --#leftsub|Advance target: [$target] --#rightsub|Dice Pool: [$diceRemaining] --#reentrant|[&amp;SendingPlayerID] --#titlecardbackgroundimage|linear-gradient(to bottom, #666666, #000000) --#oddRowBackground|#dddddd --#evenRowBackground|#aaaaaa --#diceFontColor|#000000 --#buttonFontSize|18px --#bodyFontSize|18px --#diceFontSize|36px --#buttonBackgroundImage|linear-gradient(to bottom, #666666, #000000) --=extraDie|0 --:THIS IS THE REENTRANT POINT FOR REROLLS| --:ReentryReroll| --=extraDie|[&amp;reentryval] --=thisRoll|1d6 --=rollTotal|[$rollTotal] + [$thisRoll] --?[$extraDie] -eq 1|[ --&amp;thisRollStr| Extra Die: [d6][$thisRoll.Raw][/d6] --]|[ --=diceRemaining|[$diceRemaining] - 1 --&amp;thisRollStr|[d6][$thisRoll.Raw][/d6] --]| --&amp;allRolls|+[&amp;thisRollStr] --+|[&amp;allRolls] --+Current Total|[$rollTotal] --+Num Dice Remaining|[$diceRemaining] --?[$rollTotal] -ge [$target] -or [$extraDie] -eq 1|[ --^Resolve| goto Resolve branch --]| --?[$diceRemaining] -ge 1 -and [$extraDie] -ne 1 -and [$rollTotal] -lt [$target]|[ --+Roll again?|[rbutton]Yes::ReentryReroll;0[/rbutton] / [rbutton]No::Resolve;0[/rbutton] --]| --?[$diceRemaining] -lt 1 -and [$extraDie] -eq 0 -and [$rollTotal] -lt [$target]|[ --+Out of Dice!|[rbutton]Extra Die?::ReentryReroll;1[/rbutton] / [rbutton]Done::Resolve;0[/rbutton] --]| --X| End macro --:Resolve| --+Result:|[$rollTotal] vs Target [$target] --?[$rollTotal] -ge [$target] -and [$diceRemaining] -eq 0|[ --+[#009900][b]Advance![/b][/#]| --=pushEligible|0 --]| --?[$rollTotal] -ge [$target] -and [$diceRemaining] -gt 0|[ --+[#009900][b]Advance![/b][/#]| --=pushEligible|1 --]| --?[$rollTotal] -lt [$target]|[ --+[#990000][b]Did not advance[/b][/#]| --=pushEligible|0 --]| --:Check for Push| --?[$pushEligible] -eq 1 -and [$extraDie] -eq 0|[ --+Gained a Push!| --]| }} Regarding having a sheet button call a scriptcards macro: I've never made a sheet, but I'm sure I've read about authors doing this. I think there's some protocol or considerations to make when publishing a sheet that is dependent on an api script (?), but others would have to chime in on this one.