diff --git a/The One Ring 2e/assets/background.jpg b/The One Ring 2e/assets/background.jpg new file mode 100644 index 0000000000..15a59182d0 Binary files /dev/null and b/The One Ring 2e/assets/background.jpg differ diff --git a/The One Ring 2e/assets/background.webp b/The One Ring 2e/assets/background.webp deleted file mode 100644 index 021ab6c768..0000000000 Binary files a/The One Ring 2e/assets/background.webp and /dev/null differ diff --git a/The One Ring 2e/assets/background1.webp b/The One Ring 2e/assets/background1.webp deleted file mode 100644 index 021ab6c768..0000000000 Binary files a/The One Ring 2e/assets/background1.webp and /dev/null differ diff --git a/The One Ring 2e/images/leafes-border-red-small.png b/The One Ring 2e/images/leafes-border-red-small.png new file mode 100644 index 0000000000..25c6b7aa0c Binary files /dev/null and b/The One Ring 2e/images/leafes-border-red-small.png differ diff --git a/The One Ring 2e/images/leafes-border-red.png b/The One Ring 2e/images/leafes-border-red.png new file mode 100644 index 0000000000..b1f31ba407 Binary files /dev/null and b/The One Ring 2e/images/leafes-border-red.png differ diff --git a/The One Ring 2e/readme.md b/The One Ring 2e/readme.md index 057c3ea8e6..7c5b794e6c 100644 --- a/The One Ring 2e/readme.md +++ b/The One Ring 2e/readme.md @@ -16,7 +16,8 @@ More info: [Readme](https://github.com/Roll20/roll20-character-sheets/blob/maste - Rolls for skills, wisdom, valour, attack and protection including favoured/ illfavoured / weary modifiers and optional bonus dice - Automated calculation of total parry and protection depending on stance and equipped gear. - Automated calculation of load -- Attacks with optional selecting target and integrating target's parry +- Attacks with optionally selecting target and integrating target's parry +- Attack button macro bar support ### Adversarysheet ### diff --git a/The One Ring 2e/release-notes.md b/The One Ring 2e/release-notes.md index 618f82817e..28dbb411d0 100644 --- a/The One Ring 2e/release-notes.md +++ b/The One Ring 2e/release-notes.md @@ -2,6 +2,14 @@ This is a rewrite based on the early 2e (basic) and 1e edition that also includes a 2e sheet for adversaries. It features correct handling of favoured rolls, weary/miserable state, bonus dice and stance related bonus changes to attack rating, parry, protection and damage. # Release History +## 02.02.00 (Build 6) +- The macro bar is now available for parsed rolls (which is not easy to achieve as parsed roll buttons are action buttons and need special treatment to be available for the macro bar). You can drag / drop attack and protection rolls from the sheet into the macro bar and click those actions directly without opening the sheet. This is especially useful in conjunction with targeted attacks and will smooth and speed up battles. +### Bugfixes +- bugfix miserable +- bugfix favourill not initialized +- css cleanup +- fixing two issues that might have had an impact on the roll-template issue! (fingers crossed) + ## 02.01.00 (Build 5) ### Features - changed stance values from "Forward/Open/Defensive/Rearward" to "1/2/3/4" because this opens the way for players to easily toggle stance by using the token bar diff --git a/The One Ring 2e/sheet-adversaries.png b/The One Ring 2e/sheet-adversaries.png index d2c89676ba..2f287f59cf 100644 Binary files a/The One Ring 2e/sheet-adversaries.png and b/The One Ring 2e/sheet-adversaries.png differ diff --git a/The One Ring 2e/sheet.css b/The One Ring 2e/sheet.css index 1b4418edd7..acd53382d6 100644 --- a/The One Ring 2e/sheet.css +++ b/The One Ring 2e/sheet.css @@ -33,14 +33,15 @@ font-family: "Palatino Linotype", "Book Antiqua", Palatino, serif, sans-serif; font-weight: normal; } -.charsheet { +.charsheet, +.sheet-rolltemplate-tor { /* Define CSS variables */ --red: rgb(176, 33, 30); --gray: rgb(104, 104, 104); --solidborder: 1px solid var(--gray); - --borderred: url('https://raw.githubusercontent.com/bhuesemann/roll20-character-sheets/tor2e_02-00-00/The%20One%20Ring%202e/assets/boxline-border-red.png'); - --borderbrown: url('https://raw.githubusercontent.com/bhuesemann/roll20-character-sheets/tor2e_02-00-00/The%20One%20Ring%202e/assets/boxline-border-brown.png'); - --background: url('https://raw.githubusercontent.com/bhuesemann/roll20-character-sheets/tor2e_02-00-00/The%20One%20Ring%202e/assets/background1.webp'); + --borderred: url('https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/The%20One%20Ring%202e/assets/boxline-border-red.png'); + --borderbrown: url('https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/The%20One%20Ring%202e/assets/boxline-border-brown.png'); + --background: url('https://raw.githubusercontent.com/bhuesemann/roll20-character-sheets/tor2e_02-02-00/The%20One%20Ring%202e/assets/background.jpg'); padding: 0px; } @@ -68,7 +69,7 @@ .charsheet .sheet-tabstoggle[value="isAdversary"] ~ div.sheet-adversary { display: block; } -/* Generic element styls */ +/* Generic element styles */ .charsheet :is(h1,h2,h3){ font-family: "Aniron", "Palatino Linotype", "Book Antiqua", Palatino, serif, sans-serif; font-weight: normal; @@ -222,30 +223,16 @@ input[type='radio'] { margin-right: 8px; font-family: "Aniron", "Palatino Linotype", "Book Antiqua", Palatino, serif, sans-serif; } -.charsheet .sheet-dots input[type="radio"]:checked ~ input[type="radio"] + span { - -background: url("https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/The%20One%20Ring/assets/images/square-empty.png") no-repeat; - -background-size:100%; -} .sheet-dots input[type='radio']:checked ~ input[type='radio'] + span:before { - -background: url("https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/The%20One%20Ring/assets/images/square-empty.png") no-repeat; background-size:100%; border: 2px solid #AC4637; background-color: transparent; transform: rotate(45deg); } -.charsheet .sheet-dots input[type="radio"]:not([value="0"]) + span { - -background: url("https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/The%20One%20Ring/assets/images/square-filled.png") no-repeat; - -background-size:100%; - -border: 2px solid #AC4637; - -background-color: transparent; - -transform: rotate(45deg); -} .sheet-dots input[type="radio"]:not([value="0"]) + span:before { - -background: url("https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/The%20One%20Ring/assets/images/square-filled.png") no-repeat; background-size:100%; border: 2px solid #AC4637; background-color: #AC4637; - -background-image: url('https://singlecolorimage.com/get/AC4637/10x10'); transform: rotate(45deg); } /* Remove dot from all radios _after_ selected one */ @@ -327,6 +314,9 @@ input[type='radio'] { transform: rotate(-45deg); border: 0; } +.charsheet .hidden { + display: none; +} /* Borders */ .charsheet #content :is(#strength,#wits,#skill-strength,#skill-heart,#skill-wits,#conditions,#mount) { border: 5px solid transparent; @@ -741,6 +731,7 @@ input[type='radio'] { } .ui-dialog .charsheet :is( button[type="roll"][class~="table-rolls"], + button[type="roll"][class~="parsed-rolls"], button[type="action"][class~="parsed-rolls"]):hover { opacity: .5; } @@ -753,6 +744,7 @@ input[type='radio'] { } .ui-dialog .charsheet :is( button[type="roll"][class~="table-rolls"], + button[type="roll"][class~="parsed-rolls"], button[type="action"][class~="parsed-rolls"])::before { /* change D20 to system-appropriate D12 */ font-family: "dicefontd12"; @@ -885,10 +877,10 @@ input[type='radio'] { margin-left: -7px; } .sheet-rolltemplate-tor .sheet-container { - background: url('https://raw.githubusercontent.com/roll20/roll20-character-sheets/master/The%20One%20Ring%202e/assets/background1.webp'); + background: var(--background); background-color: #FEFCF0; border: 5px solid transparent; - border-image-source: url('https://raw.githubusercontent.com/roll20/roll20-character-sheets/master/The%20One%20Ring%202e/assets/boxline-border-red.png'); + border-image-source: var(--borderred); border-image-slice: 8 8 8 8; border-image-repeat: repeat; } @@ -967,7 +959,7 @@ input[type='radio'] { justify-self: center; border: 4px solid transparent; background-color: #FEFCF0; - border-image-source: url('https://raw.githubusercontent.com/roll20/roll20-character-sheets/master/The%20One%20Ring%202e/assets/boxline-border-brown.png'); + border-image-source: var(--borderbrown); /*border-image-source: url('https://raw.githubusercontent.com/bhuesemann/roll20-character-sheets/tor2e_02-00-00/The%20One%20Ring%202e/images/box-border-brown-rttd.png');*/ /*border-image-source: url('https://raw.githubusercontent.com/roll20/roll20-character-sheets/master/The%20One%20Ring%202e/images/box-border-brown-rttd.png');*/ border-image-slice: 8 8 8 8; @@ -1016,7 +1008,7 @@ input[type='radio'] { width: 45px !important; height: 45px !important; border: 5px solid transparent; - border-image-source: url('https://raw.githubusercontent.com/roll20/roll20-character-sheets/master/The%20One%20Ring%202e/assets/boxline-border-red.png'); + border-image-source: var(--borderred); /*border-image-source: url('https://raw.githubusercontent.com/bhuesemann/roll20-character-sheets/tor2e_02-00-00/The%20One%20Ring%202e/images/box-border-red-rttd.png');*/ /*border-image-source: url('https://raw.githubusercontent.com/roll20/roll20-character-sheets/master/The%20One%20Ring%202e/images/box-border-red-rttd.png');*/ border-image-slice: 8 8 8 8; diff --git a/The One Ring 2e/sheet.html b/The One Ring 2e/sheet.html index 541506b9b0..09ac49d634 100644 --- a/The One Ring 2e/sheet.html +++ b/The One Ring 2e/sheet.html @@ -1,6 +1,7 @@ - + - +
@@ -92,7 +93,7 @@ - +
@@ -102,7 +103,7 @@ - + @@ -134,7 +135,7 @@ - +
@@ -144,7 +145,7 @@ - +
@@ -247,13 +248,23 @@ + + + + + + + +   -
@@ -273,13 +284,23 @@ - + + + + + +   -
@@ -300,14 +321,24 @@ + + + + + + + +   -
@@ -328,14 +359,24 @@ + + + + + + + +   -
@@ -363,7 +404,7 @@ data-i18n-title="stance-attack-modifier-description">Attack Mod.: + name="attr_stancedamagebonus" value="0" type="number">
@@ -680,11 +721,16 @@ - + - + + + +   @@ -704,11 +750,16 @@ - + - + + + +   @@ -728,11 +779,16 @@ - + - + + + +   @@ -752,11 +808,16 @@ - + - + + + +   @@ -855,7 +916,11 @@ - + + + +   @@ -944,33 +1009,43 @@ - + + + + +
-

Combat Proficiency

+

Combat Proficiency

- - + + + + + + + + @@ -991,11 +1066,22 @@ value="/me attacks @{target|name} against parry @{target|totalparry}.\n/roll 1t[lm-feat] + [[(@{weapon_rating_2}+?{Bonus Dice|0}+@{target|stanceattackbonus})]]t[normal]" name="roll_weapon2_target"> + + + + + + + + @@ -1029,26 +1115,6 @@
- - - - - - - - - - - - - - - - - - - - @@ -1082,12 +1148,19 @@ let textStyle = `color:${color}; ${style}`; let output = `%c${title} %c${text}`; if (title) { - console.log(output, titleStyle, textStyle); + console.log(output, titleStyle, textStyle); } else { - output = `%c${text}`; - console.log(output, textStyle); + output = `%c${text}`; + console.log(output, textStyle); } }; + const capitalize = (str) => { + return str.charAt(0).toUpperCase() + str.slice(1); + }; + + const stripaction = (str) => { + return str.replace(/_action/g,''); + }; // ASYNC ATTRIBUTE METHODS const asw = (() => { @@ -1140,6 +1213,22 @@ } } + // isolate target call + const getTarget = async () => { + const rxGrab = /^0\[(.*)\]\s*$/; + //{{charname=[[0[@{target|character_name}]]]}} + let rollBase = `! {{parrytotal=[[@{target|totalparry}]]}} {{parry=[[@{target|parry}]]}}`, + targetRoll = await startRoll(rollBase), + target = { + //name: targetRoll.results.charname.expression.match(rxGrab)[1], + name: "", + parrytotal: targetRoll.results.parrytotal.result, + parry: targetRoll.results.parry.result, + }; + finishRoll(targetRoll.rollId); + return target; + }; + // ROLL FROM ACTION BUTTONS, FUNCTIONS BELOW const rollFirst = async (char, act, dice, tn, act_fav, rolltype, additional="", lm=false) => { @@ -1157,9 +1246,10 @@ additionalStr = "", parrymod = 0, parrymodStr = "", - stanceattackmodStr = ""; + stanceattackmodStr = "", + targetnameStr = ""; - act = act.charAt(0).toUpperCase() + act.slice(1); // Capitalise the action + act = capitalize(act); act = (act === "Wisdom" || act === "Valour") ? "Shadow test: "+act : act; clog(`Character name: ${name}, Roll name: ${act}, Target number: ${tn}, Action favoured: ${act_fav}`); @@ -1168,7 +1258,6 @@ "favorill", "weary", "miserable", "currenthope", "shadow", "shadowscar", "favourill_id", "stanceattack_active", "stanceattackbonus", "stancedamagebonus" ]); - clog(`Weary: ${attrs.weary}, Miserable: ${attrs.miserable}`); let wearyStr = (attrs.weary == "on" || attrs.weary == 1) ? "{{weary=Weary}}" : "", weary = (attrs.weary == "on" || attrs.weary == 1) ? 1 : 0; miserableStr = (attrs.miserable == "on" || attrs.miserable == 1) ? "{{miserable=Miserable}}" : "", @@ -1179,7 +1268,7 @@ stanceAttackActive = int(attrs.stanceattack_active), stanceAttackBonus = int(attrs.stanceattackbonus), stanceDamageBonus = int(attrs.stancedamagebonus); - clog(`Weary Str: ${wearyStr}, Miserable Str: ${miserableStr}, Favourill_id: ${favourill_id}, StanceAttackActive: ${stanceAttackActive}, StanceAttackBonus: ${stanceAttackBonus}, StanceDamageBonus: ${stanceDamageBonus}`); + clog(`Weary: ${attrs.weary}, Weary Str: ${wearyStr}, Miserable: ${attrs.miserable}, Miserable Str: ${miserableStr}, Favourill_id: ${favourill_id}, StanceAttackActive: ${stanceAttackActive}, StanceAttackBonus: ${stanceAttackBonus}, StanceDamageBonus: ${stanceDamageBonus}`); // GET MODIFIER AND FAVOURED HERE if (rolltype.startsWith("protection") ) { @@ -1192,21 +1281,22 @@ favId = favourill_id; stanceattackmodStr = "0" if ( rolltype.includes("target") ) { - //parrymod = await getQuery(`?{Parry rating|@{target|parry}}`); if (lm){ parrymodStr = "{{parrymod= [[@{target|totalparry}]]}}"; // we include targets stance modifier stanceattackmodStr = "@{target|stanceattackbonus}"; } else { parrymodStr = "{{parrymod= [[@{target|parry}]]}}"; + // getting the name is tricky, as the parser expects numbers + // see https://app.roll20.net/forum/permalink/10353782/ + //targetnameStr = "{{tgtname= [[ 0 [@{target|name}] ]] }}"; + // Uncaught TypeError: Cannot read properties of undefined (reading 'length') + targetnameStr = ""; } } else { parrymod = await getQuery(`?{Target's Parry|0}`); parrymodStr = `{{parrymod= [[${parrymod}]]}}`; } - //tn = int(tn) + int(parrymod); - //clog(`Parry mod adjusted tn: ${tn}`); - //parrymodStr = `{{parrymod=[[${parrymod}]] }}`; clog(`Parry modifier string: ${parrymodStr}`); } @@ -1274,25 +1364,25 @@ clog(`Additional info: ${additionalStr}`); //LOG - clog(`Character: ${char}, Base dice: ${successdice}, base string ${successStr}, modifiers: ${modifiers}, target: ${tn}, favoured ${featRoll}, skill favoured: ${act_fav}`); + clog(`Character: ${char}, Base dice: ${successdice}, base string ${successStr}, modifiers: ${modifiers}, target: ${tn}, targetname: ${targetnameStr}, favoured ${featRoll}, skill favoured: ${act_fav}`); // START ROLL - rollBase = `&{template:tor} {{character-name=${char} }} {{roll-name=${act} }} {{total=[[0]]}} {{diff=[[0]]}} {{greatness=[[0]]}} {{passthroughdata=[[0]]}} {{outcome=[[0]]}} {{successes=[[0]]}} {{target=[[${tn}]] }} ${featRoll} {{r1=[[ ${successStr} ]] }} ${parrymodStr} ${favouredStr} ${wearyStr} ${miserableStr} ${modStr} {{skill-fav=${act_fav}}} ${weaponStr} ${additionalStr} }`; + rollBase = `&{template:tor} {{character-name=${char} }} {{roll-name=${act} }} {{total=[[0]]}} {{diff=[[0]]}} {{greatness=[[0]]}} {{passthroughdata=[[0]]}} {{outcome=[[0]]}} {{successes=[[0]]}} {{target=[[${tn}]] }} ${featRoll} {{r1=[[ ${successStr} ]] }} ${targetnameStr} ${parrymodStr} ${favouredStr} ${wearyStr} ${miserableStr} ${modStr} {{skill-fav=${act_fav}}} ${weaponStr} ${additionalStr}`; let rollresult = await startRoll(rollBase), rollSuccess = int(rollresult.results.r1.result,0), rollFeat = int(rollresult.results.feat.result,0); clog(`Roll: ${JSON.stringify(rollresult)}`); - if ( parrymodStr !== "") { - clog(`Parry mod: ${JSON.stringify(rollresult.results.parrymod.result)}`); - } if (rolltype.startsWith("combat") ) { clog(`TN before parry modification: ${tn}`); tn = int(tn) + int(rollresult.results.parrymod.result); clog(`TN after parry modification: ${tn}`); } + //let targetname = rolltype.includes("target") ? `attacks ${rollresult.results.tgtname.expression.match(/\[(.*)\]/)[1]}` : ""; + let targetname = ""; + // FEAT DIE AND MISERABLE // Outcomes: Failure = 0, Success = 1, Feat success = 2, Piercing blow = 3, Weary failure = -1, Miserable failure = -2 clog(`Roll result results: ${JSON.stringify(rollresult.results)}`); @@ -1384,6 +1474,7 @@ //rollData.favoured = favouredStr; rollData.outcome = outcome; rollData.greatness = successDegree; + rollData.targetname = targetname; console.log('Roll data: ' + JSON.stringify(rollData)); //rollData.passthroughdata = "This is a test"; @@ -1413,13 +1504,35 @@ }); }); + /*========================== + Action Roll Button Updates + ============================*/ + // For a generic solution for repeating actions see https://app.roll20.net/forum/post/10534166/action-buttons-in-the-macro-bar + on('sheet:opened change:character_name', function() { + getAttrs(["character_name"], function(values){ + const actions = ['protection_action', + 'weapon_1_action', 'weapon_2_action', 'weapon_3_action', 'weapon_4_action', + 'weapon_1_target_action', 'weapon_2_target_action', 'weapon_3_target_action', 'weapon_4_target_action', + 'axes_action', 'bows_action', 'spears_action', 'swords_action', + 'axes_target_action', 'bows_target_action', 'spears_target_action', 'swords_target_action', + 'adv_weapon1_action', 'adv_weapon2_action', + 'adv_weapon1_target_action', 'adv_weapon2_target_action' + ]; + const setObj = actions.reduce((accumulator,actionName)=>{ + accumulator[actionName] = `%{${values.character_name}|${actionName}}`;//Update the action call + return accumulator; //The memo (accumulator in this case) must always be returned when using a reduce function + },{}); + setAttrs(setObj,{silent:true});//Apply the changes + }); + }); + /*========================== Conditions / Stance / Load ============================*/ // weary roll table change on("change:weary sheet:opened", function() { - getAttrs(["weary","sheetTab"], function(values) { + getAttrs(["weary", "wearytype", "sheetTab"], function(values) { if (values.sheetTab === "isPC"){ let weary = values.weary||0; if (weary === "on" || weary == 1) { @@ -1431,6 +1544,11 @@ setAttrs({ wearytype: wearytype, }); + } else { + // setting default for adversaries and if sheet is opened the first time + setAttrs({ + wearytype: "normal", + }); }; }); }); @@ -1444,13 +1562,13 @@ endurance = int(values.endurance); let weary = values.weary, currentendurance = int(values.currentendurance); - clog(`Endurance: ${JSON.stringify(values)}`); - if ( load >= (currentendurance-fatigue) ) { weary = 1; } else { weary = 0} - if ( currentendurance > endurance ) { currentendurance = endurance; } - setAttrs({ - weary: weary, - currentendurance: currentendurance, - }); + clog(`Endurance: ${JSON.stringify(values)}`); + if ( load >= (currentendurance-fatigue) ) { weary = 1; } else { weary = 0} + if ( currentendurance > endurance ) { currentendurance = endurance; } + setAttrs({ + weary: weary, + currentendurance: currentendurance, + }); }; }); @@ -1470,12 +1588,12 @@ // miserable if ( (shadow + scars) >= currenthope ) { setAttrs({ - miserable: 'on', + miserable: 1, }); clog(`Set miserable based on shadow score: shadow ${shadow} + scars ${scars} higher than current hope ${currenthope}.`); } else { setAttrs({ - miserable: 'off', + miserable: 0, }); }; // favourill @@ -1648,9 +1766,9 @@ }); // parsed protection rolls - on('clicked:protection', async (ev) => { + on('clicked:protection_action', async (ev) => { clog(`Starting first roll`); - let action = (ev.htmlAttributes.name).slice(4), + let action = 'protection', data = await asw.getAttrs(['character_name', action, 'protection', 'armourcf', 'armourcm', 'helmetcf', 'helmetcm', 'sheetTab', 'protection_favoured']), actdice = int(data.protection), actfav = data.protection_favoured, @@ -1808,10 +1926,11 @@ // parsed adversary combat proficiency rolls // act_adv_weapon1_target - on('clicked:adv_weapon1 clicked:adv_weapon1_target clicked:adv_weapon2 clicked:adv_weapon2_target ', async (ev) => { + on('clicked:adv_weapon1_action clicked:adv_weapon1_target_action clicked:adv_weapon2_action clicked:adv_weapon2_target_action ', async (ev) => { clog(`Starting first roll`); - let index = (ev.htmlAttributes.name).slice(14).split("_")[0], - target = (ev.htmlAttributes.name).slice(14).split("_")[1] || "", + let options = stripaction((ev.triggerName).slice(18)).split("_"), + index = options[0], + target = options[1] || "", data = await asw.getAttrs(['character_name', `weapon_skill_name_${index}`,`weapon_rating_${index}`, `weapon_damage_${index}`, `weapon_injury_${index}`, 'favorill', 'favourill_id']), action = data[`weapon_skill_name_${index}`], actdice = data[`weapon_rating_${index}`], @@ -1826,10 +1945,11 @@ }); // parsed combat proficiency rolls - on('clicked:axes clicked:bows clicked:spears clicked:swords clicked:axes_target clicked:bows_target clicked:spears_target clicked:swords_target', async (ev) => { + on('clicked:axes_action clicked:bows_action clicked:spears_action clicked:swords_action clicked:axes_target_action clicked:bows_target_action clicked:spears_target_action clicked:swords_target_action', async (ev) => { clog(`Starting first roll`); - let action = (ev.htmlAttributes.name).slice(4).split("_")[0], - target = (ev.htmlAttributes.name).slice(4).split("_")[1] || "", + let options = stripaction((ev.triggerName).slice(8)).split("_"), + action = options[0], + target = options[1] || "", data = await asw.getAttrs(['character_name', 'strengthtn', action, `${action}_favoured`, 'favorill', 'favourill_id']), actdice = data[action], favorill = data['favorill'] || "{1t[feat]}", @@ -1851,8 +1971,8 @@ }); // parsed combat rolls per weapon - on("clicked:weapon_1 clicked:weapon_2 clicked:weapon_3 clicked:weapon_4 clicked:weapon_1_target clicked:weapon_2_target clicked:weapon_3_target clicked:weapon_4_target ", async (ev) => { - let options = (ev.htmlAttributes.name).slice(11), + on("clicked:weapon_1_action clicked:weapon_2_action clicked:weapon_3_action clicked:weapon_4_action clicked:weapon_1_target_action clicked:weapon_2_target_action clicked:weapon_3_target_action clicked:weapon_4_target_action ", async (ev) => { + let options = stripaction((ev.triggerName).slice(15)), index = options.split('_')[0], target = options.split('_')[1] || ""; target = target === "" ? "" : "-"+target; @@ -1916,7 +2036,7 @@ }); -
+
{{skill}}
{{#rollTotal() favorill 1}}
stand {{standard}}
@@ -1975,8 +2095,6 @@
{{computed::total}}
Total
-
{{#rollLess() computed::outcome 1}} diff --git a/The One Ring 2e/sheet.json b/The One Ring 2e/sheet.json index 2b02915b38..2ce816d20f 100644 --- a/The One Ring 2e/sheet.json +++ b/The One Ring 2e/sheet.json @@ -1,11 +1,11 @@ { "title": "The One Ring 2e", - "version": "2.0.0", + "version": "2.2.0", "html": "sheet.html", "css": "sheet.css", "authors": "Bodo Hüsemann, Richard W, Michael (aka Aragent) I, Paul Venner, Michael Heilemann, Stefan Unterhuber, Stuart Johnson, David Domínguez, Eric Le Bourvellec", "roll20userid": "390460,8097845,2624774,84040,61774,1227702,383147,63716,211627", "preview": "sheet.png", - "instructions": "The One Ring 2nd Edition. This is a rewrite based on the early 2e (basic) and 1e edition that also includes a 2e version for adversaries. It features correct handling of favoured rolls and stance related bonus changes to attack rating, parry, protection and damage. In addition to the classic custom roll tables the sheet also includes roll-templates for parsed rolls (player can toggle). \r\r**Important:** For table rolls to work properly, follow the instructions on [The One Ring wiki page](https://wiki.roll20.net/The_One_Ring#Rollable_Tables) to set up custom rollable tables for your game. If you want to use parsed rolls you don't have to do this anymore. \rMore info: [Readme](https://github.com/Roll20/roll20-character-sheets/blob/master/The%20One%20Ring/README.md) and [wiki page](https://wiki.roll20.net/The_One_Ring). You can reach us via Discord here: https://discord.com/invite/WEUx83PjWm .", + "instructions": "The One Ring 2nd Edition. This is a rewrite based on the early 2e (basic) and 1e edition that also includes a 2e version for adversaries. It features correct handling of favoured rolls and stance related bonus changes to attack rating, parry, protection and damage. In addition to the classic custom roll tables the sheet also includes roll-templates for parsed rolls (player can toggle). \r\r**Important:** For table rolls to work properly, follow the instructions on [The One Ring wiki page](https://wiki.roll20.net/The_One_Ring#Rollable_Tables) to set up custom rollable tables for your game. If you want to use parsed rolls you don't have to do this anymore. \rMore info: [Readme](https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/The%20One%20Ring%202e/readme.md) and [wiki page](https://wiki.roll20.net/The_One_Ring). You can reach us via Discord here: https://discord.com/invite/WEUx83PjWm .", "legacy": false } \ No newline at end of file diff --git a/The One Ring 2e/sheet.png b/The One Ring 2e/sheet.png index bd15768bbf..57197b6912 100644 Binary files a/The One Ring 2e/sheet.png and b/The One Ring 2e/sheet.png differ