Files
roll20-character-sheets-tester/SalvageUnion/SalvageUnion.html
T

1213 lines
48 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div class="wrapper">
<input type="hidden" class="tabstoggle" name="attr_sheetTab" value="settings"/>
<div>
<input class="show-pilot" name="attr_is-pilot" type="checkbox" checked hidden/>
<button type="action" name="act_pilot" class="tabs pilot-button">Pilot</button>
<input class="show-mech" name="attr_is-mech" type="checkbox" hidden/>
<button type="action" name="act_mech" class="tabs mech-button">Mech</button>
<input class="show-crawler" name="attr_is-crawler" type="checkbox" hidden/>
<button type="action" name="act_crawler" class="tabs crawler-button">Union Crawler</button>
<input class="show-notes" name="attr_show-notes-tab" type="checkbox" hidden/>
<button type="action" name="act_notes" class="tabs notes-button">Notes</button>
<button type="action" name="act_settings" class="tabs">Settings</button>
</div>
<div class="pilot">
<h2>Pilot
<button type="roll" value="&{template:roll}{{name=@{character_name}}}{{roll=[[1d20]]}}"></button>
</h2>
<div style="display:flex">
<div class="twocolumns">
<div class="descValuePair">
<label for="name">Callsign</label>
<input id="name" type="text" class="checkboxSpacer" name="attr_character_name">
</div>
<div class="descValuePair">
<label for="class">Class</label>
<input id="class" type="text" class="checkboxSpacer" name="attr_character_class">
</div>
<details>
<summary>
<span class="descValuePair">
<label>Background</label>
<input type="text" name="attr_background">
<input type="checkbox" name="attr_backgroundUsed">
</span>
</summary>
<textarea name="attr_backgroundDetails"></textarea>
</details>
<details>
<summary>
<span class="descValuePair">
<label>Keepsake </label>
<input type="text" name="attr_keepsake">
<input type="checkbox" name="attr_keepsakeUsed">
</span>
</summary>
<textarea name="attr_keepsakeDetails"></textarea>
</details>
<details>
<summary>
<span class="descValuePair">
<label>Motto </label>
<input type="text" name="attr_motto">
<input type="checkbox" name="attr_mottoUsed">
</span>
</summary>
<textarea name="attr_mottoDetails"></textarea>
</details>
</div>
<div class="marginleft twocolumns">
<div class="descValuePair">
<button type="roll" class="textbutton" value="&{template:criticalinjury}{{name=@{character_name}}}{{roll=[[1d20]]}}">Health</button>
<input id="health" type="number" min="0" name="attr_health" value="10">
<label> of <input type="number" min="0" name="attr_health_max" value="10"></label>
</div>
<div class="descValuePair">
<label for="abilityPts">Ability Pts </label>
<input id="abilityPts" type="number" min="0" name="attr_abilitypts" value="5">
<label> of <input type="number" min="5" name="attr_abilitypts_max" value="5"></label>
</div>
<button type="action" class="textbutton" name="act_downtime">Start Downtime</button>
</div>
</div>
<h3>Weapons</h3>
<div class="weapon">
<label>Name</label>
<label>Range</label>
<label>Damage</label>
</div>
<div>
<fieldset class="repeating_weapons">
<details>
<summary>
<input type="text" name="attr_weaponname" title="Name of the Weapon">
<input type="text" name="attr_range" title="Range">
<input type="text" name="attr_damage" title="Damage">
<button type="roll" title="Fire the Weapon" value="&{template:weapon}{{callsign=@{character_name}}}{{range=@{range}}}{{weapon_name=@{weaponname}}}{{roll=[[1d20]]}}{{damage=@{damage}}}">
</button>
</summary>
<textarea name="attr_weaponDetails"></textarea>
</details>
</fieldset>
</div>
<h3>Inventory</h3>
<div class="inventory">
<details>
<summary>
<input type="text" name="attr_itemname1">
</summary>
<textarea name="attr_itemDetails1"></textarea>
</details>
<details>
<summary>
<input type="text" name="attr_itemname2">
</summary>
<textarea name="attr_itemDetails2"></textarea>
</details>
<details>
<summary>
<input type="text" name="attr_itemname3">
</summary>
<textarea name="attr_itemDetails3"></textarea>
</details>
<details>
<summary>
<input type="text" name="attr_itemname4">
</summary>
<textarea name="attr_itemDetails4"></textarea>
</details>
<details>
<summary>
<input type="text" name="attr_itemname5">
</summary>
<textarea name="attr_itemDetails5"></textarea>
</details>
<details>
<summary>
<input type="text" name="attr_itemname6">
</summary>
<textarea name="attr_itemDetails6"></textarea>
</details>
</div>
<h3>Equipment</h3>
<div class="equipment">
<label>Name</label>
<label>AP/Uses</label>
<label>Range</label>
<label>Action</label>
</div>
<fieldset class="repeating_equipment">
<details class="equipment">
<summary>
<input type="text" name="attr_name" title="Name of the Equipment">
<input type="text" name="attr_cost" title="AP/Uses">
<input type="text" name="attr_range" title="Range">
<input type="text" name="attr_action" title="Action">
</summary>
<textarea name="attr_equipment" class="textarea"></textarea>
</details>
</fieldset>
<h3>Abilities</h3>
<div class="equipment">
<label>Name</label>
<label>AP</label>
<label>Range</label>
<label>Action</label>
</div>
<fieldset class="repeating_abilities">
<details class="equipment">
<summary>
<input type="text" name="attr_name" title="Name of the Ability">
<input type="text" name="attr_cost" title="AP">
<input type="text" name="attr_range" title="Range">
<input type="text" name="attr_action" title="Action">
</summary>
<textarea name="attr_ability" class="textarea"></textarea>
</details>
</fieldset>
</div>
<div class="mech">
<h2>Mech
<button type="roll" value="&{template:roll}{{name=@{character_name}}}{{roll=[[1d20]]}}{{mech=1}}{{heatroll=[[0]]}}"></button>
</h2>
<div style="display:flex">
<div class="twocolumns">
<div class="descValuePair">
<label for="mechname">Name</label>
<input id="mechname" type="text" name="attr_character_name">
</div>
<div class="descValuePair">
<label>System Slots </label>
<span style="display: flex">
<input type="number" name="attr_systems" value="@{systems_used}" disabled>
<label> of </label>
<input type="number" name="attr_systems_max">
</span>
</div>
<div class="descValuePair">
<label >Module Slots </label>
<span style="display: flex">
<input type="number" name="attr_modules" value="@{modules_used}" disabled>
<label> of</label>
<input type="number" name="attr_modules_max">
</span>
</div>
<details>
<summary>
<span class="descValuePair">
<label for="chassis">Chassis Type </label>
<input id="chassis" type="text" name="attr_chassis">
</span>
</summary>
<textarea name="attr_chassisDetails"></textarea>
</details>
</div>
<div class="marginleft twocolumns">
<div class="descValuePair">
<button type="roll" class="textbutton" value="&{template:criticaldamage}{{name=@{character_name}}}{{roll=[[1d20]]}}">Structure</button>
<input type="number" id="structure" min="0" name="attr_structure" value="10">
<label> of <input type="number" min="0" name="attr_structure_max" value="10"></label>
</div>
<input class="show-shield" name="attr_show-shield" type="checkbox" hidden/>
<div class="descValuePair shield">
<label for="shield">Shield</label>
<input type="number" id="shield" min="0" name="attr_shield" value="0">
</div>
<div class="descValuePair">
<label for="energyPts">Energy Pts </label>
<input type="number" id="energyPts" min="0" name="attr_energy" value="10">
<label> of <input type="number" min="0" name="attr_energy_max" value="10"></label>
</div>
<div class="descValuePair">
<button type="roll" class="textbutton" value="&{template:roll}{{name=@{character_name}}}{{mech=1}}{{heatroll=[[1d20]]}}{{heat=[[@{heat}]]}}">Heat</button>
<input type="number" min="0" max="@{heat_max}" name="attr_heat" value="0">
<label> of <input type="number" min="0" name="attr_heat_max" value="10"> </label>
</div>
<button type="action" class="textbutton" name="act_downtime">Start Downtime</button>
</div>
</div>
<h3>Weapons</h3>
<div class="weapon">
<label>Name</label>
<label>Range</label>
<label>Damage</label>
</div>
<div>
<fieldset class="repeating_mechweapons">
<details>
<summary class="rollButton">
<input type="text" name="attr_weaponname" title="Name of the Weapon">
<input type="text" name="attr_range" title="Range">
<input type="text" name="attr_damage" title="Damage">
<button type="action" name="act_roll" title="Fire the Weapon" value="&{template:weapon}{{callsign=@{character_name}}}{{range=@{prefix-range}}}{{weapon_name=@{prefix-weaponname}}}{{roll=[[1d20]]}}{{damage=@{prefix-damage}}}{{weaponheat=[[@{prefix-weaponheat}]]}}{{mech=1}}{{heatroll=[[0]]}}">
</button>
</summary>
<details class="subdetails">
<summary>
Settings
</summary>
<div class="descValuePair">
<label>Heat produced</label>
<input type="number" name="attr_weaponheat" value="0" min="0">
</div>
<div class="descValuePair">
<label>Cost</label>
<input type="text" name="attr_scrap" placeholder="1 T1 Scrap">
</div>
<div class="descValuePair">
<label>Slots</label>
<input type="number" name="attr_slots" value="1">
</div>
</details>
<textarea name="attr_weapondetails"></textarea>
</details>
</fieldset>
</div>
<h3>Cargo <input type="text" name="attr_maxcargo" title="Maximum cargo capacity" style="max-width: 30px;"></h3>
<fieldset class="repeating_cargo">
<details>
<summary>
<input type="text" name="attr_cargoname">
</summary>
<textarea class="textarea" name="attr_cargo"></textarea>
</details>
</fieldset>
<h3>Modules</h3>
<div class="equipment">
<label>Name</label>
<label>EP/Uses</label>
<label>Range</label>
<label>Action</label>
</div>
<fieldset class="repeating_modules">
<details class="equipment">
<summary>
<input type="text" name="attr_name" title="Name of the Equipment">
<input type="text" name="attr_cost" title="EP/Uses">
<input type="text" name="attr_range" title="Range">
<input type="text" name="attr_action" title="Action">
<input type="checkbox" name="attr_is-passive" hidden>
<button type="action" class="textbutton passiv-hide" name="act_use-module">Use</button>
<input type="checkbox" class="show-active" name="attr_has-active" hidden>
<input type="checkbox" class="active" name="attr_active" title="Active">
</summary>
<details class="subdetails">
<summary>
Settings
</summary>
<div class="descValuePair">
<label>Cost</label>
<input type="text" name="attr_scrap" placeholder="1 T1 Scrap">
</div>
<div class="descValuePair">
<label>Slots</label>
<input type="number" name="attr_slots" value="1">
</div>
<div class="descValuePair">
<label>Is passive</label>
<input type="checkbox" name="attr_is-passive">
</div>
<div class="descValuePair">
<label>Has active effect</label>
<input type="checkbox" name="attr_has-active">
</div>
<div class="descValuePair">
<label>Has Uses instead of EP cost</label>
<input type="checkbox" name="attr_has-uses">
</div>
</details>
<textarea name="attr_details" class="textarea"></textarea>
</details>
</fieldset>
<h3>Systems</h3>
<div class="equipment">
<label>Name</label>
<label>EP/Uses</label>
<label>Range</label>
<label>Action</label>
</div>
<fieldset class="repeating_systems">
<details class="equipment">
<summary>
<input type="text" name="attr_name" title="Name of the Equipment">
<input type="text" name="attr_cost" title="EP/Uses">
<input type="text" name="attr_range" title="Range">
<input type="text" name="attr_action" title="Action">
<input type="checkbox" name="attr_is-passive" class="passiv-hide" hidden>
<button type="action" class="textbutton passiv-hide" name="act_use-system">Use</button>
<input type="checkbox" class="show-active" name="attr_has-active" hidden>
<input type="checkbox" class="active" name="attr_active" title="Active">
</summary>
<details class="subdetails">
<summary>
Settings
</summary>
<div class="descValuePair">
<label>Cost</label>
<input type="text" name="attr_scrap" placeholder="1 T1 Scrap">
</div>
<div class="descValuePair">
<label>Slots</label>
<input type="number" name="attr_slots" value="1">
</div>
<div class="descValuePair">
<label>Is passive</label>
<input type="checkbox" name="attr_is-passive">
</div>
<div class="descValuePair">
<label>Has active effect</label>
<input type="checkbox" name="attr_has-active">
</div>
<div class="descValuePair">
<label>Has Uses instead of EP cost</label>
<input type="checkbox" name="attr_has-uses">
</div>
</details>
<textarea name="attr_details" class="textarea"></textarea>
</details>
</fieldset>
</div>
<div class="crawler">
<h2>Crawler
<button type="roll" value="&{template:roll}{{name=@{character_name}}}{{roll=[[1d20]]}}"></button>
</h2>
<div style="display:flex">
<div class="twocolumns">
<div class="descValuePair">
<label for="crawlername">Name</label>
<input id="crawlername" type="text" name="attr_character_name">
</div>
<details>
<summary>
<span class="descValuePair">
<label for="type">Crawler Type</label>
<input id="type" type="text" name="attr_crawlertype">
</span>
</summary>
<textarea name="attr_typeDetails"></textarea>
</details>
<div class="descValuePair">
<label for="techlevel">Tech Level</label>
<input id="techlevel" type="text" name="attr_techlevel">
</div>
<div class="descValuePair">
<label for="upgrade">Upgrade</label>
<input id="upgrade" type="text" name="attr_upgrade">
</div>
</div>
<div class="marginleft twocolumns">
<div class="descValuePair">
<label for="crawlerstructure">Structure</label>
<input type="number" id="crawlerstructure" min="0" name="attr_structure" value="20">
<label> of <input type="number" min="0" name="attr_structure_max" value="20"></label>
</div>
<div class="descValuePair">
<label for="population">Population</label>
<input type="text" id="population" name="attr_population" value="100">
</div>
</div>
</div>
<h3>Weapons</h3>
<div class="weapon">
<label>Name</label>
<label>Range</label>
<label>Damage</label>
</div>
<div>
<fieldset class="repeating_mechweapons">
<details>
<summary>
<input type="text" name="attr_weaponname" title="Name of the Weapon">
<input type="text" name="attr_range" title="Range">
<input type="text" name="attr_damage" title="Damage">
<button type="roll" title="Fire the Weapon" value="&{template:weapon}{{callsign=@{character_name}}}{{range=@{range}}}{{weapon_name=@{weaponname}}}{{roll=[[1d20]]}}{{damage=@{damage}}}">
</button>
</summary>
<details class="subdetails">
<summary>
Settings
</summary>
<div class="descValuePair">
<label>Heat produced</label>
<input type="number" name="attr_heat" value="0">
</div>
<div class="descValuePair">
<label>Cost</label>
<input type="text" name="attr_scrap" placeholder="1 T1 Scrap">
</div>
<div class="descValuePair">
<label>Slots</label>
<input type="number" name="attr_slots" value="1">
</div>
</details>
<textarea name="attr_details"></textarea>
</details>
</fieldset>
</div>
<h3>Crew</h3>
<div class="equipment">
<label>Name</label>
<label>Role</label>
</div>
<fieldset class="repeating_crew">
<details class="equipment">
<summary>
<input type="text" name="attr_name" title="Name of the Crew">
<input type="text" name="attr_role" title="Role of the Crew">
</summary>
<textarea name="attr_details" class="textarea"></textarea>
</details>
</fieldset>
<h3>Cargo</h3>
<fieldset class="repeating_cargo">
<textarea name="attr_cargo" class="textarea"></textarea>
</fieldset>
<h3>Bays</h3>
<fieldset class="repeating_bays">
<details class="equipment">
<summary>
<input type="text" name="attr_name" title="Name of the Bay">
</summary>
<textarea name="attr_details" class="textarea"></textarea>
</details>
</fieldset>
</div>
<div class="notes">
<h2>Notes </h2>
<fieldset class="repeating_notes">
<details class="equipment">
<summary>
<input type="text" name="attr_name" title="Name of the Note">
</summary>
<textarea name="attr_details" class="textarea"></textarea>
</details>
</fieldset>
</div>
<div class="settings">
<br>
<label for="isPilot" class="settings-checkbox">
<span>Is Pilot</span>
<input id="isPilot" name="attr_is-pilot" type="checkbox" checked/>
</label>
<br>
<details>
<summary>
<label for="isMech" class="settings-checkbox">
<span>Is Mech</span>
<input id="isMech" name="attr_is-mech" type="checkbox"/>
</label>
</summary>
<label for="countWeapons" class="settings-checkbox">
<span>Count Weapons as Systems</span>
<input id="countWeapons" name="attr_count-weapons" type="checkbox"/>
</label>
<label for="showShield" class="settings-checkbox">
<span>Show Shield</span>
<input id="showShield" name="attr_show-shield" type="checkbox"/>
</label>
</details>
<br>
<label for="isCrawler" class="settings-checkbox">
<span>Is Crawler</span>
<input id="isCrawler" name="attr_is-crawler" type="checkbox"/>
</label>
<br>
<label for="showNotesTab" class="settings-checkbox">
<span>Show Notes Tab</span>
<input id="showNotesTab" name="attr_show-notes-tab" type="checkbox"/>
</label>
<br>
<details>
<summary>Importer</summary>
<textarea name="attr_importerText" class="textarea" placeholder="To use the importer copy the text from the rulebook and paste it into this window."></textarea>
<button type="action" class="textbutton passiv-hide" name="act_import-mech-stats">Import Mech Stats</button>
<button type="action" class="textbutton passiv-hide" name="act_import-mech-weapon">Import Mech Weapon</button>
<button type="action" class="textbutton passiv-hide" name="act_import-mech-system">Import Mech System</button>
<button type="action" class="textbutton passiv-hide" name="act_import-mech-module">Import Mech Module</button>
</details>
</div>
</div>
<!-- Buttons used for reaction rolls-->
<div class="hidden-section" style="display:none">
<button type="action" name="act_reactPush"></button>
<button type="action" name="act_reactPushWeapon"></button>
<button type="action" name="act_reactOverload"></button>
</div>
<script type="text/worker">
const buttonlist = ["pilot","mech","crawler","notes","settings"];
buttonlist.forEach(button => {
on(`clicked:${button}`, function() {
setAttrs({
sheetTab: button
});
});
});
on("sheet:opened", (eventInfo) => {
getAttrs(['character_name'], (v) => {
set_display_name(v.character_name);
});
});
on("change:character_name", (eventInfo) => {
set_display_name(eventInfo.newValue);
});
var set_display_name = (name) => {
character_name = name.replace(/\(/g, '\[').replace(/\)/g, '\]').replace(/\"/g, '\'');
setAttrs({
character_name: character_name
});
};
on('change:repeating_modules remove:repeating_modules sheet:opened', function() {
repeatingSum("modules_used", "slots", "repeating_modules");
});
on('change:repeating_systems remove:repeating_systems change:repeating_mechweapons remove:repeating_mechweapons sheet:opened', async function() {
let countWeapons = (await asw.getAttrs(["count-weapons"]))["count-weapons"];
if(countWeapons == 'on') {
repeatingSum("systems_used", "slots", "repeating_systems", "repeating_mechweapons");
}
else {
repeatingSum("systems_used", "slots", "repeating_systems");
}
});
////////////////////////////
// ROLL AUTOMATION ////
///////////////////////////
on('clicked:repeating_mechweapons:roll',
async (event) => {
// prefix gets an empty string for normal attributes, and repeating_section_ID_ for repeating attributes
var prefix = event.sourceAttribute.split('_').slice(0,3).join('_') + '_'
let rollPart = event.htmlAttributes.value.replaceAll('prefix-', `${prefix}`);
let results = await startRoll(rollPart);
let attrs = await asw.getAttrs(['heat']);
let resultingHeat = parseInt(attrs.heat) + results.results.weaponheat.result;
asw.setAttrs({
heat: resultingHeat
});
finishRoll(
results.rollId,
{}
);
});
on('clicked:reactPush', async (ev) => {
await push(ev, 'roll');
});
on('clicked:reactPushWeapon', async (ev) => {
await push(ev, 'weapon');
});
const push = async (ev, template) => {
let attrs = await asw.getAttrs(['character_name', 'heat']);
let resultingHeat = parseInt(attrs.heat) + 2;
let rollBase = `&{template:${template}}{{name=${attrs.character_name}}}{{roll=[[1d20]]}}{{mech=1}}{{heatroll=[[1d20]]}}{{heat=[[${resultingHeat}]]}}`;
let roll = await startRoll(rollBase);
asw.setAttrs({
heat: resultingHeat
});
finishRoll(roll.rollId, {
});
}
on('clicked:reactOverload', async (ev) => {
await reactOverload(ev);
});
const reactOverload = async (ev) => {
let attrs = await asw.getAttrs(['character_name', 'heat', 'heat_max']);
let rollBase = `&{template:overload}{{name=${attrs.character_name}}}{{roll=[[1d20]]}}{{heat=${attrs.heat}}}{{maxheat=${attrs.heat_max}}}`;
let roll = await startRoll(rollBase);
finishRoll(roll.rollId, {});
}
on('clicked:downtime', async (ev) => {
let attrs = await asw.getAttrs(['health_max', 'abilitypts_max', 'structure_max', 'energy_max']);
asw.setAttrs({
health: attrs['health_max'],
abilitypts: attrs['abilitypts_max'],
structure: attrs['structure_max'],
energy: parseInt(attrs['energy_max']),
heat: 0,
});
});
on('clicked:repeating_modules:use-module clicked:repeating_systems:use-system', async (event) => {
// prefix gets an empty string for normal attributes, and repeating_section_ID_ for repeating attributes
var trigger = event.triggerName.slice(8); // this always starts with 'clicked:'
var prefix = trigger.split('_').slice(0,3).join('_') + '_'
let attrs = await asw.getAttrs(['character_name', 'energy', prefix+'name', prefix+'cost', prefix+'has-uses']);
let cost = parseInt(attrs[prefix+'cost']);
let toSet = {}
let rollBase = `/w ${attrs.character_name} &{template:info}{{info= You activated ${attrs[prefix+'name']} for `;
if(attrs[prefix+'has-uses'] ==! 'on') {
toSet.energy = attrs['energy'] - cost;
rollBase += `${cost} EP. ${toSet.energy} Energy remaining}}`
}
else {
toSet[prefix+'cost'] = cost-1;
rollBase += `1 use. ${toSet[prefix+'cost']} Uses remaining}}`
}
toSet[prefix+'active'] = 'on';
asw.setAttrs(toSet);
let roll = await startRoll(rollBase);
finishRoll(roll.rollId, {});
});
/////////////////////
// IMPORTER ////
/////////////////////
on('clicked:import-mech-stats', async (ev) => {
let mech = {};
let toImport = (await asw.getAttrs(['importerText'])).importerText;
let stats = toImport.replaceAll(/[a-zA-Z]/g, '').replaceAll(/\./g, '').replaceAll(/^\s*[\r\n]/gm, '').trim().split(/\r?\n|\s+/);
if(stats.length < 6) {
asw.setAttrs({
importerText: 'Could not parse input: Not enough values'
});
return;
}
if(!toImport.startsWith(' ') && !/^\d+/g.test(toImport)) {
let name = toImport.split(/\r?\n/)[0].trim().replace(/(\w)(\w*)/g, (_, firstChar, rest) => firstChar + rest.toLowerCase());
mech.character_name = name;
mech.chassis = name;
}
if(/CHASSIS\s*ABILITY/.test(toImport)) {
mech.chassisDetails = toImport.split(/CHASSIS\s*ABILITY/)[1].replaceAll(/[\r\n]/gm, '').trim();
}
mech.structure = stats[0];
mech.structure_max = stats[0];
mech.energy = stats[1];
mech.energy_max = stats[1];
mech.heat_max = stats[2];
mech.systems_max = stats[3];
mech.modules_max = stats[4];
mech.maxcargo = stats[5];
mech.importerText = "Values imported";
await asw.setAttrs(mech);
});
on('clicked:import-mech-weapon', async (ev) => {
let toImport = removeLineBreakInRules((await asw.getAttrs(['importerText'])).importerText);
var row = "repeating_mechweapons_" + generateRowID() + "_";
let weapon = {};
if(/T\d/.test(toImport)) {
let tier = toImport.match(/T\d/).pop();
let associatedCost = toImport.split(/T\d/)[1].trim().split(/\r?\n|\s+/)
weapon[row + "scrap"] = associatedCost[1] + " " + tier;
weapon[row + "slots"] = parseInt(associatedCost[0]);
toImport = toImport.split(/T\d/)[0].trim()
}
toImport = toImport.replaceAll(/[\r\n]/gm, '#').split('#');
weapon[row + "weaponname"] = toImport[0];
weapon[row + "range"] = toImport[1].split('//')[0].replaceAll(/[a-zA-Z]*:/g, '').trim();
weapon[row + "damage"] = toImport[1].split('//')[1].replaceAll(/[a-zA-Z]*:/g, '').trim();
if(toImport[1].includes("Hot (")) {
weapon[row + "weaponheat"] = toImport[1].match(/Hot \(\d\)/g).pop().match(/\d+/).pop();
}
else {
weapon[row + "weaponheat"] = 0;
}
weapon[row + "weapondetails"] = toImport[1].split('//').slice(2).join('//').trim() + "\n" + toImport.slice(2).join(' ').trim();
weapon["importerText"] ='Values imported'
asw.setAttrs(weapon);
});
on('clicked:import-mech-system', async (ev) => {
let toImport = removeLineBreakInRules((await asw.getAttrs(['importerText'])).importerText);
var row = "repeating_systems_" + generateRowID() + "_";
let system = {};
system[row + "name"] = toImport.split(/\r?\n/)[0].trim().replace(/(\w)(\w*)/g, (_, firstChar, rest) => firstChar + rest.toLowerCase());
if(toImport.split(/\r?\n/)[1].includes("EP")) {
system[row + "cost"] = toImport.split(/\r?\n/)[1].trim();
toImport = toImport.replaceAll(toImport.split(/\r?\n/)[1], '');
}
toImport = toImport.replaceAll(/^\s*[\r\n]/gm, '');
let rules = toImport.split(/\r?\n/)[1].trim();
if(rules.includes("Range:")) {
system[row + "range"] = rules.split('Range:')[1].split('//')[0].replaceAll(/[a-zA-Z]*:/g, '').trim()
rules = rules.split('//').slice(1).join('//').trim()
}
if(/T\d/.test(toImport)) {
let tier = toImport.match(/T\d/).pop();
let associatedCost = toImport.split(/T\d/)[1].trim().split(/\r?\n|\s+/)
system[row + "scrap"] = associatedCost[1] + " " + tier;
system[row + "slots"] = associatedCost[0];
toImport = toImport.split(/T\d/)[0].trim()
}
let longtext = toImport.split('\n').slice(2).join('').trim();
system[row + "details"] = rules + "\n" + longtext;
system.importerText = 'Values imported'
asw.setAttrs(system);
});
on('clicked:import-mech-module', async (ev) => {
let toImport = removeLineBreakInRules((await asw.getAttrs(['importerText'])).importerText);
var row = "repeating_modules_" + generateRowID() + "_";
let module = {};
module[row + "name"] = toImport.split(/\r?\n/)[0].trim().replace(/(\w)(\w*)/g, (_, firstChar, rest) => firstChar + rest.toLowerCase());
if(toImport.split(/\r?\n/)[1].includes("EP")) {
module[row + "cost"] = toImport.split(/\r?\n/)[1].trim();
toImport = toImport.replaceAll(toImport.split(/\r?\n/)[1], '');
}
toImport = toImport.replaceAll(/^\s*[\r\n]/gm, '');
let rules = toImport.split(/\r?\n/)[1].trim();
if(rules.includes("Range:")) {
module[row + "range"] = rules.split('Range:')[1].split('//')[0].replaceAll(/[a-zA-Z]*:/g, '').trim()
rules = rules.split('//').slice(1).join('//').trim()
}
if(/T\d/.test(toImport)) {
let tier = toImport.match(/T\d/).pop();
let associatedCost = toImport.split(/T\d/)[1].trim().split(/\r?\n|\s+/)
module[row + "scrap"] = associatedCost[1] + " " + tier;
module[row + "slots"] = associatedCost[0];
toImport = toImport.split(/T\d/)[0].trim()
}
let longtext = toImport.split('\n').slice(2).join('').trim();
module[row + "details"] = rules + "\n" + longtext;
module.importerText = 'Values imported'
asw.setAttrs(module);
});
///////////////////
// HELPER ////
///////////////////
const removeLineBreakInRules = (toImport) => {
return toImport.replaceAll(/\/\/\s*[\r\n]/gm, '// ').replaceAll(/[\r\n]/gm, '#').replaceAll(/#\/\//g, '//').replaceAll(/#/g, '\n')
};
async function repeatingSum (destination, fieldsum, ...sections){
// destination = the name of the attribute that stores the total
// fieldsum = the name of the field to be summed
// sections = name for/of repeating fieldset, without the repeating_
let attrs = [];
await Promise.all(sections.map(async (section) => {
let ids = await asw.getSectionIDs(section);
var sumFields = [];
for (var a=0; a< ids.length; a++) {
sumFields[sumFields.length] = section + "_" + ids[a] + "_" + fieldsum;
}
attrs.push(...sumFields);
}
));
let values = await asw.getAttrs(attrs);
let sumTotal = 0;
let tempSum = 0;
for(a=0; a < attrs.length; a++){
tempSum = parseFloat(values[attrs[a]],10) || 0;
sumTotal += tempSum;
}
var setSumValue = {};
setSumValue[destination] = sumTotal;
asw.setAttrs(setSumValue);
}
const asw = (() => {
const setActiveCharacterId = function(charId){
let oldAcid=getActiveCharacterId();
let ev = new CustomEvent("message");
ev.data={"id":"0", "type":"setActiveCharacter", "data":charId};
self.dispatchEvent(ev);
return oldAcid;
};
const promisifyWorker = (worker, parameters) => {
let acid=getActiveCharacterId();
let prevAcid=null;
return new Promise((res,rej)=>{
prevAcid=setActiveCharacterId(acid);
try {if (worker===0) getAttrs(parameters[0]||[],(v)=>res(v));
else if (worker===1) setAttrs(parameters[0]||{}, parameters[1]||{},(v)=>res(v));
else if (worker===2) getSectionIDs(parameters[0]||'',(v)=>res(v));
} catch(err) {rej(console.error(err))}
}).finally(()=>setActiveCharacterId(prevAcid));
}
return {
getAttrs(attrArray) {return promisifyWorker(0, [attrArray])},
setAttrs(attrObj, options) {return promisifyWorker(1, [attrObj, options])},
getSectionIDs(section) {return promisifyWorker(2, [section])},
setActiveCharacterId,
}
})();
</script>
<rolltemplate class="sheet-rolltemplate-roll">
<table>
<tr>
<th>
{{name}} rolls
</th>
</tr>
<tr>
<td>
<div class="sheet-rolltemplate-spacer"></div>
</td>
</tr>
<tr>
<td>
{{#rollBetween() roll 20 20}}
<strong>Nailed it</strong> ({{roll}}) <br>
You have overcome the odds and managed an outstanding success. You may achieve an additional bonus of your choice to the action. When dealing damage you double it.
{{/rollBetween() roll 20 20}}
{{#rollBetween() roll 11 19}}
Success ({{roll}}) - You’ve achieved your goal without any compromises.
{{/rollBetween() roll 11 19}}
{{#rollBetween() roll 6 10}}
Tough Choice ({{roll}}) - You succeed in your action but at a cost. The Mediator will give you a tough choice with some kind of consequence.
{{/rollBetween() roll 6 10}}
{{#rollBetween() roll 2 5}}
Failure ({{roll}}) - You’ve failed at what you were attempting, and you’ll face a consequence of The Mediator’s choice.
{{/rollBetween() roll 2 5}}
{{#rollBetween() roll 1 1}}
Cascade Failure ({{roll}}) - You have not only failed, but something has gone terribly wrong. You will suffer a severe consequence of The Mediator’s choice.
{{/rollBetween() roll 1 1}}
</td>
</tr>
{{#heat}}
<tr>
<td>
<div class="sheet-rolltemplate-spacer"></div>
</td>
</tr>
<tr>
<td>
Heat Check: {{heat}} vs {{heatroll}}
</td>
</tr>
{{/heat}}
</table>
{{#mech}}
<div class="sheet-rolltemplate-button-row">
{{#rollTotal() heatroll 0}}
<div class="sheet-rolltemplate-button">
[Push](~{{name}}|reactPush)
</div>
{{/rollTotal() heatroll 0}}
{{#^rollGreater() heatroll heat}}
<div class="sheet-rolltemplate-button">
[Reactor Overload](~{{name}}|reactOverload)
</div>
{{/^rollGreater() heatroll heat}}
</div>
{{/mech}}
</rolltemplate>
<rolltemplate class="sheet-rolltemplate-weapon">
<table>
<tr>
<th>
{{callsign}} rolls an attack on range {{range}} with {{weapon_name}}
</th>
</tr>
<tr>
<td>
<div class="sheet-rolltemplate-spacer"></div>
</td>
</tr>
<tr>
<td>
{{#rollBetween() roll 20 20}}
<strong>Nailed it</strong> ({{roll}}) <br>
You have overcome the odds and managed an outstanding success. You may achieve an additional bonus of your choice to the action e.g. double the damage.
{{/rollBetween() roll 20 20}}
{{#rollBetween() roll 11 19}}
Success ({{roll}}) - You hit the target and deal standard damage
{{/rollBetween() roll 11 19}}
{{#rollBetween() roll 6 10}}
Tough Choice ({{roll}}) - You succeed in your action but at a cost. The Mediator will give you a tough choice with some kind of consequence. You hit but something has
gone wrong.
{{/rollBetween() roll 6 10}}
{{#rollBetween() roll 2 5}}
Failure ({{roll}}) - You miss the target.
{{/rollBetween() roll 2 5}}
{{#rollBetween() roll 1 1}}
Cascade Failure ({{roll}}) - You miss the target and something has gone wrong.
{{/rollBetween() roll 1 1}}
</td>
</tr>
{{#damage}}
<tr>
<td>
<div class="sheet-rolltemplate-spacer"></div>
</td>
</tr>
<tr>
<td>
Weapondamage: {{damage}}
</td>
</tr>
{{/damage}}
{{#^rollTotal() weaponheat 0}}
<tr>
<td>
Weaponheat: {{weaponheat}}
</td>
</tr>
{{/^rollTotal() weaponheat 0}}
{{#heat}}
<tr>
<td>
<div class="sheet-rolltemplate-spacer"></div>
</td>
</tr>
<tr>
<td>
Heat Check: {{heat}} vs {{heatroll}}
</td>
</tr>
{{/heat}}
</table>
{{#mech}}
<div class="sheet-rolltemplate-button-row">
{{#rollTotal() heatroll 0}}
<div class="sheet-rolltemplate-button">
[Push](~{{callsign}}|reactPushWeapon)
</div>
{{/rollTotal() heatroll 0}}
{{#^rollGreater() heatroll heat}}
<div class="sheet-rolltemplate-button">
[Reactor Overload](~{{callsign}}|reactOverload)
</div>
{{/^rollGreater() heatroll heat}}
</div>
{{/mech}}
</rolltemplate>
<rolltemplate class="sheet-rolltemplate-criticalinjury">
<table>
<tr>
<th>
{{name}} rolls
</th>
</tr>
<tr>
<td>
<div class="sheet-rolltemplate-spacer"></div>
</td>
</tr>
<tr>
<td>
{{#rollBetween() roll 20 20}}
<strong>Miraculous Survival</strong> ({{roll}}) <br>
You survive against the odds. You have 1 HP, remain conscious and can act normally.
{{/rollBetween() roll 20 20}}
{{#rollBetween() roll 11 19}}
Unconscious ({{roll}}): You are stable at 0 HP, but unconscious and cannot move or take actions until you gain at least 1 HP. You will regain consciousness naturally in 1 hour and get back up with 1 HP.
{{/rollBetween() roll 11 19}}
{{#rollBetween() roll 6 10}}
Minor Injury ({{roll}}): You suffer a Minor Injury such as a sprain, burns, or minor concussion. Your Max HP are reduced by 1 until healed in a Tech 3 - 4 MedBay. In addition, you are Unconscious. Apply the result of 11 - 19.
{{/rollBetween() roll 6 10}}
{{#rollBetween() roll 2 5}}
Major Injury ({{roll}}): You suffer a Major Injury such as permanent scarring, broken ribs, or internal injuries. Your Max HP is reduced by 2 until healed in a Tech 5 - 6 MedBay. In addition, you are Unconscious. Apply the result of 11-19.
{{/rollBetween() roll 2 5}}
{{#rollBetween() roll 1 1}}
Fatal Injury ({{roll}}): Your Pilot suffers a fatal injury and dies.
{{/rollBetween() roll 1 1}}
</td>
</tr>
</table>
</rolltemplate>
<rolltemplate class="sheet-rolltemplate-overload">
<table>
<tr>
<th>
{{name}} rolls
</th>
</tr>
<tr>
<td>
<div class="sheet-rolltemplate-spacer"></div>
</td>
</tr>
<tr>
<td>
{{#rollBetween() roll 20 20}}
<strong>Reactor Overdrive</strong> ({{roll}}) <br>
Your Mech’s reactor goes into overdrive. Your Mech can take any additional action this turn or Push their next roll within 10 minutes for free.
{{/rollBetween() roll 20 20}}
{{#rollBetween() roll 11 19}}
Reactor Overheat ({{roll}}) - Your Mech’s reactor has overheated. Your Mech shuts down and gains the Vulnerable Trait. Your Mech will re-activate at the end of your next turn. In addition, your Mech takes {{heat}} of SP damage.
{{/rollBetween() roll 11 19}}
{{#rollBetween() roll 6 10}}
Module Overload ({{roll}}) - One of your Mech’s Modules chosen at random or by the Mediator is destroyed.
{{/rollBetween() roll 6 10}}
{{#rollBetween() roll 2 5}}
System Overload ({{roll}}) - One of your Mech’s Systems chosen at random or by the Mediator is destroyed.
{{/rollBetween() roll 2 5}}
{{#rollBetween() roll 1 1}}
Reactor Overload ({{roll}}) - Your Mech’s reactor goes into full meltdown and explodes. Your Mech, as well as any mounted Systems, Modules, and all Cargo, is destroyed in the explosion. Everything in Close Range of your Mech takes {{maxheat}} SP damage. They may take any Turn Action or Reaction in response to try to avoid this. Your Pilot dies unless they have a means to escape. The area your Mech was in becomes irradiated.
{{/rollBetween() roll 1 1}}
</td>
</tr>
</table>
</rolltemplate>
<rolltemplate class="sheet-rolltemplate-criticaldamage">
<table>
<tr>
<th>
{{name}} rolls
</th>
</tr>
<tr>
<td>
<div class="sheet-rolltemplate-spacer"></div>
</td>
</tr>
<tr>
<td>
{{#rollBetween() roll 20 20}}
<strong> Miraculous Survival</strong> ({{roll}}) <br>
Your Mech is somehow Intact. It has 1 SP and is still fully operational. Your Pilot is unharmed.
{{/rollBetween() roll 20 20}}
{{#rollBetween() roll 11 19}}
Core Damage ({{roll}}): Your Mech Chassis is damaged and inoperable until repaired. All mounted Systems and Modules remain Intact. Your Pilot is reduced to 0 HP unless they have some means to escape the Mech.
{{/rollBetween() roll 11 19}}
{{#rollBetween() roll 6 10}}
Module Destruction ({{roll}}): A Module mounted on your Mech is destroyed. This is chosen by the Mediator or at random. Your Mech Chassis is damaged and inoperable until repaired. Your Pilot is unharmed.
{{/rollBetween() roll 6 10}}
{{#rollBetween() roll 2 5}}
System Destruction ({{roll}}): A System mounted on your Mech is destroyed. This is chosen by the Mediator or at random. Your Mech Chassis is damaged and inoperable until repaired. Your Pilot is unharmed.
{{/rollBetween() roll 2 5}}
{{#rollBetween() roll 1 1}}
Catastrophic Damage ({{roll}}): The Mech, as well as any mounted Systems and Modules as well as all Cargo, is destroyed. Your Pilot dies unless they have a means to escape the Mech.
{{/rollBetween() roll 1 1}}
</td>
</tr>
</table>
</rolltemplate>
<rolltemplate class="sheet-rolltemplate-info">
<div>
{{info}}
</div>
</rolltemplate>