mirror of
https://github.com/Nighthawk42/roll20-character-sheets.git
synced 2026-09-10 00:52:28 +00:00
701 lines
27 KiB
HTML
701 lines
27 KiB
HTML
|
||
<input name="attr_version" type="hidden" value="1"/>
|
||
<input name="attr_woundsMalus" type="hidden" value="0"/>
|
||
<main>
|
||
<div class="panel panel-name">
|
||
<h2>SHS - Fiche de suivi de</h2>
|
||
<div class="panelbody">
|
||
<label class="textLabelled" for="charname"><span>Nom & Rôle:</span>
|
||
<input name="attr_charname" type="text" value=""/>
|
||
</label>
|
||
<label class="textLabelled" for="player"><span>Joueur:</span>
|
||
<input name="attr_player" type="text" value=""/>
|
||
</label>
|
||
<input name="attr_character_name" type="hidden" value=""/>
|
||
<button name="act_testWounds" type="action" value=""></button>
|
||
</div>
|
||
</div>
|
||
<div class="panel panel-nav">
|
||
<div class="panelbody">
|
||
<label class="navRadio">
|
||
<input name="attr_page" type="radio" value="base" attributes.checked="attributes.checked"/><span title="Notes & relations"></span>
|
||
</label>
|
||
<label class="navRadio">
|
||
<input name="attr_page" type="radio" value="combat" attributes.checked="attributes.checked"/><span title="Combat"></span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div class="panel panel-hp">
|
||
<h3>Santé</h3>
|
||
<div class="panelbody">
|
||
<div class="num-over-max">
|
||
<input name="attr_hp" type="number" value="0"/>
|
||
<input name="attr_hp_max" type="number" value="0"/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="panel panel-armour">
|
||
<h3>Protection</h3>
|
||
<div class="panelbody">
|
||
<div class="num-over-max">
|
||
<input name="attr_armour" type="number" value="0"/>
|
||
<input name="attr_armour_max" type="number" value="0"/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="panel panel-oxygen">
|
||
<h3>Oxygène</h3>
|
||
<div class="panelbody">
|
||
<div class="num-over-max">
|
||
<input name="attr_oxygen" type="number" value="0"/>
|
||
<input name="attr_oxygen_max" type="number" value="0"/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="panel panel-carac">
|
||
<h3>Caractéristiques</h3>
|
||
<div class="panelbody">
|
||
<div class="ability">
|
||
<label class="textLabelled carrure">
|
||
<div>Carrure</div>
|
||
<input name="attr_carrure" type="number" value="5"/>
|
||
<button class="roll d8" name="act_roll_carrure" type="action" value="Carrure"></button>
|
||
<button class="roll d10" name="act_exp_carrure" type="action" value="Carrure"></button>
|
||
</label>
|
||
</div>
|
||
<div class="ability">
|
||
<label class="textLabelled motricite">
|
||
<div>Motricité</div>
|
||
<input name="attr_motricite" type="number" value="5"/>
|
||
<button class="roll d8" name="act_roll_motricite" type="action" value="Motricité"></button>
|
||
<button class="roll d10" name="act_exp_motricite" type="action" value="Motricité"></button>
|
||
</label>
|
||
</div>
|
||
<div class="ability">
|
||
<label class="textLabelled science">
|
||
<div>Science</div>
|
||
<input name="attr_science" type="number" value="5"/>
|
||
<button class="roll d8" name="act_roll_science" type="action" value="Science"></button>
|
||
<button class="roll d10" name="act_exp_science" type="action" value="Science"></button>
|
||
</label>
|
||
</div>
|
||
<div class="ability">
|
||
<label class="textLabelled relationnel">
|
||
<div>Relationnel</div>
|
||
<input name="attr_relationnel" type="number" value="5"/>
|
||
<button class="roll d8" name="act_roll_relationnel" type="action" value="Relationnel"></button>
|
||
<button class="roll d10" name="act_exp_relationnel" type="action" value="Relationnel"></button>
|
||
</label>
|
||
</div>
|
||
<div class="ability">
|
||
<label class="textLabelled sangfroid">
|
||
<div>Sang froid</div>
|
||
<input name="attr_sangfroid" type="number" value="5"/>
|
||
<button class="roll d8" name="act_roll_sangfroid" type="action" value="Sang froid"></button>
|
||
<button class="roll d10" name="act_exp_sangfroid" type="action" value="Sang froid"></button>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="panel panel-skills">
|
||
<h3>Expertises (D8 -> D10)</h3>
|
||
<div class="panelbody">
|
||
<textarea name="attr_expertises"></textarea>
|
||
</div>
|
||
</div>
|
||
<input name="attr_page" type="hidden" value="base"/>
|
||
<div class="page page-combat">
|
||
<div class="panel panel-wounds">
|
||
<h3>Blessures et états</h3>
|
||
<div class="panelbody">
|
||
<div class="wounds"><span>Description</span><span>Malus</span><span title="Indice de gravité">IG</span><span>Dégât</span>
|
||
<fieldset class="repeating_wounds">
|
||
<input name="attr_description" type="text" value=""/>
|
||
<input name="attr_malus" type="number" value="0"/>
|
||
<input name="attr_ig" type="number" value="0"/>
|
||
<input name="attr_damage" type="number" value="0"/>
|
||
</fieldset>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="panel panel-weapons">
|
||
<h3>Armes</h3>
|
||
<div class="panelbody">
|
||
<div class="weapons"><span>Arme</span><span title="Impact">Imp.</span><span title="Portée">Por.</span><span>Attributs</span><span title="Munitions">Mun.</span><span title="Expert ?">Exp.</span><span title="Dommages de brûlure / corrosion ?">r</span><span></span>
|
||
<div class="unnarmed">
|
||
<input name="attr_unnarmed-name" type="text" value="Mains nues" readonly="readonly"/>
|
||
<input name="attr_unnarmed-impact" readonly="readonly" type="number" value="0"/>
|
||
<input name="attr_unnarmed-range" type="text" value="C" readonly="readonly"/>
|
||
<input name="attr_unnarmed-attributes" type="text" value="-" readonly="readonly"/>
|
||
<input name="attr_unnarmed-ammo" readonly="readonly" type="number" value="0"/>
|
||
<label>
|
||
<input name="attr_unnarmed-exp" value="1" type="checkbox"/><span title=" "></span>
|
||
</label><span></span>
|
||
</div>
|
||
<fieldset class="repeating_weapons">
|
||
<input name="attr_name" type="text" value=""/>
|
||
<input name="attr_impact" type="number" value="0"/>
|
||
<input name="attr_range" type="text" value=""/>
|
||
<input name="attr_attributes" type="text" value=""/>
|
||
<input name="attr_ammo" type="number" value="0"/>
|
||
<label>
|
||
<input name="attr_exp" value="1" type="checkbox"/><span title=" "></span>
|
||
</label>
|
||
<label>
|
||
<input name="attr_burn" value="1" type="checkbox"/><span title=" "></span>
|
||
</label>
|
||
<button class="roll d10" name="act_attack" type="action" value=""></button>
|
||
</fieldset>
|
||
<input name="attr_dmgString" type="hidden" value="&{template:damage}{{roll=[[d8]]}}"/>
|
||
<button class="roll hidden" name="roll_damages" type="roll" value="@{dmgString}"></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="page page-base">
|
||
<div class="panel panel-notes">
|
||
<h3>Notes & Équipement</h3>
|
||
<div class="panelbody">
|
||
<textarea name="attr_notes"></textarea>
|
||
</div>
|
||
</div>
|
||
<div class="panel panel-relations">
|
||
<h3>Relations</h3>
|
||
<div class="panelbody">
|
||
<div class="relation">
|
||
<p>Ami(e) avec</p>
|
||
<input name="attr_friend" type="text" value=""/><span>+</span>
|
||
</div>
|
||
<div class="relation">
|
||
<p>Amoureux(se) de</p>
|
||
<input name="attr_inlove" type="text" value=""/><span>+</span>
|
||
</div>
|
||
<div class="relation">
|
||
<p>Même famille que (préciser le lien)</p>
|
||
<input name="attr_family" type="text" value=""/><span>+</span>
|
||
</div>
|
||
<div class="relation">
|
||
<p>Hostile envers</p>
|
||
<input name="attr_hostile" type="text" value=""/><span>-</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main><rolltemplate class="sheet-rolltemplate-simple">
|
||
<h3>{{label}}</h3>
|
||
<div class="sheet-rollBody">{{#rollTotal() computed::option 1}}
|
||
<div class="sheet-rollOption">
|
||
Surpassement ! <small>+1 NT</small>
|
||
</div>
|
||
{{/rollTotal() computed::option 1}}
|
||
{{#rollTotal() computed::option 2}}
|
||
<div class="sheet-rollOption">
|
||
Sacrifice ! <small>Vous êtes désormais mort</small>
|
||
</div>
|
||
{{/rollTotal() computed::option 2}}
|
||
<div class="sheet-big">{{computed::totalSuccesses}} succès !</div>
|
||
<div class="sheet-baseRoll">
|
||
<div>{{roll}} réussites</div>
|
||
{{#rollTotal() computed::sides 8}}
|
||
<div class=sheet-d8>{{computed::roll}}</div>
|
||
{{/rollTotal() computed::sides 8}}
|
||
{{#rollTotal() computed::sides 10}}
|
||
<div class="sheet-d10">{{computed::roll}}</div>
|
||
{{/rollTotal() computed::sides 10}}
|
||
</div>
|
||
<div class="sheet-modRoll">
|
||
<div>{{computed::trueMod}} bonus/malus</div>
|
||
<div>{{computed::mod}}</div>
|
||
</div>
|
||
</div>
|
||
</rolltemplate><rolltemplate class="sheet-rolltemplate-attack">
|
||
<h3>{{label}}</h3>
|
||
<div class="sheet-rollBody">
|
||
{{#rollTotal() computed::option 1}}
|
||
<div class="sheet-rollOption">
|
||
Surpassement ! <small>+1 NT</small>
|
||
</div>
|
||
{{/rollTotal() computed::option 1}}
|
||
{{#rollTotal() computed::option 2}}
|
||
<div class="sheet-rollOption">
|
||
Sacrifice ! <small>Vous êtes désormais mort</small>
|
||
</div>
|
||
{{/rollTotal() computed::option 2}}
|
||
<div class="sheet-big">{{computed::totalSuccesses}} succès !</div>
|
||
<div class="sheet-baseRoll">
|
||
<div>{{roll}} réussites</div>
|
||
{{#rollTotal() computed::sides 8}}
|
||
<div class=sheet-d8>{{computed::roll}}</div>
|
||
{{/rollTotal() computed::sides 8}}
|
||
{{#rollTotal() computed::sides 10}}
|
||
<div class="sheet-d10">{{computed::roll}}</div>
|
||
{{/rollTotal() computed::sides 10}}
|
||
</div>
|
||
<div class="sheet-modRoll">
|
||
<div>{{computed::trueMod}} bonus/malus</div>
|
||
<div>{{computed::mod}}</div>
|
||
</div>
|
||
<div class="sheet-conditions">
|
||
{{#rollTotal() computed::surprise 1}}
|
||
<div class="sheet-condition">Adversaire surpris</div>
|
||
{{/rollTotal() computed::surprise 1}}
|
||
{{#rollTotal() computed::aimed 1}}
|
||
<div class="sheet-condition">Tir ajusté</div>
|
||
{{/rollTotal() computed::aimed 1}}
|
||
{{#rollTotal() computed::lethal 1}}
|
||
<div class="sheet-condition">Attaque expéditive</div>
|
||
{{/rollTotal() computed::lethal 1}}
|
||
</div>
|
||
<div class="sheet-actions">
|
||
[Dégâts](~{{charname}}|damages)
|
||
</div>
|
||
</div>
|
||
</rolltemplate><rolltemplate class="sheet-rolltemplate-goldorak">
|
||
<h3>Fulguro-poing !</h3>
|
||
</rolltemplate><rolltemplate class="sheet-rolltemplate-damage">
|
||
<h3>Blessure ({{weapon}})</h3>
|
||
<div class="sheet-rollBody">
|
||
{{#rollBetween() roll 1 3}}
|
||
<div class="sheet-odd">Blessure superficielle, chute, léger étourdissement…</div>
|
||
<div class="sheet-even"><b>Malus (Tour)</b> de 1</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 0</span><span><b>NT</b>: -</span></div>
|
||
{{/rollBetween() roll 1 3}}
|
||
{{#rollBetween() roll 4 5}}
|
||
<div class="sheet-odd">Petite commotion cérébrale</div>
|
||
<div class="sheet-even"><b>Malus (1 min)</b> de 1</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 0</span><span><b>NT</b>: -</span></div>
|
||
{{/rollBetween() roll 4 5}}
|
||
{{#rollTotal() roll 6}}
|
||
<div class="sheet-odd">Membre lacéré, hanche déboîtée, entorse…</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 1</div>
|
||
<div class="sheet-odd"><b>Malus</b> de 1</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 1</span><span><b>NT</b>: +1</span></div>
|
||
{{/rollTotal() roll 6}}
|
||
{{#rollTotal() roll 7}}
|
||
<div class="sheet-odd">Fracture, traumatisme crânien…</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 2</div>
|
||
<div class="sheet-odd"><b>Malus</b> de 2</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 2</span><span><b>NT</b>: +1</span></div>
|
||
{{/rollTotal() roll 7}}
|
||
{{#rollTotal() roll 8}}
|
||
<div class="sheet-odd">Fracture ouverte, organe vital endommagé</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 3</div>
|
||
<div class="sheet-odd"><b>Malus</b> de 2</div>
|
||
<div class="sheet-even">+1 <b>Dégât</b> par minute</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 2</span><span><b>NT</b>: +1</span></div>
|
||
{{/rollTotal() roll 8}}
|
||
{{#rollTotal() roll 9}}
|
||
<div class="sheet-odd">Hémorragie, organe vital endommagé</div>
|
||
<div class="sheet-even">+1 <b>Dégât</b> par <b>Tour</b></div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 3</span><span><b>NT</b>: +1</span></div>
|
||
{{/rollTotal() roll 9}}
|
||
{{#rollTotal() roll 10}}
|
||
<div class="sheet-odd">Éventration, membre arraché, broyé…</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 4</div>
|
||
<div class="sheet-odd"><b>Malus</b> de 3</div>
|
||
<div class="sheet-even">+1 <b>Dégât</b> par <b>Tour</b></div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 4</span><span><b>NT</b>: +1</span></div>
|
||
{{/rollTotal() roll 10}}
|
||
{{#rollTotal() roll 11}}
|
||
<div class="sheet-odd">Large éventration, membres arrachés, broyés</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 6</div>
|
||
<div class="sheet-odd"><b>Malus</b> de 4</div>
|
||
<div class="sheet-even">+1 <b>Dégât</b> par <b>Tour</b></div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 5</span><span><b>NT</b>: +1</span></div>
|
||
{{/rollTotal() roll 11}}
|
||
{{#^rollLess() roll 12}}
|
||
<div class="sheet-big"><b>Mort</b></div>
|
||
<div>Tête broyée, torse coupé en deux, colonne vertébrale arrachée, corps écartelé, éviscération complète, corps complètement calciné…</div>
|
||
{{/^rollLess() roll 12}}
|
||
</div>
|
||
</rolltemplate><rolltemplate class="sheet-rolltemplate-burndamage">
|
||
<h3>Brûlure / corrosion ({{weapon}})</h3>
|
||
<div class="sheet-rollBody">
|
||
{{#rollBetween() roll 1 3}}
|
||
<div class="sheet-odd">Brûlure/corrosion superficielle</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 1</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 0</span><span><b>NT</b>: -</span></div>
|
||
{{/rollBetween() roll 1 3}}
|
||
{{#rollBetween() roll 4 5}}
|
||
<div class="sheet-odd">Brûlure/corrosion légère</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 2</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 0</span><span><b>NT</b>: -</span></div>
|
||
{{/rollBetween() roll 4 5}}
|
||
{{#rollTotal() roll 6}}
|
||
<div class="sheet-odd">Brûlure/corrosion importante</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 3</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 1</span><span><b>NT</b>: +1</span></div>
|
||
{{/rollTotal() roll 6}}
|
||
{{#rollTotal() roll 7}}
|
||
<div class="sheet-odd">Brûlure/corrosion importante</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 3</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 2</span><span><b>NT</b>: +1</span></div>
|
||
{{/rollTotal() roll 7}}
|
||
{{#rollTotal() roll 8}}
|
||
<div class="sheet-odd">Brûlure/corrosion grave</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 4</div>
|
||
<div class="sheet-odd"><b>Malus</b> de 1</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 2</span><span><b>NT</b>: +1</span></div>
|
||
{{/rollTotal() roll 8}}
|
||
{{#rollTotal() roll 9}}
|
||
<div class="sheet-odd">Brûlure/corrosion très grave</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 5</div>
|
||
<div class="sheet-odd"><b>Malus</b> de 1</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 3</span><span><b>NT</b>: +1</span></div>
|
||
{{/rollTotal() roll 9}}
|
||
{{#rollTotal() roll 10}}
|
||
<div class="sheet-odd">Brûlure/corrosion extrême</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 6</div>
|
||
<div class="sheet-odd"><b>Malus</b> de 2</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 4</span><span><b>NT</b>: +1</span></div>
|
||
{{/rollTotal() roll 10}}
|
||
{{#rollTotal() roll 11}}
|
||
<div class="sheet-odd">Brûlure/corrosion jusqu’à l’os</div>
|
||
<div class="sheet-even"><b>Dégât</b>: 8</div>
|
||
<div class="sheet-odd"><b>Malus</b> de 3</div>
|
||
<div class="sheet-severity"><span><b>IG</b>: 5</span><span><b>NT</b>: +1</span></div>
|
||
{{/rollTotal() roll 11}}
|
||
{{#^rollLess() roll 12}}
|
||
<div class="sheet-big"><b>Mort</b></div>
|
||
<div>Tête broyée, torse coupé en deux, colonne vertébrale arrachée, corps écartelé, éviscération complète, corps complètement calciné…</div>
|
||
{{/^rollLess() roll 12}}
|
||
</div>
|
||
</rolltemplate>
|
||
<script type="text/worker">
|
||
|
||
/**
|
||
* Library of useful functions to manage repeating sections
|
||
*/
|
||
const section_name = (section, id, field) => `${section.startsWith('repeating_') ? section : `repeating_${section}`}_${id}_${field}`
|
||
|
||
const section_parts = (full_name, part='section') => {
|
||
let [stub, section, row, ...field] = full_name.split('_')
|
||
if (part === 'section' || part === 1) return section;
|
||
else if (part === 'row' || part === 'id' || part === 2) return row;
|
||
else return field.join('_')
|
||
}
|
||
|
||
const section_changes = section_object => {
|
||
let output = ''
|
||
Object.keys(section_object).forEach((key, index) => {
|
||
if (index) section += ' ';
|
||
section_object[key].forEach(field => {
|
||
output += 'change:'
|
||
output += key === 'globals' ? field : `repeating_${key}:${field}`
|
||
})
|
||
})
|
||
return output
|
||
}
|
||
|
||
const baseRoll = "&{template:_TPL_} {{roll=[[3d_D_>_DIFF_]]}} {{mod=[[_MOD_dF]]}} {{label=_LABEL_}} {{totalSuccesses=[[0]]}} {{trueMod=[[0]]}} {{sides=[[0]]}} {{option=[[0]]}}"
|
||
|
||
const askForMod = "!{{template:default}}"
|
||
+ "{{option=![[?{Option ?|Jet normal, 0|Surpassement, 1|Sacrifice, 2}]]}}"
|
||
+ "{{ask=![[?{Bonus / Malus ?|0}]]}}"
|
||
|
||
const diceLetters = '0abcdefghij'
|
||
const fateLetters = '−0+'
|
||
const dicify = dice => dice.map(x => diceLetters[x])
|
||
const fatify = dice => dice.map(x => fateLetters[1+x])
|
||
|
||
const OPT_NORMAL = 0
|
||
const OPT_SURPASS = 1
|
||
const OPT_SACRIFICE = 2
|
||
|
||
/**
|
||
* Performs a SHS standard attribute roll
|
||
*
|
||
* @param {string} attrName The roll20 attribute identifier to roll against
|
||
* @param {boolean} isExpert Wether to roll 8 or 10 sided dice
|
||
* @param {string} title What to display in the headerbar
|
||
* @param {int} specificMod Some rolls require specific modifiers (fight, etc)
|
||
* @param {string} template custom template name; default is «simple»
|
||
* @param {string} sublabel Optional label to be displayed on specific templates
|
||
*/
|
||
var attributeRoll = async (attrName, isExpert=false, title='', specificMod=0, template='simple', sublabel='', conditions={}) => {
|
||
let preroll = await startRoll(askForMod)
|
||
|
||
getAttrs([attrName, 'woundsMalus', 'character_name'], async v => {
|
||
let attrVal = parseInt(v[attrName])||8
|
||
let woundsMod = Math.abs(parseInt(v.woundsMalus)||0)
|
||
let totalMod = specificMod + preroll.results.ask.result - woundsMod
|
||
let option = parseInt(preroll.results.option.result)||0
|
||
if (option >= OPT_SURPASS) totalMod += 2
|
||
let modIsMalus = (totalMod < 0)
|
||
let sides = isExpert ? 10 : 8
|
||
|
||
let rollString = baseRoll.replace('_TPL_', template)
|
||
.replace('_D_', sides)
|
||
.replace('_DIFF_', attrVal)
|
||
.replace('_MOD_', Math.min(Math.abs(totalMod), 5))
|
||
.replace('_LABEL_', title)
|
||
|
||
if (template == 'attack') {
|
||
rollString = rollString
|
||
+ attackVars
|
||
+ '{{charname=_CHARNAME_}}'
|
||
.replace('_CHARNAME_', v.character_name)
|
||
}
|
||
|
||
let roll = await startRoll(rollString)
|
||
|
||
// Compute mod dice result
|
||
let modSuccesses = 0;
|
||
roll.results.mod.dice.forEach(die => {
|
||
if (modIsMalus && die < 0) {
|
||
modSuccesses--;
|
||
} else if (!modIsMalus && die > 0) {
|
||
modSuccesses++
|
||
}
|
||
})
|
||
|
||
let successes = roll.results.roll.result + modSuccesses + (option == OPT_SACRIFICE ? 2 : 0)
|
||
allDice = dicify(roll.results.roll.dice)
|
||
|
||
let results = {
|
||
totalSuccesses: successes,
|
||
trueMod: modSuccesses,
|
||
roll: dicify(roll.results.roll.dice).join(' '),
|
||
mod: fatify(roll.results.mod.dice).join(' '),
|
||
sides: sides,
|
||
label: sublabel
|
||
}
|
||
|
||
finishRoll(roll.rollId, {...results, ...conditions})
|
||
})
|
||
}
|
||
|
||
//
|
||
const askForStrategy = "!{{template:default}}"
|
||
+ "{{strategy=![[?{Stratégie ?|Combat rapproché (faire face), 0|Combat rapproché (fuite), 1|Distance, 2}]]}}"
|
||
|
||
const askForMeleeMod = "!{{template:default}}"
|
||
+ "{{surpriseMod=![[?{Adversaire surpris ?|Non, 0|Oui, 2}]]}}"
|
||
+ "{{lethalAtk=![[?{Attaque expéditive ?|Non, 0|Oui, -2}]]}}"
|
||
|
||
const askForDistMod = "!{{template:default}}"
|
||
+ "{{aimedMod=![[?{Tir ajusté au tour précédent ?|Non, 0|Oui, 2}]]}}"
|
||
+ "{{lethalAtk=![[?{Attaque expéditive ?|Non, 0|Oui, -2}]]}}"
|
||
+ "{{distMod=![[?{Distance de la cible?|Moyenne, 0|Courte, 1|Longue, -1}]]}}"
|
||
|
||
const askForDmgMod = "!{{template:default}}"
|
||
+ "{{tgtArmor=![[?{Protection cible ?}]]}}"
|
||
|
||
const damageRollString = "&{template:_TEMPLATE_}{{roll=[[d8+_IMPACT_-?{Protection cible ?|0}]]}}{{weapon=_WPNAME_}}"
|
||
|
||
const distanceUnnarmed = "&{template:goldorak} {{roll=[[0]]}}"
|
||
|
||
const attackVars = "{{surprise=[[0]]}}{{lethal=[[0]]}}{{aimed=[[0]]}}{{button=[[0]]}}"
|
||
|
||
/**
|
||
* Returns a range modifier for long range attacks
|
||
*
|
||
* @param {string} char A string representing a range
|
||
* @returns The range modifier
|
||
*/
|
||
const rangeMod = char => {
|
||
switch(char.trim()) {
|
||
case 'C':
|
||
case 'P':
|
||
return 1
|
||
case 'M':
|
||
return 0
|
||
case 'L':
|
||
return -1
|
||
default:
|
||
return 0
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Performs the pre-roll for melee attacks
|
||
*
|
||
* @returns Pre roll data
|
||
*/
|
||
const preMelee = async () => {
|
||
let roll = await startRoll(askForMeleeMod)
|
||
let lethalMod = parseInt(roll.results.lethalAtk.result)||0
|
||
let surpriseMod = parseInt(roll.results.surpriseMod.result)
|
||
let response = {
|
||
specificMod: lethalMod + surpriseMod,
|
||
conditions: {
|
||
lethal: lethalMod&&1,
|
||
surprise: surpriseMod&&1
|
||
}
|
||
}
|
||
|
||
return response
|
||
}
|
||
|
||
/**
|
||
* Performs the pre-roll for long range attacks
|
||
*
|
||
* @returns Pre roll data
|
||
*/
|
||
const preDistance = async () => {
|
||
let roll = await startRoll(askForDistMod)
|
||
let lethalMod = parseInt(roll.results.lethalAtk.result)||0
|
||
let aimedMod = parseInt(roll.results.aimedMod.result)||0
|
||
let distMod = parseInt(roll.results.distMod.result)||0
|
||
|
||
let response = {
|
||
specificMod: lethalMod + aimedMod + distMod,
|
||
conditions: {
|
||
lethal: lethalMod&&1,
|
||
aimed: aimedMod&&1
|
||
}
|
||
}
|
||
|
||
return response
|
||
}
|
||
|
||
/**
|
||
* Prepares the damage roll
|
||
*
|
||
* @param {string} wpnName The weapon name
|
||
* @param {int} impact The weapon impact
|
||
* @param {int} isBurning Standard or burning damage ?
|
||
*/
|
||
const setDamageString = async (wpnName, impact, isBurning) => {
|
||
let rollString = damageRollString
|
||
.replace('_TEMPLATE_', isBurning ? 'burndamage' : 'damage')
|
||
.replace('_WPNAME_', wpnName)
|
||
.replace('_IMPACT_', impact)
|
||
setAttrs({
|
||
dmgString: rollString
|
||
})
|
||
}
|
||
|
||
const attackRoll = async (strategy, wpnName, isExpert, range, impact, isArmed, isBurning) => {
|
||
// Case strategy 0 Aggressive
|
||
attr = 'carrure'
|
||
sublabel = 'Combat rapproché (Carrure)'
|
||
|
||
let preRoll = {};
|
||
if (strategy === 2) {
|
||
attr = 'sangfroid'
|
||
sublabel = 'Combat à distance (Sang-froid)'
|
||
preRoll = await preDistance()
|
||
} else {
|
||
preRoll = await preMelee()
|
||
if (strategy === 1) {
|
||
attr = 'motricite'
|
||
sublabel = 'Combat rapproché (Motricité - Fuite)'
|
||
}
|
||
}
|
||
|
||
setDamageString(wpnName, impact, isBurning)
|
||
|
||
attributeRoll(attr, (isExpert === 1), wpnName, preRoll.specificMod + isArmed, 'attack', sublabel, preRoll.conditions)
|
||
}
|
||
|
||
on('clicked:unnarmed-attack', async ev => {
|
||
let strategyroll = await startRoll(askForStrategy)
|
||
let strategy = parseInt(strategyroll.results.strategy.result)||0
|
||
|
||
if (strategy === 2) {
|
||
let oops = await startRoll(distanceUnnarmed)
|
||
finishRoll(oops.rollId)
|
||
} else {
|
||
getAttrs(['unnarmed-exp'], (v) => {
|
||
let wpName = 'Mains nues'
|
||
let isExpert = parseInt(v['unnamred-exp'])||0
|
||
let range = 'C'
|
||
let impact = 0
|
||
let isArmed = 0
|
||
|
||
attackRoll(strategy, wpName, isExpert, range, impact, isArmed, false)
|
||
})
|
||
}
|
||
})
|
||
|
||
on('clicked:repeating_weapons:attack', async ev => {
|
||
strategyroll = await startRoll(askForStrategy)
|
||
let strategy = parseInt(strategyroll.results.strategy.result)||0
|
||
|
||
let toGet = ['name', 'impact', 'range', 'exp', 'burn'].map(a => 'repeating_weapons_' + a)
|
||
|
||
getAttrs(toGet, v => {
|
||
let wpName = v.repeating_weapons_name
|
||
let isExpert = parseInt(v.repeating_weapons_exp)||0
|
||
let range = v.repeating_weapons_range
|
||
let impact = parseInt(v.repeating_weapons_impact)||0
|
||
let isArmed = 1
|
||
let isBurning = parseInt(v.repeating_weapons_burn)||0
|
||
|
||
attackRoll(strategy, wpName, isExpert, range, impact, isArmed, isBurning)
|
||
})
|
||
})
|
||
/**
|
||
* Says «hello» and then changes character's name
|
||
* @param {event} ev
|
||
*/
|
||
const editCharName = (ev) => {
|
||
getAttrs(['charname', 'player'], v => {
|
||
let display = v.player + ' - ' + v.charname;
|
||
setAttrs({
|
||
character_name: display,
|
||
killhim_action: `%{${display}|killhim-action}`
|
||
})
|
||
})
|
||
}
|
||
|
||
on('change:charname change:player', ev => {
|
||
editCharName(ev)
|
||
})
|
||
|
||
/**
|
||
* Computes the max HP according to carrure value
|
||
*/
|
||
const computeMaxHp = () => {
|
||
getAttrs(['carrure'], v => {
|
||
let hpMax = 17 - (parseInt(v.carrure)||5)
|
||
setAttrs({
|
||
hp_max: hpMax
|
||
})
|
||
})
|
||
}
|
||
|
||
on('change:carrure', ev => {
|
||
computeMaxHp()
|
||
})
|
||
|
||
on('clicked:roll_carrure clicked:roll_motricite clicked:roll_science clicked:roll_relationnel '
|
||
+ 'clicked:roll_sangfroid clicked:exp_carrure clicked:exp_motricite clicked:exp_science '
|
||
+ 'clicked:exp_relationnel clicked:exp_sangfroid', ev => {
|
||
let nameData = ev.htmlAttributes.name.split('_')
|
||
let attrName = nameData[2];
|
||
let isExpert = nameData[1] == 'exp' ? true : false
|
||
let title = ev.htmlAttributes.value
|
||
attributeRoll(attrName, isExpert, title)
|
||
})
|
||
|
||
const updateWoundMod = () => {
|
||
getSectionIDs('repeating_wounds', ids => {
|
||
const rows = ids.map(id => section_name('wounds', id, 'malus'))
|
||
getAttrs(rows, values => {
|
||
let total = 0
|
||
rows.forEach(row => {
|
||
let malus = +Math.abs(values[row] || 0)
|
||
total += malus
|
||
})
|
||
console.warn(total)
|
||
setAttrs({
|
||
woundsMalus: total
|
||
})
|
||
})
|
||
})
|
||
}
|
||
|
||
const woundsMalusFields = {
|
||
wounds: ['malus']
|
||
}
|
||
|
||
on(`${section_changes(woundsMalusFields)} remove:repeating_wounds`, ev => {
|
||
updateWoundMod()
|
||
})
|
||
|
||
on('sheet:opened', ev => {
|
||
computeMaxHp()
|
||
})
|
||
</script> |