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

I need help with a Final Fantasy RPG (4th edition) Initiative macro

1553359350

Edited 1553359603
So to explain I've been working on building a custom character sheet for the revised 4th edition of the Final Fantasy RPG (never touched HTML before, only wiremod and gamemaker 2). While I've got all the fields down and the sheet is pretty much good to go there is one thing that is bothering me. The way initiative is played out in this game is the party and monsters roll d10s (players roll a default of 3d10 but enemies can roll anywhere from 2 for minions or 5 for bosses) and take actions in ascending order from 1 to 10 with a few tiebreakers. Players may also use 2 initiative dice to act outside their normal turn order for emergency healing and such. The problem is that rolling and typing in 3d10 for all four of my players and however many the monsters need every round can really kill the pace of the game but the &{tracker} doesn't create more than one initiative step on the tracker so a macro for "/roll 1d10 &{tracker}" doesn't work and these rolls need to all be on the tracker at the start of the round, it would also be great to do it automatically so when players spend 2 initiative steps to act out of order I can delete the spent steps from the tracker and have it automatically put back up next round. Also I have a slightly smaller question regarding repeating fieldsheets and macros. Do they account for the unique value assigned to each of them, e.g (a macro for casting fire refering to "@{spelldif} and @{spellmod}" for the fieldsheet segment the button is attached to. I really hope someone here can help because I've used all my problem solving energy today on silly first timer code mistakes. Also if anyone wants it I can post the code for the FFRPG 4th ed character sheet for anyone to look at and improve.
1553366981

Edited 1553366996
vÍnce
Pro
Sheet Author
Does each sheet include an initative attribute? Maybe something like; characters init <input name="attr_pc-init" value="[[3 d10&{tracker}]] "> monster/npc  init <input name="attr_npc-init" value="[[?{Init dice|2} d10&{tracker}]] "> Include an Initiative button on the sheet so player's can roll init for themselves and another for NPC/Monster's for the GM. If you want to roll a number of tokens at once, you might consider Aaron's GroupInit script.  Macros that originate within a repeating/fieldset can reference the other attributes within that repeating/fieldset by their direct attribute name, while a macro outside of a repeating/fieldset referencing an attribute that originates within a repeating/fieldset will require the full/longer name ie @{repeating_spells_$X_foo}, where X is either the row number, or $X is the rowId.
Cheers for the help, the main problem I'm having is easily getting three different initiative values per player per round, its not the total of 3d10, its 3 separate actions taken, each dice is its own step, so if you roll "1, 4, 8" and a monster rolled "2,3,9" then you go first followed by two monster turns and then you take two and the monster takes one. then you re-roll at the end of the round. the problem is that &{tracker} replaces the previous step if there already is one so I'm wondering if there is any easy way to add 3 initiative steps, for the same character, at the same time. without dragging or right clicking every token three + times. the dream would be if i could have a macro run "/r1d10 &{tracker}" three times but that just gives you the last of the three rolls on one turn. no each roll having its own. That's the fieldset problem sorted though so I can get to work on that.
I'm not sure.
1553369569

Edited 1553371032
vÍnce
Pro
Sheet Author
@Callum I see. Thanks for the clarification. That sounds like a cool mechanic for initiative. You might be able to create a couple of other "placeholder" token's that are the same name as the character.  Running an initiative macro for each would send all three to the tracker with unique initiative lines. I'm still thinking on this... 
1553370788
Kraynic
Pro
Sheet Author
It isn't as granular as what you are doing, but I ran into a similar situation with the Palladium games I am running.&nbsp; In that game, it uses the d20 initiative, but any characters/npcs that have multiple attacks get their actions resolved one at a time in order instead of all actions at once.&nbsp; I altered my initiative to add 80 to the d20 initiative roll, and then The Aaron wrote a script to duplicate initiative entries, with each duplicate having the initiative number reduced by 20.&nbsp; That does keep all actions in a predictable order though, while it sounds like the multiple d10 is quite a bit more random. In case the script The Aaron wrote can work for you as a backup solution, or as inspiration for a more accurate solution for your system, it can be found here:&nbsp; <a href="https://app.roll20.net/forum/permalink/6817748/" rel="nofollow">https://app.roll20.net/forum/permalink/6817748/</a>
1553371116

Edited 1553373781
This game has certainly been full of challenges to macro, things like the digit dice of the d100 roll to hit is added to damage (e.g. if you rolled a 58 then your attack does 8 more damage while 50 would be 10 extra damage) not sure if all the macros are necessary but they are certainly enjoyable to put together. mainly just that initiative one that's stumped me cause I wasn't expecting the triple "&amp;{tracker}" macro to work like it did. but I'd recommend to anyone who wants to check it out and publish a decent character sheet to give it a go mainly for all the interesting systems.&nbsp;
In my games I Create a grid with 10 columns and place one token per init dia, something like this:&nbsp; &nbsp;
1553449940
vÍnce
Pro
Sheet Author
Nice option Bruno. I like it.&nbsp; Player's can even be responsible for placing their own token's on the "Initiative Grid".&nbsp; Do you also use a turn marker/flag to indicate the current turn?
1553450367

Edited 1553451170
vÍnce
Pro
Sheet Author
I wonder if the Group Initiative script could be modified to include the additional initiative rolls and placement on the tracker?&nbsp; edit : I've made an inquiry on the API forum here
Yep, the players move their own tokens to the grid as they roll init and off the grid as they perform actions. Also, a small circle around the phase numbers (moved by the GM) marks the current phase&nbsp;
1553489716

Edited 1553489797
The Aaron
Roll20 Production Team
API Scripter
Here's a first pass approximation of a script to do this. Select one or more tokens and run: !ffi to roll 3d10 and put them in the turn order. Or you can pass a number: !ffi 5 You can also use a formula: !ffi [[3+@{adjust}]] It will roll the given number of dice individually for each selected token.&nbsp; For visible tokens, it prints the rolls to chat, for GM layer tokens, it whispers them to the GM.&nbsp; It respects the sorting and tie breaking mechanic (Highest total sum of dice goes first in a tie), but only when rolls happen.&nbsp; If you remove turns for interrupting, you might need to manually adjust ties.&nbsp; Note, it will resort when a roll is made. I can probably add the mechanics for interrupting, and have it clear turns that have been used at a later point.&nbsp; Let me know if this works for you. Code: on('ready',()=&gt;{ const DIE_SIZE = 10; const DEFAULT_NUM_DICE = 3; const styles = { entry: { "font-size": ".8em" }, name: { "font-weight": "bold" }, roll: { "background-color": "#fff", "border": "1px solid #ddd", "border-radius": ".5em", "color": "#966", "font-family": "monospace", "line-height": "2em", "font-weight": "bold", "width": "2em", "height": "2em", "overflow": "auto", "text-align": "center", "display": "inline-block" } }; const processInlinerolls = (msg) =&gt; { if(_.has(msg,'inlinerolls')){ return _.chain(msg.inlinerolls) .reduce(function(m,v,k){ let ti=_.reduce(v.results.rolls,function(m2,v2){ if(_.has(v2,'table')){ m2.push(_.reduce(v2.results,function(m3,v3){ m3.push(v3.tableItem.name); return m3; },[]).join(', ')); } return m2; },[]).join(', '); m['$[['+k+']]']= (ti.length &amp;&amp; ti) || v.results.total || 0; return m; },{}) .reduce(function(m,v,k){ return m.replace(k,v); },msg.content) .value(); } else { return msg.content; } }; const s = (name) =&gt; { if(styles.hasOwnProperty(name)){ return `style="${Object.keys(styles[name]).reduce((m,k)=&gt;`${m}${k}:${styles[name][k]};`,'')}"`; } return ''; }; const getTurnArray = () =&gt; ( '' === Campaign().get('turnorder') ? [] : JSON.parse(Campaign().get('turnorder'))); const setTurnArray = (ta) =&gt; Campaign().set({turnorder: JSON.stringify(ta)}); const addTokenTurn = (id, pr) =&gt; Campaign().set({ turnorder: JSON.stringify( [...getTurnArray(), {id,pr}]) }); const addCustomTurn = (custom, pr) =&gt; Campaign().set({ turnorder: JSON.stringify( [...getTurnArray(), {id:-1,custom,pr}]) }); const removeTokenTurn = (tid) =&gt; Campaign().set({ turnorder: JSON.stringify( getTurnArray().filter( (to) =&gt; to.id !== tid)) }); const clearTurnOrder = () =&gt; Campaign().set({turnorder:'[]'}); const sorter_asc = (a, b) =&gt; b.pr - a.pr; const sorter_desc = (a, b) =&gt; a.pr - b.pr; const sortTurnOrder = (sortBy = sorter_desc) =&gt; Campaign().set({turnorder: JSON.stringify(getTurnArray().sort(sortBy))}); const sorter_ascFF4 = (lookup) =&gt; (a, b) =&gt; { let dir = a.pr - b.pr; if( 0 === dir) { dir = lookup[b.id] - lookup[a.id]; } return dir; }; const buildFF4Lookup = (ta) =&gt; ta.reduce((m,o)=&gt;{ m[o.id]=(m[o.id]||0)+o.pr; return m; },{}); const doRolls = (num=DEFAULT_NUM_DICE) =&gt; [...Array(num)].map(()=&gt;randomInteger(DIE_SIZE)); on('chat:message',(msg)=&gt;{ if('api'===msg.type &amp;&amp; /^!ffi\b/i.test(msg.content)){ let c = processInlinerolls(msg); // !ffi &lt;NumRolls&gt; let args = c.split(/\s+/); let output = []; let outputPrivate = []; if(msg.selected){ msg.selected .map(o=&gt;getObj('graphic',o._id)) .filter(g=&gt;undefined !== g) .map(t =&gt; ({token:t,rolls:doRolls(parseInt(args[1],10)||undefined)})) .filter(o=&gt;removeTokenTurn(o.token.id) || true) .filter(o=&gt;o.rolls.forEach(r=&gt;addTokenTurn(o.token.id,r))||true) .forEach(o=&gt;{ let m=`&lt;div ${s('entry')}&gt;&lt;span ${s('name')}&gt;${o.token.get('name')}&lt;/span&gt; rolled: ${ o.rolls.map(r=&gt;`&lt;span ${s('roll')}&gt;${r}&lt;/span&gt;`).join(' ') }&lt;/div&gt;`; if('objects' === o.token.get('layer')){ output.push(m); } else { outputPrivate.push(m); } }) ; let to = getTurnArray(); let lookup = buildFF4Lookup(to); sortTurnOrder(sorter_ascFF4(lookup)); if(output.length){ log(output.join('')); sendChat('FF4 Init', output.join('')); } if(outputPrivate.length){ sendChat('FF4 Init', `/w "gm" ${outputPrivate.join('')}`); } } } }); });
1553533989

Edited 1553534047
Thanks Aaron that's works perfectly, also thank you to everyone else to helped out, once I'm happy with the sheet I'll try and get it published or at least share the code. I assume I just copy paste that into the API?
1553549199
The Aaron
Roll20 Production Team
API Scripter
Yup, just copy that code and put it in a new tab in the API section of the Game's Settings:
1553552361
vÍnce
Pro
Sheet Author
Aaron is awesome! Last request, could the script be modified to "auto-sort" the entire tracker in ascending order after each time you add initiatives using !ffi?
1553556222
The Aaron
Roll20 Production Team
API Scripter
It does for me, is that not working for you?
1553560271

Edited 1664659918
The Aaron
Roll20 Production Team
API Scripter
Ok, made an adjusted version that adds in !eot (or !feot in case you have something else doing eot stuff you don't want to trigger), as well as an end marker and resorting when things are changed in the turn order.&nbsp; That makes it easy to remove turns for interrupt (it will respect the change in sorting when your total drops lower than someone else's) or adjust the value of turns for some reason. !eot, !feot, and just clicking the arrow to advance the turn will remove the top turn from the turn order. Example: Gish interrupts and uses their 5 and 10, resulting in the tie breaker order for 6 swapping.&nbsp; In this case, the GM just trashes those two turns for Gish causing the resort to happen. Example: Running !eot, Rook's 2 entry has been removed.&nbsp; Only the GM or someone that controls the current token can issue !eot or !feot. Update 10/1/2022:&nbsp; Fixed for new turnorder pageid requirement. on('ready',()=&gt;{ const DIE_SIZE = 10; const DEFAULT_NUM_DICE = 3; const END_LABEL = '--- END ---'; const styles = { entry: { "font-size": ".8em" }, name: { "font-weight": "bold" }, roll: { "background-color": "#fff", "border": "1px solid #ddd", "border-radius": ".5em", "color": "#966", "font-family": "monospace", "line-height": "2em", "font-weight": "bold", "width": "2em", "height": "2em", "overflow": "auto", "text-align": "center", "display": "inline-block" } }; const playerCanControl = (obj, playerid='any') =&gt; { const playerInControlledByList = (list, playerid) =&gt; list.includes('all') || list.includes(playerid) || ('any'===playerid &amp;&amp; list.length); let players = obj.get('controlledby') .split(/,/) .filter(s=&gt;s.length); if(playerInControlledByList(players,playerid)){ return true; } if('' !== obj.get('represents') ) { players = (getObj('character',obj.get('represents')) || {get: function(){return '';} } ) .get('controlledby').split(/,/) .filter(s=&gt;s.length); return playerInControlledByList(players,playerid); } return false; }; const processInlinerolls = (msg) =&gt; { if(_.has(msg,'inlinerolls')){ return _.chain(msg.inlinerolls) .reduce(function(m,v,k){ let ti=_.reduce(v.results.rolls,function(m2,v2){ if(_.has(v2,'table')){ m2.push(_.reduce(v2.results,function(m3,v3){ m3.push(v3.tableItem.name); return m3; },[]).join(', ')); } return m2; },[]).join(', '); m['$[['+k+']]']= (ti.length &amp;&amp; ti) || v.results.total || 0; return m; },{}) .reduce(function(m,v,k){ return m.replace(k,v); },msg.content) .value(); } else { return msg.content; } }; const s = (name) =&gt; { if(styles.hasOwnProperty(name)){ return `style="${Object.keys(styles[name]).reduce((m,k)=&gt;`${m}${k}:${styles[name][k]};`,'')}"`; } return ''; }; const getTurnArray = () =&gt; ( '' === Campaign().get('turnorder') ? [] : JSON.parse(Campaign().get('turnorder'))); const setTurnArray = (ta) =&gt; Campaign().set({turnorder: JSON.stringify(ta)}); const addTokenTurn = (id, pr, pageid) =&gt; setTurnArray([...getTurnArray(), {id,pr,_pageid:(pageid||(getObj('graphic',id)||{get:''}).get('pageid'))}]); const addCustomTurn = (custom, pr) =&gt; Campaign().set({ turnorder: JSON.stringify( [...getTurnArray(), {id:'-1',custom,pr}]) }); const removeTokenTurn = (tid) =&gt; Campaign().set({ turnorder: JSON.stringify( getTurnArray().filter( (to) =&gt; to.id !== tid)) }); const clearTurnOrder = () =&gt; Campaign().set({turnorder:'[]'}); const sorter_asc = (a, b) =&gt; b.pr - a.pr; const sorter_desc = (a, b) =&gt; a.pr - b.pr; const sortTurnOrder = (sortBy = sorter_desc) =&gt; Campaign().set({turnorder: JSON.stringify(getTurnArray().sort(sortBy))}); const sorter_ascFF4 = (lookup) =&gt; (a, b) =&gt; { if(a.custom===END_LABEL){ return 1; } if(b.custom===END_LABEL){ return -1; } let dir = a.pr - b.pr; if( 0 === dir) { dir = lookup[b.id] - lookup[a.id]; } return dir; }; const buildFF4Lookup = (ta) =&gt; ta.reduce((m,o)=&gt;{ m[o.id]=(m[o.id]||0)+o.pr; return m; },{}); const doRolls = (num=DEFAULT_NUM_DICE) =&gt; [...Array(num)].map(()=&gt;randomInteger(DIE_SIZE)); on('change:campaign:turnorder', (obj,prev) =&gt; { let to = getTurnArray(); let told = (( '' === prev.turnorder) ? [] : JSON.parse(prev.turnorder)); let l = to.pop(); let f = told.shift(); if(f &amp;&amp; l &amp;&amp; f.id === l.id &amp;&amp; f.pr === l.pr){ setTurnArray(to); } else { assureEndLabel(); } to = getTurnArray(); let lookup = buildFF4Lookup(to); sortTurnOrder(sorter_ascFF4(lookup)); }); const assureEndLabel = () =&gt; { let to = getTurnArray(); let f = to.find((e)=&gt;END_LABEL===e.custom); if(!f){ addCustomTurn(END_LABEL,''); to = getTurnArray(); let lookup = buildFF4Lookup(to); sortTurnOrder(sorter_ascFF4(lookup)); } }; on('chat:message',(msg)=&gt;{ if('api'===msg.type) { if(/^!ffi\b/i.test(msg.content)){ let c = processInlinerolls(msg); // !ffi &lt;NumRolls&gt; let args = c.split(/\s+/); let output = []; let outputPrivate = []; if(msg.selected){ msg.selected .map(o=&gt;getObj('graphic',o._id)) .filter(g=&gt;undefined !== g) .map(t =&gt; ({token:t,rolls:doRolls(parseInt(args[1],10)||undefined)})) .filter(o=&gt;removeTokenTurn(o.token.id) || true) .filter(o=&gt;o.rolls.forEach(r=&gt;addTokenTurn(o.token.id,r,o.token.get('pageid')))||true) .forEach(o=&gt;{ let m=`&lt;div ${s('entry')}&gt;&lt;span ${s('name')}&gt;${o.token.get('name')}&lt;/span&gt; rolled: ${ o.rolls.map(r=&gt;`&lt;span ${s('roll')}&gt;${r}&lt;/span&gt;`).join(' ') }&lt;/div&gt;`; if('objects' === o.token.get('layer')){ output.push(m); } else { outputPrivate.push(m); } }) ; let to = getTurnArray(); let lookup = buildFF4Lookup(to); sortTurnOrder(sorter_ascFF4(lookup)); if(output.length){ log(output.join('')); sendChat('FF4 Init', output.join('')); } if(outputPrivate.length){ sendChat('FF4 Init', `/w "gm" ${outputPrivate.join('')}`); } } } else if( /^!f?eot\b/i.test(msg.content)){ let to = getTurnArray(); let token = getObj('graphic',(to[0]||{id:-1}).id); if(token &amp;&amp; (playerIsGM(msg.playerid) || playerCanControl(token,msg.playerid))){ to.shift(); setTurnArray(to); let lookup = buildFF4Lookup(to); sortTurnOrder(sorter_ascFF4(lookup)); } else { let who = getObj('player',msg.playerid).get('_displayname'); sendChat('FF4 Init', `/w "${who}" &lt;div ${s('entry')}&gt;It is not one of your character's turns right now.&lt;/div&gt;`); } } } }); assureEndLabel(); });
1553561706
vÍnce
Pro
Sheet Author
The Aaron said: It does for me, is that not working for you? I just tested it real quick last night, so I may not have total recall.&nbsp; This updated version has gone above and beyond the request.&nbsp; As always...&nbsp; Thanks Aaron ™ .
1553562079
The Aaron
Roll20 Production Team
API Scripter
=D No prob. =D
I tested it out in a game Monday night... Players and I enjoyed it...was much better than manually entering values. THANK YOU... .like Vince said... Also thanks for the update as well...will give that a shot next time... :)
1553708528
The Aaron
Roll20 Production Team
API Scripter
No problem, happy to help. =D
Figured I should put my character sheet up here, Its not much to look at but for a first time with self taught html I'm pretty proud of it. &lt;div class='3colrow'&gt; &lt;div class='col'&gt; &lt;!-- Put the content for the first column here --&gt; Name &lt;input type="text" name="attr_character_name" /&gt; &lt;br/&gt; Group &lt;input type="text" name="attr_groupname" /&gt; &lt;br/&gt; Main Job &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;input type="text" name="attr_Mainjob" style="width: 8em" /&gt; &lt;br/&gt;&nbsp; Secondary Job &lt;input type="text" name="attr_Secjob" style="width: 8em" /&gt; &lt;br/&gt; Level &lt;input type="number" name="attr_level" value="(@{EarthLevel}+@{AirLevel}+@{FireLevel}+@{WaterLevel})" disabled="true" /&gt; XP Points &lt;Input type="number" name="attr_Exp" style="width: 5em" value="200" /&gt; &lt;br/&gt;&lt;br/&gt;&lt;br/&gt; &lt;Label&gt;STATS&lt;/Label&gt; &nbsp; &nbsp; EARTH &lt;Input type="number" name="attr_EarthLevel" Value="floor(@{EarthV}/10)" disabled="true" /&gt; &lt;Input type="number" name="attr_EarthV" /&gt; &lt;Input type="number" name="attr_EarthXP" style="width:5em" /&gt; &lt;br/&gt; &nbsp; &nbsp; AIR &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;Input type="number" name="attr_AirLevel" Value="floor(@{AirV}/10)" disabled="true" /&gt; &lt;Input type="number" name="attr_AirV" /&gt; &lt;Input type="number" name="attr_AirXP" style="width:5em" /&gt; &lt;br/&gt; &nbsp; &nbsp; FIRE &amp;nbsp; &amp;nbsp; &lt;Input type="number" name="attr_FireLevel" Value="floor(@{FireV}/10)" disabled="true" /&gt; &lt;Input type="number" name="attr_FireV" /&gt; &lt;Input type="number" name="attr_FireXP" style="width:5em" /&gt; &lt;br/&gt; &nbsp; &nbsp; WATER &lt;Input type="number" name="attr_WaterLevel" Value="floor(@{WaterV}/10)" disabled="true" /&gt; &lt;Input type="number" name="attr_WaterV" /&gt; &lt;Input type="number" name="attr_WaterXP" style="width:5em" /&gt; &lt;br/&gt; &lt;br/&gt; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; HP &lt;input type="number" name="attr_HP" min="0" Max="@{MaxHP}" style="width 5em" Value="0" /&gt; &nbsp; &nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; MP &lt;input type="number" name="attr_MP" min="0" Max="@{MaxMP}" style="width 5em" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; Max HP &lt;input type="number" name="attr_MaxHP" style="width: 5em" value="(@{level}*@{HPmod}+@{EarthV})" disabled="true" /&gt; &amp;nbsp; &amp;nbsp;&nbsp; &nbsp; &nbsp; Max MP &lt;input type="number" name="attr_MaxMP" style="width: 5em" value="(@{level}*@{MPmod}+@{WaterV})" disabled="true" /&gt; &lt;br/&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; HP Modifier &lt;input type="number" name="attr_HPmod" Value="0" /&gt; &amp;nbsp; &amp;nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MP Modifier &lt;input type="number" name="attr_MPmod" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp;&nbsp; &lt;hg&gt;Actions&lt;/hg&gt; &nbsp; &nbsp; &lt;fieldset class="repeating_Actions"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;input type="text" name="attr_actionname" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;select name="attr_ACT_Type" style="width: 5em"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="0"&gt;None&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{EarthV}"&gt;Earth&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{AirV}"&gt;Air&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{FireV}"&gt;Fire&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{WaterV}"&gt;Water&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/select&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; VS &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;select name="attr_ACT_VSType" style="width: 5em"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="None"&gt;None&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="earth"&gt;Earth&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="Air"&gt;Air&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="Fire"&gt;Fire&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="Water"&gt;Water&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/select&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dif &lt;input type="number" name="attr_ACTDif" /&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DMG x&lt;input type="number" name="attr_ACTDMGMOD" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;select name="attr_ACTModEle" style="width: 5em"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="0"&gt;None&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{EarthLevel}"&gt;Earth&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{AirLevel}"&gt;Air&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{FireLevel}"&gt;Fire&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{WaterLevel}"&gt;Water&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{level}"&gt;Level&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/select&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Effects &lt;input type="text" name="attr_SpellEffect" style="width: 13em" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;button type="roll" value="&amp;{template:default} {{name=@{actionname}}} {{attack=[[1d100+@{ACT_Type}-@{ACTDif}]]}} {{damage=[[floor(@{ACTMODEle})*@{ACTDMGMOD}]]}}" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt; &lt;br/&gt; &lt;br/&gt; &nbsp; &nbsp; &lt;/fieldset&gt; &nbsp; &nbsp; &lt;br/&gt; &lt;br/&gt; &lt;hg&gt;Proficiencies&lt;/hg&gt; &nbsp; &nbsp; &lt;fieldset class="repeating_proficiencies"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;select name="attr_proftype" Class="Proftype" style="width: 5em"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="WPN"&gt;WPN&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="ARM"&gt;ARM&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/select&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;input type="text" name="attr_profname" style="width: 14em" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt; &nbsp; &nbsp; &lt;/fieldset&gt; &lt;/div&gt; &lt;div class='col'&gt; &lt;!-- Second column --&gt; &lt;label&gt;SKILLS&lt;/label&gt; &nbsp; &nbsp; &lt;label&gt;Earth&lt;/label&gt; &nbsp; &nbsp; &nbsp; &nbsp; Strength &lt;input type="number" name="attr_Skill_Strength" Value="0" /&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Climbing &lt;input type="number" name="attr_Skill_Climbing" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; Swimming &lt;input type="number" name="attr_Skill_Swimming" Value="0" /&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Intimidation &lt;input type="number" name="attr_Skill_Intimidation" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; Tolerance &lt;input type="number" name="attr_Skill_Tolerance" Value="0" /&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Jumping &lt;input type="number" name="attr_Skill_Jumping" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; &lt;label&gt;Air&lt;/label&gt; &nbsp; &nbsp; &nbsp; &nbsp; Running &lt;input type="number" name="attr_Skill_Running" Value="0" /&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Stealth &lt;input type="number" name="attr_Skill_Stealth" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; Piloting &lt;input type="number" name="attr_Skill_Piloting" Value="0" /&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Riding &lt;input type="number" name="attr_Skill_Riding" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; Theivery &lt;input type="number" name="attr_Skill_Thievery" Value="0" /&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Acrobatics &lt;input type="number" name="attr_Skill_Acrobatics" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; &lt;label&gt;Fire&lt;/label&gt; &nbsp; &nbsp; &nbsp; &nbsp; Infiltration &lt;input type="number" name="attr_Skill_Infiltration" Value="0" /&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Perception &lt;input type="number" name="attr_Skill_Perception" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; Medicine &lt;input type="number" name="attr_Skill_Medicine" Value="0" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; Survival &lt;input type="number" name="attr_Skill_Survival" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; Technology &lt;input type="number" name="attr_Skill_Technology" Value="0" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; Wisdsom &lt;input type="number" name="attr_Skill_Wisdom" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; &lt;label&gt;Water&lt;/label&gt; &nbsp; &nbsp; &nbsp; &nbsp; Willpower &lt;input type="number" name="attr_Skill_Willpower" Value="0" /&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Bluff &lt;input type="number" name="attr_Skill_Bluff" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; Animal Handling &lt;input type="number" name="attr_Skill_Animal_Handling" Value="0" /&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Charisma &lt;input type="number" name="attr_Skill_Charisma" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; Performance &lt;input type="number" name="attr_Skill_Performance" Value="0" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; Magic &lt;input type="number" name="attr_Skill_Magic" Value="0" /&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &lt;br/&gt;&lt;br/&gt;&lt;br/&gt; &lt;h3&gt;Traits &amp; Quirks&lt;/h3&gt; &nbsp; &nbsp; &lt;fieldset class="repeating_Traits"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;input type="text" name="attr_Traitname" style="width: 10em" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;Select name="attr_Trait_Type" class="Trait_Type" style="width: 6em"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="Trait"&gt;Trait&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="Quirk"&gt;Quirk&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/Select&gt; &nbsp; &nbsp; &lt;/fieldset&gt; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &lt;/div&gt; &lt;div class='col'&gt; &lt;!-- Third column --&gt; &lt;label&gt;SPELLS AND EQUIPMENT&lt;/label&gt; &nbsp; &nbsp; &lt;h3&gt;Weapons&lt;/h3&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;fieldset class="repeating_Weapons"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name &lt;input type="text" name="attr_weaponname" style="width: 9em" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DMG x &lt;input type="number" name="attr_weaponmod" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Effects &lt;input type="text" name="attr_weaponeffects" style="width: 13em" /&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;button type="roll" Value="&amp;{template:default} {{name=!Attack}} {{attack=[[1d100+@{EarthV}-40]]}} {{damage=[[@{EarthLevel}*@{weaponmod}]]}}" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/fieldset&gt; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &lt;br/&gt; &nbsp; &nbsp; &lt;h3&gt;Armor&lt;/h3&gt; &nbsp; &nbsp; &nbsp; &nbsp; Name &lt;Input type="text" name="attr_armorname" style="width: 12em" /&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; &amp;nbsp; ARM &lt;input type="number" name="attr_ARM" /&gt; &amp;nbsp; MARM &lt;input type="number" name="attr_MARM" /&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; effects &lt;input type="text" name="attr_armeffect" /&gt; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &lt;br/&gt; &lt;br/&gt; &lt;h3&gt;Abilities&lt;/h3&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;fieldset class="repeating_abilities"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;input Type="text" name="attr_ABL" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/fieldset&gt; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &lt;br/&gt; &lt;br/&gt; &lt;h3&gt;Spells&lt;/h3&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;fieldset class="repeating_Spells"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name &lt;input type="text" name="attr_spellname" style="width: 10em" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MP &lt;input type="number" name="attr_SpellMP" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;select name="attr_Spell_Type" style="width: 5em"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="0"&gt;None&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{EarthV}"&gt;Earth&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{AirV}"&gt;Air&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{FireV}"&gt;Fire&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{WaterV}"&gt;Water&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/select&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; VS &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;select name="attr_Spell_VSType" style="width: 5em"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="None"&gt;None&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="earth"&gt;Earth&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="Air"&gt;Air&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="Fire"&gt;Fire&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="Water"&gt;Water&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/select&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dif &lt;input type="number" name="attr_SpellDif" /&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DMG x&lt;input type="number" name="attr_SpellDMGMOD" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;select name="attr_SpellDMGEle" style="width: 5em"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="0"&gt;None&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{EarthLevel}"&gt;Earth&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{AirLevel}"&gt;Air&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{FireLevel}"&gt;Fire&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{WaterLevel}"&gt;Water&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="@{level}"&gt;Level&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/select&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Effects &lt;input type="text" name="attr_SpellEffect" style="width: 13em" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;button type="roll" value="&amp;{template:default} {{name=@{spellname}}} {{attack=[[1d100+@{Spell_Type}-@{SpellDif}]]}} {{damage=[[floor(@{SpellDMGEle}*@{SpellDMGMOD}]]}}" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt; &lt;br/&gt; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/fieldset&gt; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &lt;br/&gt; &lt;br/&gt; &lt;h3&gt;Inventory&lt;/h3&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;fieldset class="repeating_INV"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;input type="text"name="attr_INV_NAME" style="width: 13em" /&gt; Qnt &lt;input type="number" name="attr_INVQnt" /&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/fieldset&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt; &nbsp; &nbsp; &nbsp; &nbsp; GIL &lt;input type="number" name="attr_GIL" Style="width: 5em" value="200" &lt;/div&gt; &lt;/div&gt; Any tips from anyone who knows this stuff better would be great, I hope some people can get good use out of this since roll20 doesn't have one published yet but i think I'll pretty it up beforehand.
1553734459

Edited 1553734515
GiGs
Pro
Sheet Author
API Scripter
You'd be better off posting that in the character sheets forum, and asking for tips there. I think it would be a good thing, too. It's a shame more people dont post their works in progress and ask for tips or showcase techniques there.