Files
roll20-character-sheets/walking_dead/walking_dead.html
T
Scott Casey 85c8dfb64e Walking Dead 1.0 release (#12979)
* walking dead 1.0 release

* fix compendium name
2024-06-04 16:55:17 -04:00

6404 lines
421 KiB
HTML

<button name="act_k-network-call" hidden="" type="action">
</button>
<!-- An absolutely positioned decorative element that styles a relatively positioned repitem to look like a notecard. --><!-- Inserted fonts:"Material+Icons+Outlined" -->
<input name="attr_character_id" type="hidden" title="@{character_id}"/>
<input name="attr_script_character_name" type="hidden" title="@{script_character_name}"/>
<input name="attr_sheet_version" value="0" type="hidden" title="@{sheet_version}"/>
<button name="act_push" hidden="" type="action">
</button>
<div class="compendium-drop-target npcs havens vehicles">
<input name="attr_drop_name" accept="Name" value="" type="hidden" title="@{drop_name}"/>
<input name="attr_drop_data" accept="data" value="" type="hidden" title="@{drop_data}"/><!-- sectionName:walking-dead -->
<input name="attr_walking_dead_tab" value="nav-tabs-walking-dead--settings" type="hidden" title="@{walking_dead_tab}"/>
<div class="tabs tabs--walking-dead">
<nav class="tabs__header tabs--walking-dead__header">
<ul class="tabs__nav-list">
<li class="tabs__nav-item">
<button class="tabs__button tabs--walking-dead__button tabs--walking-dead__button--character" name="act_nav-tabs-walking-dead--character" data-container-button="walking-dead" data-button="character" data-i18n="tabs-walking-dead-character" type="action" data-container-tab="walking-dead" data-tab="character">
</button>
</li>
<li class="tabs__nav-item">
<button class="tabs__button tabs--walking-dead__button tabs--walking-dead__button--npc" name="act_nav-tabs-walking-dead--npc" data-container-button="walking-dead" data-button="npc" data-i18n="tabs-walking-dead-npc" type="action" data-container-tab="walking-dead" data-tab="npc">
</button>
</li>
<li class="tabs__nav-item">
<button class="tabs__button tabs--walking-dead__button tabs--walking-dead__button--challenge" name="act_nav-tabs-walking-dead--challenge" data-container-button="walking-dead" data-button="challenge" data-i18n="tabs-walking-dead-challenge" type="action" data-container-tab="walking-dead" data-tab="challenge">
</button>
</li>
<li class="tabs__nav-item">
<button class="tabs__button tabs--walking-dead__button tabs--walking-dead__button--haven" name="act_nav-tabs-walking-dead--haven" data-container-button="walking-dead" data-button="haven" data-i18n="tabs-walking-dead-haven" type="action" data-container-tab="walking-dead" data-tab="haven">
</button>
</li>
<li class="tabs__nav-item">
<button class="tabs__button tabs--walking-dead__button tabs--walking-dead__button--faction" name="act_nav-tabs-walking-dead--faction" data-container-button="walking-dead" data-button="faction" data-i18n="tabs-walking-dead-faction" type="action" data-container-tab="walking-dead" data-tab="faction">
</button>
</li>
<li class="tabs__nav-item">
<button class="tabs__button tabs--walking-dead__button tabs--walking-dead__button--gm" name="act_nav-tabs-walking-dead--gm" data-container-button="walking-dead" data-button="gm" data-i18n="tabs-walking-dead-gm" type="action" data-container-tab="walking-dead" data-tab="gm">
</button>
</li>
<li class="tabs__nav-item">
<button class="tabs__button tabs--walking-dead__button tabs--walking-dead__button--travel-log" name="act_nav-tabs-walking-dead--travel-log" data-container-button="walking-dead" data-button="travel-log" data-i18n="tabs-walking-dead-travel-log" type="action" data-container-tab="walking-dead" data-tab="travel-log">
</button>
</li>
<li class="tabs__nav-item">
<button class="tabs__button tabs--walking-dead__button tabs--walking-dead__button--vehicle" name="act_nav-tabs-walking-dead--vehicle" data-container-button="walking-dead" data-button="vehicle" data-i18n="tabs-walking-dead-vehicle" type="action" data-container-tab="walking-dead" data-tab="vehicle">
</button>
</li>
<li class="tabs__nav-item">
<button class="tabs__button tabs--walking-dead__button tabs--walking-dead__button--settings material-icons" name="act_nav-tabs-walking-dead--settings" data-container-button="walking-dead" data-button="settings" type="action" data-container-tab="walking-dead" data-tab="settings">settings
</button>
</li>
</ul>
</nav>
<div class="tabs__body tabs--walking-dead__body">
<article class="tabs__container tabs--walking-dead__container tabs--walking-dead__container--character pc-page" data-container-tab="walking-dead" data-tab="character">
<section class="pc-info-section" data-i18n-aria-label="character info"><img class="logo" src="https://files.d20.io/images/368479329/HgW2WAq5CUmayPMeTQow3A/original.png"/>
<label class="input-label stacked character-name"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_character_name" type="text" title="@{character_name}"/>
</label>
<label class="input-label stacked archetype"><span class="input-label__text" data-i18n="archetype"></span>
<input class="input-label__input" name="attr_archetype" type="text" title="@{archetype}"/>
</label>
<label class="input-label stacked description"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_character_description" title="@{character_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_character_description" type="text" title="@{character_description}"></textarea>
</div>
</label>
<label class="input-label stacked pc-anchor"><span class="input-label__text" data-i18n="pc anchor"></span>
<input class="input-label__input" name="attr_pc_anchor" type="text" title="@{pc_anchor}"/>
</label>
<label class="input-label stacked npc-anchor"><span class="input-label__text" data-i18n="npc anchor"></span>
<input class="input-label__input" name="attr_npc_anchor" type="text" title="@{npc_anchor}"/>
</label>
<label class="input-label stacked notes"><span data-i18n="notes"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_character_notes" title="@{character_notes}"></span>
<textarea class="adaptive--text__textarea" name="attr_character_notes" type="text" title="@{character_notes}"></textarea>
</div>
</label>
<div class="flex-box half-gap justify-space-between drive">
<label class="input-label stacked"><span class="input-label__text" data-i18n="drive"></span>
<input class="input-label__input" name="attr_drive" type="text" title="@{drive}"/>
</label>
<input class="red-border" name="attr_drive_used" value="1" type="checkbox" title="@{drive_used}"/>
</div>
<label class="input-label stacked issues"><span data-i18n="issues"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_character_issues" title="@{character_issues}"></span>
<textarea class="adaptive--text__textarea" name="attr_character_issues" type="text" title="@{character_issues}"></textarea>
</div>
</label>
</section>
<section class="head-section attributes-skills--section">
<div class="header attributes-skills--header half-gap">
<h3 data-i18n="attributes &amp; skills"></h3>
<div class="sub-header flex-box half-gap flex-wrap">
<label class="input-label"><span class="input-label__text" data-i18n="stress"></span>
<input class="input-label__input" name="attr_stress" type="number" title="@{stress}"/>
</label>
<label class="input-label"><span class="input-label__text" data-i18n="experience"></span>
<input class="input-label__input" name="attr_experience" type="number" title="@{experience}"/>
</label>
</div>
</div>
<div class="section-content attributes-skills--content">
<div class="ability-column">
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="strength" role="heading" aria-level="4" name="roll_strength" value="@{strength_action}" type="roll">
</button>
<button name="act_strength-action" hidden="" type="action">
</button>
<input name="attr_strength_action" type="hidden" title="@{strength_action}"/>
<input class="red-border" name="attr_strength" value="2" type="number" title="@{strength}"/>
</div>
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="close combat" role="heading" aria-level="4" name="roll_close_combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{close_combat_action}"/>
<input class="red-border" name="attr_close_combat" value="0" type="number" title="@{close_combat}"/>
</div>
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="endure" role="heading" aria-level="4" name="roll_endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{endure_action}"/>
<input class="red-border" name="attr_endure" value="0" type="number" title="@{endure}"/>
</div>
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="force" role="heading" aria-level="4" name="roll_force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{force_action}"/>
<input class="red-border" name="attr_force" value="0" type="number" title="@{force}"/>
</div>
</div>
<div class="ability-column">
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="agility" role="heading" aria-level="4" name="roll_agility" value="@{agility_action}" type="roll">
</button>
<button name="act_agility-action" hidden="" type="action">
</button>
<input name="attr_agility_action" type="hidden" title="@{agility_action}"/>
<input class="red-border" name="attr_agility" value="2" type="number" title="@{agility}"/>
</div>
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="mobility" role="heading" aria-level="4" name="roll_mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{mobility_action}"/>
<input class="red-border" name="attr_mobility" value="0" type="number" title="@{mobility}"/>
</div>
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="ranged combat" role="heading" aria-level="4" name="roll_ranged_combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{ranged_combat_action}"/>
<input class="red-border" name="attr_ranged_combat" value="0" type="number" title="@{ranged_combat}"/>
</div>
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="stealth" role="heading" aria-level="4" name="roll_stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{stealth_action}"/>
<input class="red-border" name="attr_stealth" value="0" type="number" title="@{stealth}"/>
</div>
</div>
<div class="ability-column">
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="wits" role="heading" aria-level="4" name="roll_wits" value="@{wits_action}" type="roll">
</button>
<button name="act_wits-action" hidden="" type="action">
</button>
<input name="attr_wits_action" type="hidden" title="@{wits_action}"/>
<input class="red-border" name="attr_wits" value="2" type="number" title="@{wits}"/>
</div>
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="scout" role="heading" aria-level="4" name="roll_scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{scout_action}"/>
<input class="red-border" name="attr_scout" value="0" type="number" title="@{scout}"/>
</div>
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="survival" role="heading" aria-level="4" name="roll_survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{survival_action}"/>
<input class="red-border" name="attr_survival" value="0" type="number" title="@{survival}"/>
</div>
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="tech" role="heading" aria-level="4" name="roll_tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{tech_action}"/>
<input class="red-border" name="attr_tech" value="0" type="number" title="@{tech}"/>
</div>
</div>
<div class="ability-column">
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="empathy" role="heading" aria-level="4" name="roll_empathy" value="@{empathy_action}" type="roll">
</button>
<button name="act_empathy-action" hidden="" type="action">
</button>
<input name="attr_empathy_action" type="hidden" title="@{empathy_action}"/>
<input class="red-border" name="attr_empathy" value="2" type="number" title="@{empathy}"/>
</div>
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="leadership" role="heading" aria-level="4" name="roll_leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{leadership_action}"/>
<input class="red-border" name="attr_leadership" value="0" type="number" title="@{leadership}"/>
</div>
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="manipulation" role="heading" aria-level="4" name="roll_manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{manipulation_action}"/>
<input class="red-border" name="attr_manipulation" value="0" type="number" title="@{manipulation}"/>
</div>
<div class="input-label flex-row-reverse justify-space-between ability-skill-entry">
<button class="embossed roller" data-i18n="medicine" role="heading" aria-level="4" name="roll_medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{medicine_action}"/>
<input class="red-border" name="attr_medicine" value="0" type="number" title="@{medicine}"/>
</div>
</div>
</div>
</section>
<div class="pc-weapon-armor-container">
<section class="head-section pc-armor-section">
<div class="header column-subgrid grid-span-all">
<h3 data-i18n="armor"></h3>
<h4 data-i18n="protection"></h4>
<h4 data-i18n="penalty"></h4>
</div>
<div class="section-content column-subgrid grid-span-all border-back">
<input class="border-back-container" name="attr_armor_name" value="" type="text" title="@{armor_name}"/>
<input class="full-width-number border-back-container" name="attr_armor_protection" type="number" title="@{armor_protection}"/>
<input class="full-width-number border-back-container" name="attr_armor_penalty" type="number" title="@{armor_penalty}"/>
</div>
</section>
<section class="head-section pc-weapon-section">
<div class="header column-subgrid grid-span-all">
<h3 data-i18n="weapons"></h3>
<h4 data-i18n="damage"></h4>
<h4 data-i18n="bonus"></h4>
<h4 data-i18n="range"></h4>
</div>
<div class="section-content column-subgrid grid-span-all pc-weapon-content">
<button class="repcontrol-button repcontrol-button--add" name="act_add-weapons" type="action">
</button>
<fieldset class="repeating_weapons"><!-- fieldset prefix: -->
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_weapons_$X_collapse}"/>
<div class="cardExpanded expanded">
</div>
<button class="collapsed embossed roller" name="roll_roll" value="@{action}" type="roll"><span name="attr_name" title="@{repeating_weapons_$X_name}"></span>
</button>
<button name="act_action" hidden="" type="action">
</button>
<input name="attr_action" type="hidden" title="@{repeating_weapons_$X_action}"/><span class="collapsed summary-details" name="attr_damage" title="@{repeating_weapons_$X_damage}"></span><span class="collapsed summary-details" name="attr_bonus" title="@{repeating_weapons_$X_bonus}"></span><span class="collapsed summary-details" name="attr_range" title="@{repeating_weapons_$X_range}"></span>
<div class="input-label input-label--button expanded">
<button class="icon-roller roller" name="roll_roll" value="@{action}" type="roll">
</button>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_weapons_$X_name}"/>
</div>
<button name="act_action" hidden="" type="action">
</button>
<input name="attr_action" type="hidden" title="@{repeating_weapons_$X_action}"/>
<input class="red-border expanded summary-details" name="attr_damage" type="number" data-i18n-placeholder="damage" title="@{repeating_weapons_$X_damage}"/>
<input class="red-border expanded summary-details" name="attr_bonus" type="number" data-i18n-placeholder="bonus" title="@{repeating_weapons_$X_bonus}"/>
<input class="red-border expanded summary-details" name="attr_range" type="text" data-i18n-placeholder="range" title="@{repeating_weapons_$X_range}"/>
<div class="expanded grid-span-all weapon-details">
<label class="input-label" style="justify-self: end;"><span class="input-label__text" data-i18n="skill"></span>
<select class="input-label__input" name="attr_skill" title="@{repeating_weapons_$X_skill}">
<option value="close combat" data-i18n="close combat" selected="">
</option>
<option value="endure" data-i18n="endure">
</option>
<option value="force" data-i18n="force">
</option>
<option value="mobility" data-i18n="mobility">
</option>
<option value="ranged combat" data-i18n="ranged combat">
</option>
<option value="stealth" data-i18n="stealth">
</option>
<option value="scout" data-i18n="scout">
</option>
<option value="survival" data-i18n="survival">
</option>
<option value="tech" data-i18n="tech">
</option>
<option value="leadership" data-i18n="leadership">
</option>
<option value="manipulation" data-i18n="manipulation">
</option>
<option value="medicine" data-i18n="medicine">
</option>
</select>
</label>
<label class="input-label"><span class="input-label__text" data-i18n="slots"></span>
<input class="number input-label__input" name="attr_slots" type="text" title="@{repeating_weapons_$X_slots}"/>
</label>
<label class="input-label stacked grid-span-all"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_weapons_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" title="@{repeating_weapons_$X_description}"></textarea>
</div>
</label>
</div>
</fieldset>
</div>
</section>
</div>
<section class="head-section pc-health-section">
<div class="header">
<h3 data-i18n="health"></h3>
</div>
<div class="section-content">
<label class="input-label justify-space-between"><span data-i18n="{{index.}} unharmed" data-i18n-vars="3."></span>
<input class="red-border" name="attr_health" value="3" checked="" type="radio" title="@{health}"/>
</label>
</div>
<div class="section-content">
<label class="input-label justify-space-between"><span data-i18n="{{index.}} bruised" data-i18n-vars="2."></span>
<input class="red-border" name="attr_health" value="2" type="radio" title="@{health}"/>
</label>
</div>
<div class="section-content">
<label class="input-label justify-space-between"><span data-i18n="{{index.}} battered" data-i18n-vars="1."></span>
<input class="red-border" name="attr_health" value="1" type="radio" title="@{health}"/>
</label>
</div>
<div class="section-content">
<label class="input-label justify-space-between"><span data-i18n="{{index.}} broken" data-i18n-vars="0."></span>
<input class="red-border" name="attr_health" value="0" type="radio" title="@{health}"/>
</label>
</div>
<div class="section-content injury-section">
<button class="repcontrol-button repcontrol-button--add" name="act_add-injury" type="action">
</button>
<fieldset class="repeating_injury">
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_injury_$X_collapse}"/>
<div class="collapsed flex-box justify-space-between"><span name="attr_name" title="@{repeating_injury_$X_name}"></span>
<input class="red-border number" name="attr_penalty" type="text" title="@{repeating_injury_$X_penalty}"/>
</div>
<div class="expanded">
<label class="input-label stacked name"><span class="input-label__text" data-i18n="injury"></span>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_injury_$X_name}"/>
</label>
<label class="input-label stacked penalty"><span class="input-label__text" data-i18n="penalty"></span>
<input class="number input-label__input" name="attr_penalty" type="text" title="@{repeating_injury_$X_penalty}"/>
</label>
<label class="input-label stacked limit"><span class="input-label__text" data-i18n="time limit"></span>
<input class="input-label__input" name="attr_limit" type="text" title="@{repeating_injury_$X_limit}"/>
</label>
<label class="input-label stacked recovery"><span class="input-label__text" data-i18n="recovery"></span>
<input class="input-label__input" name="attr_recovery" type="text" title="@{repeating_injury_$X_recovery}"/>
</label>
</div>
</fieldset>
<button class="critical-roller compendium-dependent disabled roller" name="roll_critical_injuries" data-i18n="Injury Table" value="@{critical_injuries_action}" type="roll">
</button>
<button name="act_critical-injuries-action" hidden="" type="action">
</button>
<input name="attr_critical_injuries_action" type="hidden" title="@{critical_injuries_action}"/>
<button class="critical-roller compendium-independent" name="roll_basic_critical_injuries" data-i18n="Injury d66" value="@{template_start} {{title=^{Critical Injury}}} {{roll=[[[[d6]][[d6]]]]}}" type="roll">
</button>
</div>
</section>
<section class="head-section pc-talent-section">
<div class="header">
<h3 data-i18n="talents"></h3>
</div>
<div class="section-content talent-section-content">
<div class="talent-display collapse-container">
<input class="collapse" name="attr_talent_session" value="1" hidden="" type="checkbox" title="@{talent_session}"/>
<label class="input-label stacked"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_talent_name" type="text" placeholder="New talent" title="@{talent_name}"/>
</label>
<input name="attr_talent_description" value="" type="hidden" title="@{talent_description}"/>
<label class="input-label stacked"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_talent_description" title="@{talent_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_talent_description" title="@{talent_description}"></textarea>
</div>
</label>
<label class="input-label justify-space-between"><span data-i18n="usable once/session"></span>
<input class="red-border" name="attr_talent_session" value="1" type="checkbox" title="@{talent_session}"/>
</label>
<div class="collapsed flex-box justify-end">
<label class="input-label justify-space-between"><span data-i18n="used"></span>
<input class="red-border" name="attr_talent_used" value="1" type="checkbox" title="@{talent_used}"/>
</label>
</div>
</div>
<input name="attr_talent_row_id" type="hidden" title="@{talent_row_id}"/>
<button class="repcontrol-button--add repcontrol-button" name="act_add-talent" type="action">
</button>
<fieldset class="repeating_talents">
<input class="conditional-red-control" name="attr_is_selected" value="1" hidden="" type="checkbox" title="@{repeating_talents_$X_is_selected}"/>
<button class="conditional-red-box embossed" name="act_display" type="action"><span name="attr_name" title="@{repeating_talents_$X_name}"></span>
</button>
<input name="attr_session" type="hidden" title="@{repeating_talents_$X_session}"/>
<input name="attr_description" type="hidden" title="@{repeating_talents_$X_description}"/>
<input name="attr_used" type="hidden" title="@{repeating_talents_$X_used}"/>
</fieldset>
</div>
</section>
<section class="head-section pc-gear-section">
<div class="header grid-span-all">
<h3 data-i18n="gear"></h3>
</div>
<div class="section-content pc-gear-content">
<div class="flex-box tiny-gap justify-end encumbrance-container grid-span-all"><span data-i18n="encumbrance slots"></span>
<input class="red-border" name="attr_encumbrance" readonly="" type="number" title="@{encumbrance}"/><span class="slash">/</span>
<input class="red-border" name="attr_encumbrance_max" readonly="" value="2" type="number" title="@{encumbrance|max}"/>
</div>
</div>
<div class="section-content pc-gear-content">
<div class="equip-repeat">
<div class="header grid-span-all pc-gear-header column-subgrid">
<h4 data-i18n="equipped"></h4>
<h5 data-i18n="bonus"></h5>
</div>
<button class="repcontrol-button repcontrol-button--add" name="act_add-gear" type="action">
</button>
<fieldset class="repeating_gear">
<input class="equip-checkbox" name="attr_equipped" value="1" checked="" type="checkbox" title="@{repeating_gear_$X_equipped}"/>
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_gear_$X_collapse}"/>
<div class="no-gap collapsed column-subgrid grid-span-all gear-display border-back">
<div class="flex-box tiny-gap justify-center"><span class="qty-span" name="attr_quantity" title="@{repeating_gear_$X_quantity}"></span><span class="slots" name="attr_slots" title="@{repeating_gear_$X_slots}"></span>
</div><span class="gear-name-span" name="attr_name" title="@{repeating_gear_$X_name}"></span>
<input class="bonus" name="attr_bonus" readonly="" type="number" title="@{repeating_gear_$X_bonus}"/>
</div>
<div class="expanded grid-span-all gear-display border-back">
<label class="input-label stacked name-input grid-span-all"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_gear_$X_name}"/>
</label>
<label class="input-label stacked"><span class="input-label__text" data-i18n="quantity abbreviation"></span>
<input class="input-label__input" name="attr_quantity" type="number" title="@{repeating_gear_$X_quantity}"/>
</label>
<label class="input-label stacked gear-slots"><span class="input-label__text" data-i18n="slots"></span>
<input class="number input-label__input" name="attr_slots" type="text" title="@{repeating_gear_$X_slots}"/>
</label>
<label class="input-label stacked bonus-input"><span class="input-label__text" data-i18n="bonus"></span>
<input class="input-label__input" name="attr_bonus" type="number" title="@{repeating_gear_$X_bonus}"/>
</label>
<label class="input-label stacked grid-span-all"><span class="input-label__text" data-i18n="affects"></span>
<select class="input-label__input" name="attr_affects" title="@{repeating_gear_$X_affects}">
<option value="" data-i18n="select one">
</option>
<option value="close combat" data-i18n="close combat">
</option>
<option value="endure" data-i18n="endure">
</option>
<option value="force" data-i18n="force">
</option>
<option value="mobility" data-i18n="mobility">
</option>
<option value="ranged combat" data-i18n="ranged combat">
</option>
<option value="stealth" data-i18n="stealth">
</option>
<option value="scout" data-i18n="scout">
</option>
<option value="survival" data-i18n="survival">
</option>
<option value="tech" data-i18n="tech">
</option>
<option value="leadership" data-i18n="leadership">
</option>
<option value="manipulation" data-i18n="manipulation">
</option>
<option value="medicine" data-i18n="medicine">
</option>
</select>
</label>
<label class="input-label stacked grid-span-all"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_gear_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" title="@{repeating_gear_$X_description}"></textarea>
</div>
</label>
</div>
<input name="attr_location" type="hidden" title="@{repeating_gear_$X_location}"/>
</fieldset>
</div>
<div class="equip-repeat stored-repeat">
<div class="header grid-span-all pc-gear-header column-subgrid">
<h4 data-i18n="stored"></h4>
<h5 data-i18n="location"></h5>
</div>
<button class="repcontrol-button repcontrol-button--add" name="act_add-stored-gear" type="action">
</button>
<fieldset class="repeating_stored-gear">
<input class="equip-checkbox" name="attr_equipped" value="1" type="checkbox" title="@{repeating_stored-gear_$X_equipped}"/>
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_stored-gear_$X_collapse}"/>
<div class="no-gap collapsed column-subgrid grid-span-all gear-display border-back">
<div class="flex-box tiny-gap justify-center"><span class="qty-span" name="attr_quantity" title="@{repeating_stored-gear_$X_quantity}"></span><span class="slots" name="attr_slots" title="@{repeating_stored-gear_$X_slots}"></span>
</div><span class="gear-name-span" name="attr_name" title="@{repeating_stored-gear_$X_name}"></span><span name="attr_location" readonly="" title="@{repeating_stored-gear_$X_location}"></span>
<input class="bonus" name="attr_bonus" readonly="" type="number" title="@{repeating_stored-gear_$X_bonus}"/>
</div>
<div class="expanded grid-span-all gear-display border-back">
<label class="input-label stacked name-input grid-span-all"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_stored-gear_$X_name}"/>
</label>
<label class="input-label stacked"><span class="input-label__text" data-i18n="quantity abbreviation"></span>
<input class="input-label__input" name="attr_quantity" type="number" title="@{repeating_stored-gear_$X_quantity}"/>
</label>
<label class="input-label stacked gear-slots"><span class="input-label__text" data-i18n="slots"></span>
<input class="number input-label__input" name="attr_slots" type="text" title="@{repeating_stored-gear_$X_slots}"/>
</label>
<label class="input-label stacked bonus-input"><span class="input-label__text" data-i18n="bonus"></span>
<input class="input-label__input" name="attr_bonus" type="number" title="@{repeating_stored-gear_$X_bonus}"/>
</label>
<label class="input-label stacked location-input"><span class="input-label__text" data-i18n="location"></span>
<input class="input-label__input" name="attr_location" type="text" title="@{repeating_stored-gear_$X_location}"/>
</label>
<label class="input-label stacked grid-span-all"><span class="input-label__text" data-i18n="affects"></span>
<select class="input-label__input" name="attr_affects" title="@{repeating_stored-gear_$X_affects}">
<option value="" data-i18n="select one">
</option>
<option value="close combat" data-i18n="close combat">
</option>
<option value="endure" data-i18n="endure">
</option>
<option value="force" data-i18n="force">
</option>
<option value="mobility" data-i18n="mobility">
</option>
<option value="ranged combat" data-i18n="ranged combat">
</option>
<option value="stealth" data-i18n="stealth">
</option>
<option value="scout" data-i18n="scout">
</option>
<option value="survival" data-i18n="survival">
</option>
<option value="tech" data-i18n="tech">
</option>
<option value="leadership" data-i18n="leadership">
</option>
<option value="manipulation" data-i18n="manipulation">
</option>
<option value="medicine" data-i18n="medicine">
</option>
</select>
</label>
<label class="input-label stacked grid-span-all"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_stored-gear_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" title="@{repeating_stored-gear_$X_description}"></textarea>
</div>
</label>
</div>
</fieldset>
</div>
</div>
</section>
</article>
<article class="tabs__container tabs--walking-dead__container tabs--walking-dead__container--npc npc-page collapse-container border-back-container" data-container-tab="walking-dead" data-tab="npc">
<input class="collapse" name="attr_npc_collapse" value="1" type="checkbox" title="@{npc_collapse}"/>
<div class="expanded">
<div class="statblock-row flex-box half-gap">
<input class="underlined" name="attr_character_name" type="text" title="@{character_name}"/>
<input class="underlined" name="attr_npc_descriptor" data-i18n-placeholder="descriptor" type="text" title="@{npc_descriptor}"/>
</div>
<div class="statblock-row flex-box half-gap">
<input class="underlined" name="attr_npc_faction" data-i18n-placeholder="faction" type="text" title="@{npc_faction}"/>
<input class="underlined" name="attr_npc_haven" data-i18n-placeholder="haven" type="text" title="@{npc_haven}"/>
</div>
<div class="flex-box flex-wrap npc-skill-container">
<button class="bold capitalize roller" name="roll_npc_untrained_skills" data-i18n="skills" style="background: white; width: 100%" value="@{npc_untrained_skills_action}" type="roll">
</button>
<button name="act_npc-untrained-skills-action" hidden="" type="action">
</button>
<input name="attr_npc_untrained_skills_action" type="hidden" title="@{npc_untrained_skills_action}"/>
<div class="npc-skill-edit">
<div class="input-label justify-end">
<button class="roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{close_combat_action}"/>
<select class="red-border" name="attr_close_combat" title="@{close_combat}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{endure_action}"/>
<select class="red-border" name="attr_endure" title="@{endure}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{force_action}"/>
<select class="red-border" name="attr_force" title="@{force}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{mobility_action}"/>
<select class="red-border" name="attr_mobility" title="@{mobility}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{ranged_combat_action}"/>
<select class="red-border" name="attr_ranged_combat" title="@{ranged_combat}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{stealth_action}"/>
<select class="red-border" name="attr_stealth" title="@{stealth}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{scout_action}"/>
<select class="red-border" name="attr_scout" title="@{scout}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{survival_action}"/>
<select class="red-border" name="attr_survival" title="@{survival}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{tech_action}"/>
<select class="red-border" name="attr_tech" title="@{tech}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{leadership_action}"/>
<select class="red-border" name="attr_leadership" title="@{leadership}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{manipulation_action}"/>
<select class="red-border" name="attr_manipulation" title="@{manipulation}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{medicine_action}"/>
<select class="red-border" name="attr_medicine" title="@{medicine}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
</div>
</div>
<div class="statblock-section npc-gear inline-fieldset-container">
<h4 data-i18n="gear"></h4>
<button class="repcontrol-button repcontrol-button--add" name="act_add-gear" type="action">
</button>
<fieldset class="repeating_gear">
<input class="gear-name" name="attr_name" value="New gear" type="text" title="@{repeating_gear_$X_name}"/>
</fieldset>
</div>
<div class="statblock-section npc-weapon-section inline-fieldset-container">
<h4 data-i18n="weapon"></h4>
<button class="repcontrol-button repcontrol-button--add" name="act_add-weapons" type="action">
</button>
<fieldset class="repeating_weapons">
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_weapons_$X_collapse}"/>
<div class="cardExpanded expanded">
</div>
<button class="collapsed embossed roller" name="roll_roll" value="@{action}" type="roll"><span name="attr_name" title="@{repeating_weapons_$X_name}"></span>
</button>
<button name="act_action" hidden="" type="action">
</button>
<input name="attr_action" type="hidden" title="@{repeating_weapons_$X_action}"/>
<div class="input-label input-label--button expanded">
<button class="icon-roller roller" name="roll_roll" value="@{action}" type="roll">
</button>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_weapons_$X_name}"/>
</div>
<button name="act_action" hidden="" type="action">
</button>
<input name="attr_action" type="hidden" title="@{repeating_weapons_$X_action}"/>
<input class="red-border expanded summary-details" name="attr_damage" type="number" data-i18n-placeholder="damage" title="@{repeating_weapons_$X_damage}"/>
<input class="red-border expanded summary-details" name="attr_bonus" type="number" data-i18n-placeholder="bonus" title="@{repeating_weapons_$X_bonus}"/>
<input class="red-border expanded summary-details" name="attr_range" type="text" data-i18n-placeholder="range" title="@{repeating_weapons_$X_range}"/>
<div class="expanded grid-span-all weapon-details">
<label class="input-label" style="justify-self: end;"><span class="input-label__text" data-i18n="skill"></span>
<select class="input-label__input" name="attr_skill" title="@{repeating_weapons_$X_skill}">
<option value="close combat" data-i18n="close combat" selected="">
</option>
<option value="endure" data-i18n="endure">
</option>
<option value="force" data-i18n="force">
</option>
<option value="mobility" data-i18n="mobility">
</option>
<option value="ranged combat" data-i18n="ranged combat">
</option>
<option value="stealth" data-i18n="stealth">
</option>
<option value="scout" data-i18n="scout">
</option>
<option value="survival" data-i18n="survival">
</option>
<option value="tech" data-i18n="tech">
</option>
<option value="leadership" data-i18n="leadership">
</option>
<option value="manipulation" data-i18n="manipulation">
</option>
<option value="medicine" data-i18n="medicine">
</option>
</select>
</label>
<label class="input-label stacked grid-span-all"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_weapons_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" title="@{repeating_weapons_$X_description}"></textarea>
</div>
</label>
</div>
</fieldset>
</div>
<div class="npcDescriptionEdit">
<label class="input-label stacked"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_character_description" title="@{character_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_character_description" title="@{character_description}"></textarea>
</div>
</label>
<label class="input-label stacked"><span data-i18n="issues"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_character_issues" title="@{character_issues}"></span>
<textarea class="adaptive--text__textarea" name="attr_character_issues" title="@{character_issues}"></textarea>
</div>
</label>
</div>
</div>
<div class="collapsed">
<div class="flex-box flex-wrap inline-npc-view">
<div class="statblock-row flex-box half-gap" style="align-items:end">
<h3><span name="attr_character_name" title="@{character_name}"></span>
</h3>
<h4><span name="attr_npc_descriptor" title="@{npc_descriptor}"></span>
</h4>
</div>
<div class="flex-box flex-wrap npc-skill-row">
<button class="flex-box controlled-display roller" name="roll_npc_untrained_skills" value="@{npc_untrained_skills_action}" type="roll"><span class="capitalize bold" data-i18n="skills"></span>
<input class="display-control" name="attr_npc_is_untrained" value="1" hidden="" checked="" readonly="" type="checkbox" title="@{npc_is_untrained}"/><span class="controlled-display" data-i18n="untrained"></span>
</button>
<button name="act_npc-untrained-skills-action" hidden="" type="action">
</button>
<input name="attr_npc_untrained_skills_action" type="hidden" title="@{npc_untrained_skills_action}"/>
<input class="display-control" name="attr_npc_is_trained" value="1" hidden="" readonly="" type="checkbox" title="@{npc_is_trained}"/>
<div class="trained-display controlled-display npc-skill-display flex-box half-gap"><span class="bold capitalize" data-i18n="trained"></span>
<div class="flex-box tiny-gap-x flex-wrap">
<input class="display-control" name="attr_close_combat" value="5" hidden="" type="checkbox" title="@{close_combat}"/>
<button class="controlled-display roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{close_combat_action}"/>
<input class="display-control" name="attr_endure" value="5" hidden="" type="checkbox" title="@{endure}"/>
<button class="controlled-display roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{endure_action}"/>
<input class="display-control" name="attr_force" value="5" hidden="" type="checkbox" title="@{force}"/>
<button class="controlled-display roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{force_action}"/>
<input class="display-control" name="attr_mobility" value="5" hidden="" type="checkbox" title="@{mobility}"/>
<button class="controlled-display roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{mobility_action}"/>
<input class="display-control" name="attr_ranged_combat" value="5" hidden="" type="checkbox" title="@{ranged_combat}"/>
<button class="controlled-display roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{ranged_combat_action}"/>
<input class="display-control" name="attr_stealth" value="5" hidden="" type="checkbox" title="@{stealth}"/>
<button class="controlled-display roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{stealth_action}"/>
<input class="display-control" name="attr_scout" value="5" hidden="" type="checkbox" title="@{scout}"/>
<button class="controlled-display roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{scout_action}"/>
<input class="display-control" name="attr_survival" value="5" hidden="" type="checkbox" title="@{survival}"/>
<button class="controlled-display roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{survival_action}"/>
<input class="display-control" name="attr_tech" value="5" hidden="" type="checkbox" title="@{tech}"/>
<button class="controlled-display roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{tech_action}"/>
<input class="display-control" name="attr_leadership" value="5" hidden="" type="checkbox" title="@{leadership}"/>
<button class="controlled-display roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{leadership_action}"/>
<input class="display-control" name="attr_manipulation" value="5" hidden="" type="checkbox" title="@{manipulation}"/>
<button class="controlled-display roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{manipulation_action}"/>
<input class="display-control" name="attr_medicine" value="5" hidden="" type="checkbox" title="@{medicine}"/>
<button class="controlled-display roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{medicine_action}"/>
</div>
</div>
<input class="display-control" name="attr_npc_is_expert" value="1" hidden="" readonly="" type="checkbox" title="@{npc_is_expert}"/>
<div class="expert-display controlled-display npc-skill-display flex-box half-gap"><span class="bold capitalize" data-i18n="expert"></span>
<div class="flex-box tiny-gap-x flex-wrap">
<input class="display-control" name="attr_close_combat" value="8" hidden="" type="checkbox" title="@{close_combat}"/>
<button class="controlled-display roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{close_combat_action}"/>
<input class="display-control" name="attr_endure" value="8" hidden="" type="checkbox" title="@{endure}"/>
<button class="controlled-display roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{endure_action}"/>
<input class="display-control" name="attr_force" value="8" hidden="" type="checkbox" title="@{force}"/>
<button class="controlled-display roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{force_action}"/>
<input class="display-control" name="attr_mobility" value="8" hidden="" type="checkbox" title="@{mobility}"/>
<button class="controlled-display roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{mobility_action}"/>
<input class="display-control" name="attr_ranged_combat" value="8" hidden="" type="checkbox" title="@{ranged_combat}"/>
<button class="controlled-display roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{ranged_combat_action}"/>
<input class="display-control" name="attr_stealth" value="8" hidden="" type="checkbox" title="@{stealth}"/>
<button class="controlled-display roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{stealth_action}"/>
<input class="display-control" name="attr_scout" value="8" hidden="" type="checkbox" title="@{scout}"/>
<button class="controlled-display roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{scout_action}"/>
<input class="display-control" name="attr_survival" value="8" hidden="" type="checkbox" title="@{survival}"/>
<button class="controlled-display roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{survival_action}"/>
<input class="display-control" name="attr_tech" value="8" hidden="" type="checkbox" title="@{tech}"/>
<button class="controlled-display roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{tech_action}"/>
<input class="display-control" name="attr_leadership" value="8" hidden="" type="checkbox" title="@{leadership}"/>
<button class="controlled-display roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{leadership_action}"/>
<input class="display-control" name="attr_manipulation" value="8" hidden="" type="checkbox" title="@{manipulation}"/>
<button class="controlled-display roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{manipulation_action}"/>
<input class="display-control" name="attr_medicine" value="8" hidden="" type="checkbox" title="@{medicine}"/>
<button class="controlled-display roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{medicine_action}"/>
</div>
</div>
<input class="display-control" name="attr_npc_is_master" value="1" hidden="" readonly="" type="checkbox" title="@{npc_is_master}"/>
<div class="master-display controlled-display npc-skill-display flex-box half-gap"><span class="bold capitalize" data-i18n="master"></span>
<div class="flex-box tiny-gap-x flex-wrap">
<input class="display-control" name="attr_close_combat" value="10" hidden="" type="checkbox" title="@{close_combat}"/>
<button class="controlled-display roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{close_combat_action}"/>
<input class="display-control" name="attr_endure" value="10" hidden="" type="checkbox" title="@{endure}"/>
<button class="controlled-display roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{endure_action}"/>
<input class="display-control" name="attr_force" value="10" hidden="" type="checkbox" title="@{force}"/>
<button class="controlled-display roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{force_action}"/>
<input class="display-control" name="attr_mobility" value="10" hidden="" type="checkbox" title="@{mobility}"/>
<button class="controlled-display roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{mobility_action}"/>
<input class="display-control" name="attr_ranged_combat" value="10" hidden="" type="checkbox" title="@{ranged_combat}"/>
<button class="controlled-display roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{ranged_combat_action}"/>
<input class="display-control" name="attr_stealth" value="10" hidden="" type="checkbox" title="@{stealth}"/>
<button class="controlled-display roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{stealth_action}"/>
<input class="display-control" name="attr_scout" value="10" hidden="" type="checkbox" title="@{scout}"/>
<button class="controlled-display roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{scout_action}"/>
<input class="display-control" name="attr_survival" value="10" hidden="" type="checkbox" title="@{survival}"/>
<button class="controlled-display roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{survival_action}"/>
<input class="display-control" name="attr_tech" value="10" hidden="" type="checkbox" title="@{tech}"/>
<button class="controlled-display roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{tech_action}"/>
<input class="display-control" name="attr_leadership" value="10" hidden="" type="checkbox" title="@{leadership}"/>
<button class="controlled-display roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{leadership_action}"/>
<input class="display-control" name="attr_manipulation" value="10" hidden="" type="checkbox" title="@{manipulation}"/>
<button class="controlled-display roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{manipulation_action}"/>
<input class="display-control" name="attr_medicine" value="10" hidden="" type="checkbox" title="@{medicine}"/>
<button class="controlled-display roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{medicine_action}"/>
</div>
</div>
</div>
<div class="statblock-section npc-gear inline-fieldset-container view-only">
<h4 data-i18n="gear"></h4>
<button class="repcontrol-button repcontrol-button--add" name="act_add-gear" type="action">
</button>
<fieldset class="repeating_gear"><span name="attr_name"></span>
</fieldset>
</div>
<div class="statblock-section npc-weapon-section inline-fieldset-container view-only">
<h4 data-i18n="weapon"></h4>
<button class="repcontrol-button repcontrol-button--add" name="act_add-weapons" type="action">
</button>
<fieldset class="repeating_weapons">
<div class="cardExpanded"></div>
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_weapons_$X_collapse}"/>
<div class="cardExpanded expanded">
</div>
<button class="collapsed embossed roller" name="roll_roll" value="@{action}" type="roll"><span name="attr_name" title="@{repeating_weapons_$X_name}"></span>
</button>
<button name="act_action" hidden="" type="action">
</button>
<input name="attr_action" type="hidden" title="@{repeating_weapons_$X_action}"/>
<div class="input-label input-label--button expanded">
<button class="icon-roller roller" name="roll_roll" value="@{action}" type="roll">
</button>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_weapons_$X_name}"/>
</div>
<button name="act_action" hidden="" type="action">
</button>
<input name="attr_action" type="hidden" title="@{repeating_weapons_$X_action}"/>
<input class="red-border expanded summary-details" name="attr_damage" type="number" data-i18n-placeholder="damage" title="@{repeating_weapons_$X_damage}"/>
<input class="red-border expanded summary-details" name="attr_bonus" type="number" data-i18n-placeholder="bonus" title="@{repeating_weapons_$X_bonus}"/>
<input class="red-border expanded summary-details" name="attr_range" type="text" data-i18n-placeholder="range" title="@{repeating_weapons_$X_range}"/>
<div class="expanded grid-span-all weapon-details">
<label class="input-label" style="justify-self: end;"><span class="input-label__text" data-i18n="skill"></span>
<select class="input-label__input" name="attr_skill" title="@{repeating_weapons_$X_skill}">
<option value="close combat" data-i18n="close combat" selected="">
</option>
<option value="endure" data-i18n="endure">
</option>
<option value="force" data-i18n="force">
</option>
<option value="mobility" data-i18n="mobility">
</option>
<option value="ranged combat" data-i18n="ranged combat">
</option>
<option value="stealth" data-i18n="stealth">
</option>
<option value="scout" data-i18n="scout">
</option>
<option value="survival" data-i18n="survival">
</option>
<option value="tech" data-i18n="tech">
</option>
<option value="leadership" data-i18n="leadership">
</option>
<option value="manipulation" data-i18n="manipulation">
</option>
<option value="medicine" data-i18n="medicine">
</option>
</select>
</label>
<label class="input-label stacked grid-span-all"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_weapons_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" title="@{repeating_weapons_$X_description}"></textarea>
</div>
</label>
</div>
</fieldset>
</div>
</div>
<div class="npcDescriptionView">
<h4 data-i18n="description:"></h4><span name="attr_character_description" title="@{character_description}"></span>
<h4 data-i18n="issues:"></h4><span name="attr_character_issues" title="@{character_issues}"></span>
</div>
</div>
</article>
<article class="tabs__container tabs--walking-dead__container tabs--walking-dead__container--challenge challenge-page" data-container-tab="walking-dead" data-tab="challenge">
<section class="head-section issue-section">
<div class="header issue-header grid-span-all column-subgrid">
<h3 data-i18n="issues"></h3>
<h4 data-i18n="source"></h4>
</div>
<div class="section-content issue-content grid-span-all column-subgrid">
<button class="repcontrol-button repcontrol-button--add" name="act_add-issues" type="action">
</button>
<fieldset class="repeating_issues">
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_issues_$X_collapse}"/><span class="collapsed" name="attr_name" title="@{repeating_issues_$X_name}"></span>
<label class="input-label stacked expanded"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_issues_$X_name}"/>
</label><span class="collapsed source" name="attr_source" title="@{repeating_issues_$X_source}"></span>
<label class="input-label stacked expanded source"><span class="input-label__text" data-i18n="source"></span>
<input class="input-label__input" name="attr_source" type="text" title="@{repeating_issues_$X_source}"/>
</label>
<label class="input-label stacked grid-span-all expanded"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_issues_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" type="text" title="@{repeating_issues_$X_description}"></textarea>
</div>
</label>
</fieldset>
</div>
</section>
<section class="head-section npc-section"><img class="logo grid-span-all" src="https://files.d20.io/images/368479329/HgW2WAq5CUmayPMeTQow3A/original.png"/>
<div class="header npc-header grid-span-all column-subgrid">
<h3 data-i18n="npcs"></h3>
<h4 data-i18n="fate"></h4>
</div>
<div class="section-content npc-content grid-span-all column-subgrid">
<button class="repcontrol-button repcontrol-button--add" name="act_add-npcs" type="action">
</button>
<fieldset class="repeating_npcs">
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_npcs_$X_collapse}"/>
<div class="collapsed">
<div class="flex-box half-gap"><span class="bold" name="attr_name" title="@{repeating_npcs_$X_name}"></span><span name="attr_descriptor" title="@{repeating_npcs_$X_descriptor}"></span>
</div>
<div class="flex-box flex-wrap npc-skill-row">
<button class="flex-box controlled-display roller" name="roll_npc_untrained_skills" value="@{npc_untrained_skills_action}" type="roll"><span class="capitalize bold" data-i18n="skills"></span>
<input class="display-control" name="attr_npc_is_untrained" value="1" hidden="" checked="" readonly="" type="checkbox" title="@{repeating_npcs_$X_npc_is_untrained}"/><span class="controlled-display" data-i18n="untrained"></span>
</button>
<button name="act_npc-untrained-skills-action" hidden="" type="action">
</button>
<input name="attr_npc_untrained_skills_action" type="hidden" title="@{repeating_npcs_$X_npc_untrained_skills_action}"/>
<input class="display-control" name="attr_npc_is_trained" value="1" hidden="" readonly="" type="checkbox" title="@{repeating_npcs_$X_npc_is_trained}"/>
<div class="trained-display controlled-display npc-skill-display flex-box half-gap"><span class="bold capitalize" data-i18n="trained"></span>
<div class="flex-box tiny-gap-x flex-wrap">
<input class="display-control" name="attr_close_combat" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_close_combat}"/>
<button class="controlled-display roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{repeating_npcs_$X_close_combat_action}"/>
<input class="display-control" name="attr_endure" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_endure}"/>
<button class="controlled-display roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{repeating_npcs_$X_endure_action}"/>
<input class="display-control" name="attr_force" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_force}"/>
<button class="controlled-display roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{repeating_npcs_$X_force_action}"/>
<input class="display-control" name="attr_mobility" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_mobility}"/>
<button class="controlled-display roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{repeating_npcs_$X_mobility_action}"/>
<input class="display-control" name="attr_ranged_combat" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_ranged_combat}"/>
<button class="controlled-display roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{repeating_npcs_$X_ranged_combat_action}"/>
<input class="display-control" name="attr_stealth" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_stealth}"/>
<button class="controlled-display roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{repeating_npcs_$X_stealth_action}"/>
<input class="display-control" name="attr_scout" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_scout}"/>
<button class="controlled-display roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{repeating_npcs_$X_scout_action}"/>
<input class="display-control" name="attr_survival" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_survival}"/>
<button class="controlled-display roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{repeating_npcs_$X_survival_action}"/>
<input class="display-control" name="attr_tech" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_tech}"/>
<button class="controlled-display roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{repeating_npcs_$X_tech_action}"/>
<input class="display-control" name="attr_leadership" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_leadership}"/>
<button class="controlled-display roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{repeating_npcs_$X_leadership_action}"/>
<input class="display-control" name="attr_manipulation" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_manipulation}"/>
<button class="controlled-display roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{repeating_npcs_$X_manipulation_action}"/>
<input class="display-control" name="attr_medicine" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_medicine}"/>
<button class="controlled-display roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{repeating_npcs_$X_medicine_action}"/>
</div>
</div>
<input class="display-control" name="attr_npc_is_expert" value="1" hidden="" readonly="" type="checkbox" title="@{repeating_npcs_$X_npc_is_expert}"/>
<div class="expert-display controlled-display npc-skill-display flex-box half-gap"><span class="bold capitalize" data-i18n="expert"></span>
<div class="flex-box tiny-gap-x flex-wrap">
<input class="display-control" name="attr_close_combat" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_close_combat}"/>
<button class="controlled-display roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{repeating_npcs_$X_close_combat_action}"/>
<input class="display-control" name="attr_endure" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_endure}"/>
<button class="controlled-display roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{repeating_npcs_$X_endure_action}"/>
<input class="display-control" name="attr_force" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_force}"/>
<button class="controlled-display roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{repeating_npcs_$X_force_action}"/>
<input class="display-control" name="attr_mobility" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_mobility}"/>
<button class="controlled-display roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{repeating_npcs_$X_mobility_action}"/>
<input class="display-control" name="attr_ranged_combat" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_ranged_combat}"/>
<button class="controlled-display roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{repeating_npcs_$X_ranged_combat_action}"/>
<input class="display-control" name="attr_stealth" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_stealth}"/>
<button class="controlled-display roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{repeating_npcs_$X_stealth_action}"/>
<input class="display-control" name="attr_scout" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_scout}"/>
<button class="controlled-display roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{repeating_npcs_$X_scout_action}"/>
<input class="display-control" name="attr_survival" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_survival}"/>
<button class="controlled-display roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{repeating_npcs_$X_survival_action}"/>
<input class="display-control" name="attr_tech" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_tech}"/>
<button class="controlled-display roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{repeating_npcs_$X_tech_action}"/>
<input class="display-control" name="attr_leadership" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_leadership}"/>
<button class="controlled-display roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{repeating_npcs_$X_leadership_action}"/>
<input class="display-control" name="attr_manipulation" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_manipulation}"/>
<button class="controlled-display roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{repeating_npcs_$X_manipulation_action}"/>
<input class="display-control" name="attr_medicine" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_medicine}"/>
<button class="controlled-display roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{repeating_npcs_$X_medicine_action}"/>
</div>
</div>
<input class="display-control" name="attr_npc_is_master" value="1" hidden="" readonly="" type="checkbox" title="@{repeating_npcs_$X_npc_is_master}"/>
<div class="master-display controlled-display npc-skill-display flex-box half-gap"><span class="bold capitalize" data-i18n="master"></span>
<div class="flex-box tiny-gap-x flex-wrap">
<input class="display-control" name="attr_close_combat" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_close_combat}"/>
<button class="controlled-display roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{repeating_npcs_$X_close_combat_action}"/>
<input class="display-control" name="attr_endure" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_endure}"/>
<button class="controlled-display roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{repeating_npcs_$X_endure_action}"/>
<input class="display-control" name="attr_force" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_force}"/>
<button class="controlled-display roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{repeating_npcs_$X_force_action}"/>
<input class="display-control" name="attr_mobility" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_mobility}"/>
<button class="controlled-display roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{repeating_npcs_$X_mobility_action}"/>
<input class="display-control" name="attr_ranged_combat" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_ranged_combat}"/>
<button class="controlled-display roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{repeating_npcs_$X_ranged_combat_action}"/>
<input class="display-control" name="attr_stealth" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_stealth}"/>
<button class="controlled-display roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{repeating_npcs_$X_stealth_action}"/>
<input class="display-control" name="attr_scout" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_scout}"/>
<button class="controlled-display roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{repeating_npcs_$X_scout_action}"/>
<input class="display-control" name="attr_survival" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_survival}"/>
<button class="controlled-display roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{repeating_npcs_$X_survival_action}"/>
<input class="display-control" name="attr_tech" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_tech}"/>
<button class="controlled-display roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{repeating_npcs_$X_tech_action}"/>
<input class="display-control" name="attr_leadership" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_leadership}"/>
<button class="controlled-display roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{repeating_npcs_$X_leadership_action}"/>
<input class="display-control" name="attr_manipulation" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_manipulation}"/>
<button class="controlled-display roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{repeating_npcs_$X_manipulation_action}"/>
<input class="display-control" name="attr_medicine" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_medicine}"/>
<button class="controlled-display roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{repeating_npcs_$X_medicine_action}"/>
</div>
</div>
</div>
<input class="display-control--non-zero" name="attr_gear" value="" type="hidden" title="@{repeating_npcs_$X_gear}"/>
<div class="flex-box controlled-display"><span class="capitalize bold" data-i18n="gear"></span><span name="attr_gear" title="@{repeating_npcs_$X_gear}"></span>
</div>
<input class="display-control--non-zero" name="attr_weapons" value="" type="hidden" title="@{repeating_npcs_$X_weapons}"/>
<button class="flex-box controlled-display roller" name="roll_weapons" value="@{weapons_action}" type="roll"><span class="capitalize bold" data-i18n="weapons"></span><span name="attr_weapons" title="@{repeating_npcs_$X_weapons}"></span>
</button>
<button name="act_weapons-action" hidden="" type="action">
</button>
<input name="attr_weapons_action" type="hidden" title="@{repeating_npcs_$X_weapons_action}"/>
</div>
<div class="expanded border-back-interior">
<label class="input-label stacked"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_npcs_$X_name}"/>
</label>
<label class="input-label stacked"><span class="input-label__text" data-i18n="descriptor"></span>
<input class="input-label__input" name="attr_descriptor" type="text" title="@{repeating_npcs_$X_descriptor}"/>
</label>
<div class="flex-box flex-wrap npc-skill-container">
<button class="bold capitalize roller" name="roll_npc_untrained_skills" data-i18n="skills" style="background: white; width: 100%" value="@{npc_untrained_skills_action}" type="roll">
</button>
<button name="act_npc-untrained-skills-action" hidden="" type="action">
</button>
<input name="attr_npc_untrained_skills_action" type="hidden" title="@{repeating_npcs_$X_npc_untrained_skills_action}"/>
<div class="npc-skill-edit">
<div class="input-label justify-end">
<button class="roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{repeating_npcs_$X_close_combat_action}"/>
<select class="red-border" name="attr_close_combat" title="@{repeating_npcs_$X_close_combat}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{repeating_npcs_$X_endure_action}"/>
<select class="red-border" name="attr_endure" title="@{repeating_npcs_$X_endure}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{repeating_npcs_$X_force_action}"/>
<select class="red-border" name="attr_force" title="@{repeating_npcs_$X_force}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{repeating_npcs_$X_mobility_action}"/>
<select class="red-border" name="attr_mobility" title="@{repeating_npcs_$X_mobility}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{repeating_npcs_$X_ranged_combat_action}"/>
<select class="red-border" name="attr_ranged_combat" title="@{repeating_npcs_$X_ranged_combat}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{repeating_npcs_$X_stealth_action}"/>
<select class="red-border" name="attr_stealth" title="@{repeating_npcs_$X_stealth}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{repeating_npcs_$X_scout_action}"/>
<select class="red-border" name="attr_scout" title="@{repeating_npcs_$X_scout}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{repeating_npcs_$X_survival_action}"/>
<select class="red-border" name="attr_survival" title="@{repeating_npcs_$X_survival}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{repeating_npcs_$X_tech_action}"/>
<select class="red-border" name="attr_tech" title="@{repeating_npcs_$X_tech}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{repeating_npcs_$X_leadership_action}"/>
<select class="red-border" name="attr_leadership" title="@{repeating_npcs_$X_leadership}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{repeating_npcs_$X_manipulation_action}"/>
<select class="red-border" name="attr_manipulation" title="@{repeating_npcs_$X_manipulation}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{repeating_npcs_$X_medicine_action}"/>
<select class="red-border" name="attr_medicine" title="@{repeating_npcs_$X_medicine}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
</div>
</div>
<input class="display-control--zero" name="attr_character_id" value="" type="hidden" title="@{repeating_npcs_$X_character_id}"/>
<label class="input-label stacked controlled-display"><span class="input-label__text" data-i18n="gear"></span>
<input class="input-label__input" name="attr_gear" type="text" title="@{repeating_npcs_$X_gear}"/>
</label>
<input class="display-control--zero" name="attr_character_id" value="" type="hidden" title="@{repeating_npcs_$X_character_id}"/>
<div class="input-label input-label--button stacked controlled-display">
<button class="roller" name="roll_weapons" data-i18n="weapons" value="@{weapons_action}" type="roll">
</button>
<input class="input-label__input" name="attr_weapons" type="text" title="@{repeating_npcs_$X_weapons}"/>
</div>
<button name="act_weapons-action" hidden="" type="action">
</button>
<input name="attr_weapons_action" type="hidden" title="@{repeating_npcs_$X_weapons_action}"/>
<label class="input-label stacked grid-span-all"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_npcs_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" type="text" title="@{repeating_npcs_$X_description}"></textarea>
</div>
</label>
</div>
</fieldset>
</div>
</section>
<section class="head-section rumors-section">
<div class="header rumors-header column-subgrid grid-span-all">
<h3 data-i18n="rumors"></h3>
<h4 data-i18n="clock"></h4>
</div>
<div class="section-content column-subgrid grid-span-all rumors-content">
<button class="repcontrol-button repcontrol-button--add" name="act_add-rumors" type="action">
</button>
<fieldset class="repeating_rumors">
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_rumors_$X_collapse}"/><span class="collapsed" name="attr_name" title="@{repeating_rumors_$X_name}"></span>
<label class="input-label stacked expanded"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_rumors_$X_name}"/>
</label>
<div class="clock-container">
<div class="clock" style="--_clockSize: 30px;--_sectionBase: 17.32041615186541px;--_sections: 6;">
<input class="clock__control" name="attr_clock" value="1" hidden="" type="checkbox" title="@{repeating_rumors_$X_clock}"/>
<div class="clock__segment" style="--_rotation:30deg">
<input name="attr_clock" value="1" hidden="" type="checkbox" title="@{repeating_rumors_$X_clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="2" hidden="" type="checkbox" title="@{repeating_rumors_$X_clock}"/>
<div class="clock__segment" style="--_rotation:90deg">
<input name="attr_clock" value="2" hidden="" type="checkbox" title="@{repeating_rumors_$X_clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="3" hidden="" type="checkbox" title="@{repeating_rumors_$X_clock}"/>
<div class="clock__segment" style="--_rotation:150deg">
<input name="attr_clock" value="3" hidden="" type="checkbox" title="@{repeating_rumors_$X_clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="4" hidden="" type="checkbox" title="@{repeating_rumors_$X_clock}"/>
<div class="clock__segment" style="--_rotation:210deg">
<input name="attr_clock" value="4" hidden="" type="checkbox" title="@{repeating_rumors_$X_clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="5" hidden="" type="checkbox" title="@{repeating_rumors_$X_clock}"/>
<div class="clock__segment" style="--_rotation:270deg">
<input name="attr_clock" value="5" hidden="" type="checkbox" title="@{repeating_rumors_$X_clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="6" hidden="" type="checkbox" title="@{repeating_rumors_$X_clock}"/>
<div class="clock__segment" style="--_rotation:330deg">
<input name="attr_clock" value="6" hidden="" type="checkbox" title="@{repeating_rumors_$X_clock}"/>
</div>
<input class="clock__number" name="attr_clock" min="0" max="6" value="0" type="number" title="@{repeating_rumors_$X_clock}"/>
</div>
</div>
<label class="input-label stacked grid-span-all expanded"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_rumors_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" type="text" title="@{repeating_rumors_$X_description}"></textarea>
</div>
</label>
</fieldset>
</div>
</section>
<section class="head-section challenge-section">
<div class="header challenge-header">
<h3 data-i18n="challenges"></h3>
</div>
<div class="section-content challenge-content">
<button class="repcontrol-button repcontrol-button--add" name="act_add-challenges" type="action">
</button>
<fieldset class="repeating_challenges">
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_challenges_$X_collapse}"/><span class="collapsed" name="attr_name" title="@{repeating_challenges_$X_name}"></span>
<label class="input-label stacked expanded"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_challenges_$X_name}"/>
</label>
<label class="input-label stacked grid-span-all expanded"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_challenges_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" type="text" title="@{repeating_challenges_$X_description}"></textarea>
</div>
</label>
</fieldset>
</div>
</section>
<div class="faction-endgame-section">
<section class="head-section endgame-section grid-span-all">
<div class="header endgame-header grid-span-all column-subgrid">
<h3 data-i18n="endgame"></h3>
<h4 data-i18n="clock"></h4>
</div>
<div class="section-content endgame-content grid-span-all column-subgrid collapse-container">
<input class="collapse" name="attr_endgame_collapse" value="1" type="checkbox" title="@{endgame_collapse}"/><span class="collapsed" name="attr_endgame_name" title="@{endgame_name}"></span>
<input class="expanded" name="attr_endgame_name" type="text" title="@{endgame_name}"/>
<div class="clock-container">
<div class="clock" style="--_clockSize: 30px;--_sectionBase: 17.32041615186541px;--_sections: 6;">
<input class="clock__control" name="attr_clock" value="1" hidden="" type="checkbox" title="@{clock}"/>
<div class="clock__segment" style="--_rotation:30deg">
<input name="attr_clock" value="1" hidden="" type="checkbox" title="@{clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="2" hidden="" type="checkbox" title="@{clock}"/>
<div class="clock__segment" style="--_rotation:90deg">
<input name="attr_clock" value="2" hidden="" type="checkbox" title="@{clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="3" hidden="" type="checkbox" title="@{clock}"/>
<div class="clock__segment" style="--_rotation:150deg">
<input name="attr_clock" value="3" hidden="" type="checkbox" title="@{clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="4" hidden="" type="checkbox" title="@{clock}"/>
<div class="clock__segment" style="--_rotation:210deg">
<input name="attr_clock" value="4" hidden="" type="checkbox" title="@{clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="5" hidden="" type="checkbox" title="@{clock}"/>
<div class="clock__segment" style="--_rotation:270deg">
<input name="attr_clock" value="5" hidden="" type="checkbox" title="@{clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="6" hidden="" type="checkbox" title="@{clock}"/>
<div class="clock__segment" style="--_rotation:330deg">
<input name="attr_clock" value="6" hidden="" type="checkbox" title="@{clock}"/>
</div>
<input class="clock__number" name="attr_clock" min="0" max="6" value="0" type="number" title="@{clock}"/>
</div>
</div>
<label class="input-label stacked grid-span-all expanded"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_endgame_description" title="@{endgame_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_endgame_description" type="text" title="@{endgame_description}"></textarea>
</div>
</label>
</div>
</section>
<section class="head-section faction-section grid-span-all column-subgrid">
<div class="header faction-header grid-span-all column-subgrid">
<h3 data-i18n="factions"></h3>
<h4 data-i18n="clock"></h4>
</div>
<div class="section-content faction-content grid-span-all column-subgrid">
<button class="repcontrol-button repcontrol-button--add" name="act_add-factions" type="action">
</button>
<fieldset class="repeating_factions">
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_factions_$X_collapse}"/><span class="collapsed" name="attr_name" title="@{repeating_factions_$X_name}"></span>
<label class="input-label stacked expanded"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_factions_$X_name}"/>
</label>
<div class="clock-container">
<div class="clock" style="--_clockSize: 30px;--_sectionBase: 17.32041615186541px;--_sections: 6;">
<input class="clock__control" name="attr_clock" value="1" hidden="" type="checkbox" title="@{repeating_factions_$X_clock}"/>
<div class="clock__segment" style="--_rotation:30deg">
<input name="attr_clock" value="1" hidden="" type="checkbox" title="@{repeating_factions_$X_clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="2" hidden="" type="checkbox" title="@{repeating_factions_$X_clock}"/>
<div class="clock__segment" style="--_rotation:90deg">
<input name="attr_clock" value="2" hidden="" type="checkbox" title="@{repeating_factions_$X_clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="3" hidden="" type="checkbox" title="@{repeating_factions_$X_clock}"/>
<div class="clock__segment" style="--_rotation:150deg">
<input name="attr_clock" value="3" hidden="" type="checkbox" title="@{repeating_factions_$X_clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="4" hidden="" type="checkbox" title="@{repeating_factions_$X_clock}"/>
<div class="clock__segment" style="--_rotation:210deg">
<input name="attr_clock" value="4" hidden="" type="checkbox" title="@{repeating_factions_$X_clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="5" hidden="" type="checkbox" title="@{repeating_factions_$X_clock}"/>
<div class="clock__segment" style="--_rotation:270deg">
<input name="attr_clock" value="5" hidden="" type="checkbox" title="@{repeating_factions_$X_clock}"/>
</div>
<input class="clock__control" name="attr_clock" value="6" hidden="" type="checkbox" title="@{repeating_factions_$X_clock}"/>
<div class="clock__segment" style="--_rotation:330deg">
<input name="attr_clock" value="6" hidden="" type="checkbox" title="@{repeating_factions_$X_clock}"/>
</div>
<input class="clock__number" name="attr_clock" min="0" max="6" value="0" type="number" title="@{repeating_factions_$X_clock}"/>
</div>
</div>
<label class="input-label stacked grid-span-all expanded"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_factions_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" type="text" title="@{repeating_factions_$X_description}"></textarea>
</div>
</label>
</fieldset>
</div>
</section>
</div>
</article>
<article class="tabs__container tabs--walking-dead__container tabs--walking-dead__container--haven haven-page" data-container-tab="walking-dead" data-tab="haven">
<section class="haven-info-section" data-i18n-aria-label="haven info"><img class="logo" src="https://files.d20.io/images/368479329/HgW2WAq5CUmayPMeTQow3A/original.png"/>
<label class="input-label stacked name"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_character_name" type="text" title="@{character_name}"/>
</label>
<label class="input-label justify-space-between capacity"><span data-i18n="capacity"></span>
<input class="red-border" name="attr_capacity" type="number" title="@{capacity}"/>
</label>
<label class="input-label justify-space-between defense"><span data-i18n="defense"></span>
<input class="red-border" name="attr_defense" type="number" title="@{defense}"/>
</label>
<label class="input-label stacked issues"><span data-i18n="issues"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_issues" title="@{issues}"></span>
<textarea class="adaptive--text__textarea" name="attr_issues" type="text" title="@{issues}"></textarea>
</div>
</label>
<section class="head-section haven-info-description border-back-interior">
<div class="header">
<h3 data-i18n="description"></h3>
</div>
<div class="section-content haven-description-content">
<label class="input-label stacked"><span data-i18n="overall"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_overall" title="@{overall}"></span>
<textarea class="adaptive--text__textarea" name="attr_overall" title="@{overall}"></textarea>
</div>
</label>
<label class="input-label stacked"><span data-i18n="structures"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_structures" title="@{structures}"></span>
<textarea class="adaptive--text__textarea" name="attr_structures" title="@{structures}"></textarea>
</div>
</label>
<label class="input-label stacked"><span data-i18n="surroudings"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_surroudings" title="@{surroudings}"></span>
<textarea class="adaptive--text__textarea" name="attr_surroudings" title="@{surroudings}"></textarea>
</div>
</label>
<label class="input-label stacked"><span data-i18n="food sources"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_food_sources" title="@{food_sources}"></span>
<textarea class="adaptive--text__textarea" name="attr_food_sources" title="@{food_sources}"></textarea>
</div>
</label>
<section class="head-section stored-gear-section">
<div class="header">
<h3 data-i18n="stored gear"></h3>
</div>
<div class="section-content haven-stored-gear">
<button class="repcontrol-button repcontrol-button--add" name="act_add-stored-gear" type="action">
</button>
<fieldset class="repeating_stored-gear">
<input class="equip-checkbox" name="attr_equipped" value="1" type="checkbox" title="@{repeating_stored-gear_$X_equipped}"/>
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_stored-gear_$X_collapse}"/>
<div class="no-gap collapsed column-subgrid grid-span-all gear-display border-back">
<div class="flex-box tiny-gap justify-center"><span class="qty-span" name="attr_quantity" title="@{repeating_stored-gear_$X_quantity}"></span><span class="slots" name="attr_slots" title="@{repeating_stored-gear_$X_slots}"></span>
</div><span class="gear-name-span" name="attr_name" title="@{repeating_stored-gear_$X_name}"></span>
<input class="bonus" name="attr_bonus" readonly="" type="number" title="@{repeating_stored-gear_$X_bonus}"/>
</div>
<div class="expanded grid-span-all gear-display border-back">
<label class="input-label stacked name-input grid-span-all"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_stored-gear_$X_name}"/>
</label>
<label class="input-label stacked"><span class="input-label__text" data-i18n="quantity abbreviation"></span>
<input class="input-label__input" name="attr_quantity" type="number" title="@{repeating_stored-gear_$X_quantity}"/>
</label>
<label class="input-label stacked gear-slots"><span class="input-label__text" data-i18n="slots"></span>
<input class="number input-label__input" name="attr_slots" type="text" title="@{repeating_stored-gear_$X_slots}"/>
</label>
<label class="input-label stacked bonus-input"><span class="input-label__text" data-i18n="bonus"></span>
<input class="input-label__input" name="attr_bonus" type="number" title="@{repeating_stored-gear_$X_bonus}"/>
</label>
<label class="input-label stacked grid-span-all"><span class="input-label__text" data-i18n="owner"></span>
<input class="input-label__input" name="attr_owner" type="text" title="@{repeating_stored-gear_$X_owner}"/>
</label>
<label class="input-label stacked grid-span-all"><span class="input-label__text" data-i18n="affects"></span>
<select class="input-label__input" name="attr_affects" title="@{repeating_stored-gear_$X_affects}">
<option value="" data-i18n="select one">
</option>
<option value="close combat" data-i18n="close combat">
</option>
<option value="endure" data-i18n="endure">
</option>
<option value="force" data-i18n="force">
</option>
<option value="mobility" data-i18n="mobility">
</option>
<option value="ranged combat" data-i18n="ranged combat">
</option>
<option value="stealth" data-i18n="stealth">
</option>
<option value="scout" data-i18n="scout">
</option>
<option value="survival" data-i18n="survival">
</option>
<option value="tech" data-i18n="tech">
</option>
<option value="leadership" data-i18n="leadership">
</option>
<option value="manipulation" data-i18n="manipulation">
</option>
<option value="medicine" data-i18n="medicine">
</option>
</select>
</label>
<label class="input-label stacked grid-span-all"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_stored-gear_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" title="@{repeating_stored-gear_$X_description}"></textarea>
</div>
</label>
</div>
<input name="attr_connected_json" type="hidden" title="@{repeating_stored-gear_$X_connected_json}"/>
</fieldset>
</div>
</section>
</div>
</section>
<section class="head-section haven-project-section">
<div class="header haven-project-header">
<h3 data-i18n="projects"></h3>
</div>
<div class="section-content haven-project-content border-back-interior">
<button class="repcontrol-button repcontrol-button--add" name="act_add-projects" type="action">
</button>
<fieldset class="repeating_projects">
<div class="cardExpanded expanded">
</div>
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_projects_$X_collapse}"/>
<label class="input-label stacked"><span class="input-label__text" data-i18n="project"></span>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_projects_$X_name}"/>
</label>
<label class="input-label stacked"><span class="input-label__text" data-i18n="effect"></span>
<input class="input-label__input" name="attr_effect" type="text" title="@{repeating_projects_$X_effect}"/>
</label>
<label class="input-label justify-space-between expanded"><span data-i18n="workforce"></span>
<input class="red-border" name="attr_workforce" type="number" title="@{repeating_projects_$X_workforce}"/>
</label>
<label class="input-label justify-space-between expanded"><span data-i18n="finish date"></span>
<input class="red-border" name="attr_finish_date" type="text" title="@{repeating_projects_$X_finish_date}"/>
</label>
<label class="input-label stacked expanded grid-span-all"><span data-i18n="requirements"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_requirements" title="@{repeating_projects_$X_requirements}"></span>
<textarea class="adaptive--text__textarea" name="attr_requirements" title="@{repeating_projects_$X_requirements}"></textarea>
</div>
</label>
</fieldset>
</div>
</section>
</section>
<section class="head-section haven-npc-section">
<div class="header haven-npc-header">
<h3 data-i18n="npc survivors"></h3>
</div>
<div class="section-content haven-npc-content">
<button class="repcontrol-button repcontrol-button--add" name="act_add-npcs" type="action">
</button>
<fieldset class="repeating_npcs">
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_npcs_$X_collapse}"/>
<div class="collapsed">
<div class="flex-box half-gap"><span class="bold" name="attr_name" title="@{repeating_npcs_$X_name}"></span><span name="attr_descriptor" title="@{repeating_npcs_$X_descriptor}"></span>
</div>
<div class="flex-box flex-wrap npc-skill-row">
<button class="flex-box controlled-display roller" name="roll_npc_untrained_skills" value="@{npc_untrained_skills_action}" type="roll"><span class="capitalize bold" data-i18n="skills"></span>
<input class="display-control" name="attr_npc_is_untrained" value="1" hidden="" checked="" readonly="" type="checkbox" title="@{repeating_npcs_$X_npc_is_untrained}"/><span class="controlled-display" data-i18n="untrained"></span>
</button>
<button name="act_npc-untrained-skills-action" hidden="" type="action">
</button>
<input name="attr_npc_untrained_skills_action" type="hidden" title="@{repeating_npcs_$X_npc_untrained_skills_action}"/>
<input class="display-control" name="attr_npc_is_trained" value="1" hidden="" readonly="" type="checkbox" title="@{repeating_npcs_$X_npc_is_trained}"/>
<div class="trained-display controlled-display npc-skill-display flex-box half-gap"><span class="bold capitalize" data-i18n="trained"></span>
<div class="flex-box tiny-gap-x flex-wrap">
<input class="display-control" name="attr_close_combat" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_close_combat}"/>
<button class="controlled-display roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{repeating_npcs_$X_close_combat_action}"/>
<input class="display-control" name="attr_endure" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_endure}"/>
<button class="controlled-display roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{repeating_npcs_$X_endure_action}"/>
<input class="display-control" name="attr_force" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_force}"/>
<button class="controlled-display roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{repeating_npcs_$X_force_action}"/>
<input class="display-control" name="attr_mobility" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_mobility}"/>
<button class="controlled-display roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{repeating_npcs_$X_mobility_action}"/>
<input class="display-control" name="attr_ranged_combat" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_ranged_combat}"/>
<button class="controlled-display roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{repeating_npcs_$X_ranged_combat_action}"/>
<input class="display-control" name="attr_stealth" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_stealth}"/>
<button class="controlled-display roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{repeating_npcs_$X_stealth_action}"/>
<input class="display-control" name="attr_scout" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_scout}"/>
<button class="controlled-display roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{repeating_npcs_$X_scout_action}"/>
<input class="display-control" name="attr_survival" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_survival}"/>
<button class="controlled-display roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{repeating_npcs_$X_survival_action}"/>
<input class="display-control" name="attr_tech" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_tech}"/>
<button class="controlled-display roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{repeating_npcs_$X_tech_action}"/>
<input class="display-control" name="attr_leadership" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_leadership}"/>
<button class="controlled-display roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{repeating_npcs_$X_leadership_action}"/>
<input class="display-control" name="attr_manipulation" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_manipulation}"/>
<button class="controlled-display roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{repeating_npcs_$X_manipulation_action}"/>
<input class="display-control" name="attr_medicine" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_medicine}"/>
<button class="controlled-display roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{repeating_npcs_$X_medicine_action}"/>
</div>
</div>
<input class="display-control" name="attr_npc_is_expert" value="1" hidden="" readonly="" type="checkbox" title="@{repeating_npcs_$X_npc_is_expert}"/>
<div class="expert-display controlled-display npc-skill-display flex-box half-gap"><span class="bold capitalize" data-i18n="expert"></span>
<div class="flex-box tiny-gap-x flex-wrap">
<input class="display-control" name="attr_close_combat" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_close_combat}"/>
<button class="controlled-display roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{repeating_npcs_$X_close_combat_action}"/>
<input class="display-control" name="attr_endure" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_endure}"/>
<button class="controlled-display roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{repeating_npcs_$X_endure_action}"/>
<input class="display-control" name="attr_force" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_force}"/>
<button class="controlled-display roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{repeating_npcs_$X_force_action}"/>
<input class="display-control" name="attr_mobility" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_mobility}"/>
<button class="controlled-display roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{repeating_npcs_$X_mobility_action}"/>
<input class="display-control" name="attr_ranged_combat" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_ranged_combat}"/>
<button class="controlled-display roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{repeating_npcs_$X_ranged_combat_action}"/>
<input class="display-control" name="attr_stealth" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_stealth}"/>
<button class="controlled-display roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{repeating_npcs_$X_stealth_action}"/>
<input class="display-control" name="attr_scout" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_scout}"/>
<button class="controlled-display roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{repeating_npcs_$X_scout_action}"/>
<input class="display-control" name="attr_survival" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_survival}"/>
<button class="controlled-display roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{repeating_npcs_$X_survival_action}"/>
<input class="display-control" name="attr_tech" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_tech}"/>
<button class="controlled-display roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{repeating_npcs_$X_tech_action}"/>
<input class="display-control" name="attr_leadership" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_leadership}"/>
<button class="controlled-display roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{repeating_npcs_$X_leadership_action}"/>
<input class="display-control" name="attr_manipulation" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_manipulation}"/>
<button class="controlled-display roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{repeating_npcs_$X_manipulation_action}"/>
<input class="display-control" name="attr_medicine" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_medicine}"/>
<button class="controlled-display roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{repeating_npcs_$X_medicine_action}"/>
</div>
</div>
<input class="display-control" name="attr_npc_is_master" value="1" hidden="" readonly="" type="checkbox" title="@{repeating_npcs_$X_npc_is_master}"/>
<div class="master-display controlled-display npc-skill-display flex-box half-gap"><span class="bold capitalize" data-i18n="master"></span>
<div class="flex-box tiny-gap-x flex-wrap">
<input class="display-control" name="attr_close_combat" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_close_combat}"/>
<button class="controlled-display roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{repeating_npcs_$X_close_combat_action}"/>
<input class="display-control" name="attr_endure" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_endure}"/>
<button class="controlled-display roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{repeating_npcs_$X_endure_action}"/>
<input class="display-control" name="attr_force" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_force}"/>
<button class="controlled-display roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{repeating_npcs_$X_force_action}"/>
<input class="display-control" name="attr_mobility" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_mobility}"/>
<button class="controlled-display roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{repeating_npcs_$X_mobility_action}"/>
<input class="display-control" name="attr_ranged_combat" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_ranged_combat}"/>
<button class="controlled-display roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{repeating_npcs_$X_ranged_combat_action}"/>
<input class="display-control" name="attr_stealth" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_stealth}"/>
<button class="controlled-display roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{repeating_npcs_$X_stealth_action}"/>
<input class="display-control" name="attr_scout" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_scout}"/>
<button class="controlled-display roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{repeating_npcs_$X_scout_action}"/>
<input class="display-control" name="attr_survival" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_survival}"/>
<button class="controlled-display roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{repeating_npcs_$X_survival_action}"/>
<input class="display-control" name="attr_tech" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_tech}"/>
<button class="controlled-display roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{repeating_npcs_$X_tech_action}"/>
<input class="display-control" name="attr_leadership" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_leadership}"/>
<button class="controlled-display roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{repeating_npcs_$X_leadership_action}"/>
<input class="display-control" name="attr_manipulation" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_manipulation}"/>
<button class="controlled-display roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{repeating_npcs_$X_manipulation_action}"/>
<input class="display-control" name="attr_medicine" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_medicine}"/>
<button class="controlled-display roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{repeating_npcs_$X_medicine_action}"/>
</div>
</div>
</div>
<input class="display-control--non-zero" name="attr_gear" value="" type="hidden" title="@{repeating_npcs_$X_gear}"/>
<div class="flex-box controlled-display"><span class="capitalize bold" data-i18n="gear"></span><span name="attr_gear" title="@{repeating_npcs_$X_gear}"></span>
</div>
<input class="display-control--non-zero" name="attr_weapons" value="" type="hidden" title="@{repeating_npcs_$X_weapons}"/>
<button class="flex-box controlled-display roller" name="roll_weapons" value="@{weapons_action}" type="roll"><span class="capitalize bold" data-i18n="weapons"></span><span name="attr_weapons" title="@{repeating_npcs_$X_weapons}"></span>
</button>
<button name="act_weapons-action" hidden="" type="action">
</button>
<input name="attr_weapons_action" type="hidden" title="@{repeating_npcs_$X_weapons_action}"/>
</div>
<div class="expanded border-back-interior">
<label class="input-label stacked"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_npcs_$X_name}"/>
</label>
<label class="input-label stacked"><span class="input-label__text" data-i18n="descriptor"></span>
<input class="input-label__input" name="attr_descriptor" type="text" title="@{repeating_npcs_$X_descriptor}"/>
</label>
<div class="flex-box flex-wrap npc-skill-container">
<button class="bold capitalize roller" name="roll_npc_untrained_skills" data-i18n="skills" style="background: white; width: 100%" value="@{npc_untrained_skills_action}" type="roll">
</button>
<button name="act_npc-untrained-skills-action" hidden="" type="action">
</button>
<input name="attr_npc_untrained_skills_action" type="hidden" title="@{repeating_npcs_$X_npc_untrained_skills_action}"/>
<div class="npc-skill-edit">
<div class="input-label justify-end">
<button class="roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{repeating_npcs_$X_close_combat_action}"/>
<select class="red-border" name="attr_close_combat" title="@{repeating_npcs_$X_close_combat}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{repeating_npcs_$X_endure_action}"/>
<select class="red-border" name="attr_endure" title="@{repeating_npcs_$X_endure}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{repeating_npcs_$X_force_action}"/>
<select class="red-border" name="attr_force" title="@{repeating_npcs_$X_force}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{repeating_npcs_$X_mobility_action}"/>
<select class="red-border" name="attr_mobility" title="@{repeating_npcs_$X_mobility}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{repeating_npcs_$X_ranged_combat_action}"/>
<select class="red-border" name="attr_ranged_combat" title="@{repeating_npcs_$X_ranged_combat}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{repeating_npcs_$X_stealth_action}"/>
<select class="red-border" name="attr_stealth" title="@{repeating_npcs_$X_stealth}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{repeating_npcs_$X_scout_action}"/>
<select class="red-border" name="attr_scout" title="@{repeating_npcs_$X_scout}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{repeating_npcs_$X_survival_action}"/>
<select class="red-border" name="attr_survival" title="@{repeating_npcs_$X_survival}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{repeating_npcs_$X_tech_action}"/>
<select class="red-border" name="attr_tech" title="@{repeating_npcs_$X_tech}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{repeating_npcs_$X_leadership_action}"/>
<select class="red-border" name="attr_leadership" title="@{repeating_npcs_$X_leadership}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{repeating_npcs_$X_manipulation_action}"/>
<select class="red-border" name="attr_manipulation" title="@{repeating_npcs_$X_manipulation}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{repeating_npcs_$X_medicine_action}"/>
<select class="red-border" name="attr_medicine" title="@{repeating_npcs_$X_medicine}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
</div>
</div>
<input class="display-control--zero" name="attr_character_id" value="" type="hidden" title="@{repeating_npcs_$X_character_id}"/>
<label class="input-label stacked controlled-display"><span class="input-label__text" data-i18n="gear"></span>
<input class="input-label__input" name="attr_gear" type="text" title="@{repeating_npcs_$X_gear}"/>
</label>
<input class="display-control--zero" name="attr_character_id" value="" type="hidden" title="@{repeating_npcs_$X_character_id}"/>
<div class="input-label input-label--button stacked controlled-display">
<button class="roller" name="roll_weapons" data-i18n="weapons" value="@{weapons_action}" type="roll">
</button>
<input class="input-label__input" name="attr_weapons" type="text" title="@{repeating_npcs_$X_weapons}"/>
</div>
<button name="act_weapons-action" hidden="" type="action">
</button>
<input name="attr_weapons_action" type="hidden" title="@{repeating_npcs_$X_weapons_action}"/>
<label class="input-label stacked grid-span-all"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_npcs_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" type="text" title="@{repeating_npcs_$X_description}"></textarea>
</div>
</label>
</div>
</fieldset>
</div>
</section>
</article>
<article class="tabs__container tabs--walking-dead__container tabs--walking-dead__container--faction faction-page border-back-container collapse-container" data-container-tab="walking-dead" data-tab="faction">
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{collapse}"/>
<div class="expanded">
<input class="faction-spacer" name="attr_character_name" style="column-span:all;" role="heading" aria-level="2" type="text" title="@{character_name}"/>
<div class="adaptive adaptive--text underlined faction-spacer"><span class="adaptive--text__span" name="attr_character_description" title="@{character_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_character_description" title="@{character_description}"></textarea>
</div>
<div class="avoid-break-inside">
<h3 class="faction-spacer" data-i18n="issues"></h3>
<div class="adaptive adaptive--text underlined faction-spacer"><span class="adaptive--text__span" name="attr_character_issues" title="@{character_issues}"></span>
<textarea class="adaptive--text__textarea" name="attr_character_issues" title="@{character_issues}"></textarea>
</div>
</div>
<div class="avoid-break-inside faction-haven-container">
<h3 class="faction-spacer" data-i18n="haven"></h3>
<label class="input-label stacked faction-spacer"><span class="input-label__text" data-i18n="name"></span>
<input class="underlined input-label__input" name="attr_haven_name" type="text" data-i18n-placeholder="name for autolinking" title="@{haven_name}"/>
</label>
<div class="adaptive adaptive--text underlined faction-spacer"><span class="adaptive--text__span" name="attr_haven_description" title="@{haven_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_haven_description" title="@{haven_description}"></textarea>
</div>
<label class="input-label faction-spacer"><span class="input-label__text" data-i18n="capacity"></span>
<input class="underlined input-label__input" name="attr_haven_capacity" type="number" value="0" title="@{haven_capacity}"/>
</label>
<label class="input-label faction-spacer"><span class="input-label__text" data-i18n="defense"></span>
<input class="underlined input-label__input" name="attr_haven_defense" type="number" value="0" title="@{haven_defense}"/>
</label>
</div>
<div class="avoid-break-inside faction-challenge-container">
<h3 class="faction-spacer" data-i18n="challenges"></h3>
<div class="adaptive adaptive--text underlined faction-spacer"><span class="adaptive--text__span" name="attr_challenges_description" title="@{challenges_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_challenges_description" title="@{challenges_description}"></textarea>
</div>
</div>
</div>
<div class="collapsed"><span class="faction-spacer" name="attr_character_name" role="heading" aria-level="2" title="@{character_name}" style="column-span:all;"></span><span class="paragraph faction-spacer" name="attr_character_description" title="@{character_description}"></span>
<input class="display-control--non-zero" name="attr_character_issues" value="" type="hidden" title="@{character_issues}"/>
<div class="avoid-break-inside controlled-display">
<h3 class="faction-spacer" data-i18n="issues"></h3><span class="paragraph faction-spacer" name="attr_character_issues" title="@{character_issues}"></span>
</div>
<input class="display-control--non-zero" name="attr_haven_name" value="" type="hidden" title="@{haven_name}"/>
<div class="avoid-break-inside faction-haven-container controlled-display">
<h3 class="faction-spacer" data-i18n="haven"></h3><span class="paragraph faction-spacer" name="attr_haven_description" title="@{haven_description}"></span>
<div class="input-label faction-spacer"><span class="input-label__span" data-i18n="capacity"></span><span class="input-label__input" name="attr_capacity" title="@{capacity}"></span>
</div>
<div class="input-label faction-spacer"><span class="input-label__span" data-i18n="defense"></span><span class="input-label__input" name="attr_defense" title="@{defense}"></span>
</div>
</div>
<input class="display-control--non-zero" name="attr_challenge_description" type="hidden" title="@{challenge_description}"/>
<div class="avoid-break-inside faction-challenges-container controlled-display">
<h3 class="faction-spacer" data-i18n="challenges"></h3><span class="paragraph faction-spacer" name="attr_challenge_description" title="@{challenge_description}"></span>
</div>
</div>
<div class="avoid-break-inside faction-npc-container repeating-section-container">
<h3 data-i18n="key npcs"></h3>
<button class="repcontrol-button repcontrol-button--add" name="act_add-npcs" type="action">
</button>
<fieldset class="repeating_npcs">
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_npcs_$X_collapse}"/>
<div class="collapsed">
<div class="flex-box half-gap"><span class="bold" name="attr_name" title="@{repeating_npcs_$X_name}"></span><span name="attr_descriptor" title="@{repeating_npcs_$X_descriptor}"></span>
</div>
<div class="flex-box flex-wrap npc-skill-row">
<button class="flex-box controlled-display roller" name="roll_npc_untrained_skills" value="@{npc_untrained_skills_action}" type="roll"><span class="capitalize bold" data-i18n="skills"></span>
<input class="display-control" name="attr_npc_is_untrained" value="1" hidden="" checked="" readonly="" type="checkbox" title="@{repeating_npcs_$X_npc_is_untrained}"/><span class="controlled-display" data-i18n="untrained"></span>
</button>
<button name="act_npc-untrained-skills-action" hidden="" type="action">
</button>
<input name="attr_npc_untrained_skills_action" type="hidden" title="@{repeating_npcs_$X_npc_untrained_skills_action}"/>
<input class="display-control" name="attr_npc_is_trained" value="1" hidden="" readonly="" type="checkbox" title="@{repeating_npcs_$X_npc_is_trained}"/>
<div class="trained-display controlled-display npc-skill-display flex-box half-gap"><span class="bold capitalize" data-i18n="trained"></span>
<div class="flex-box tiny-gap-x flex-wrap">
<input class="display-control" name="attr_close_combat" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_close_combat}"/>
<button class="controlled-display roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{repeating_npcs_$X_close_combat_action}"/>
<input class="display-control" name="attr_endure" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_endure}"/>
<button class="controlled-display roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{repeating_npcs_$X_endure_action}"/>
<input class="display-control" name="attr_force" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_force}"/>
<button class="controlled-display roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{repeating_npcs_$X_force_action}"/>
<input class="display-control" name="attr_mobility" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_mobility}"/>
<button class="controlled-display roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{repeating_npcs_$X_mobility_action}"/>
<input class="display-control" name="attr_ranged_combat" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_ranged_combat}"/>
<button class="controlled-display roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{repeating_npcs_$X_ranged_combat_action}"/>
<input class="display-control" name="attr_stealth" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_stealth}"/>
<button class="controlled-display roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{repeating_npcs_$X_stealth_action}"/>
<input class="display-control" name="attr_scout" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_scout}"/>
<button class="controlled-display roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{repeating_npcs_$X_scout_action}"/>
<input class="display-control" name="attr_survival" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_survival}"/>
<button class="controlled-display roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{repeating_npcs_$X_survival_action}"/>
<input class="display-control" name="attr_tech" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_tech}"/>
<button class="controlled-display roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{repeating_npcs_$X_tech_action}"/>
<input class="display-control" name="attr_leadership" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_leadership}"/>
<button class="controlled-display roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{repeating_npcs_$X_leadership_action}"/>
<input class="display-control" name="attr_manipulation" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_manipulation}"/>
<button class="controlled-display roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{repeating_npcs_$X_manipulation_action}"/>
<input class="display-control" name="attr_medicine" value="5" hidden="" type="checkbox" title="@{repeating_npcs_$X_medicine}"/>
<button class="controlled-display roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{repeating_npcs_$X_medicine_action}"/>
</div>
</div>
<input class="display-control" name="attr_npc_is_expert" value="1" hidden="" readonly="" type="checkbox" title="@{repeating_npcs_$X_npc_is_expert}"/>
<div class="expert-display controlled-display npc-skill-display flex-box half-gap"><span class="bold capitalize" data-i18n="expert"></span>
<div class="flex-box tiny-gap-x flex-wrap">
<input class="display-control" name="attr_close_combat" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_close_combat}"/>
<button class="controlled-display roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{repeating_npcs_$X_close_combat_action}"/>
<input class="display-control" name="attr_endure" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_endure}"/>
<button class="controlled-display roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{repeating_npcs_$X_endure_action}"/>
<input class="display-control" name="attr_force" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_force}"/>
<button class="controlled-display roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{repeating_npcs_$X_force_action}"/>
<input class="display-control" name="attr_mobility" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_mobility}"/>
<button class="controlled-display roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{repeating_npcs_$X_mobility_action}"/>
<input class="display-control" name="attr_ranged_combat" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_ranged_combat}"/>
<button class="controlled-display roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{repeating_npcs_$X_ranged_combat_action}"/>
<input class="display-control" name="attr_stealth" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_stealth}"/>
<button class="controlled-display roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{repeating_npcs_$X_stealth_action}"/>
<input class="display-control" name="attr_scout" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_scout}"/>
<button class="controlled-display roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{repeating_npcs_$X_scout_action}"/>
<input class="display-control" name="attr_survival" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_survival}"/>
<button class="controlled-display roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{repeating_npcs_$X_survival_action}"/>
<input class="display-control" name="attr_tech" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_tech}"/>
<button class="controlled-display roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{repeating_npcs_$X_tech_action}"/>
<input class="display-control" name="attr_leadership" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_leadership}"/>
<button class="controlled-display roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{repeating_npcs_$X_leadership_action}"/>
<input class="display-control" name="attr_manipulation" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_manipulation}"/>
<button class="controlled-display roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{repeating_npcs_$X_manipulation_action}"/>
<input class="display-control" name="attr_medicine" value="8" hidden="" type="checkbox" title="@{repeating_npcs_$X_medicine}"/>
<button class="controlled-display roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{repeating_npcs_$X_medicine_action}"/>
</div>
</div>
<input class="display-control" name="attr_npc_is_master" value="1" hidden="" readonly="" type="checkbox" title="@{repeating_npcs_$X_npc_is_master}"/>
<div class="master-display controlled-display npc-skill-display flex-box half-gap"><span class="bold capitalize" data-i18n="master"></span>
<div class="flex-box tiny-gap-x flex-wrap">
<input class="display-control" name="attr_close_combat" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_close_combat}"/>
<button class="controlled-display roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{repeating_npcs_$X_close_combat_action}"/>
<input class="display-control" name="attr_endure" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_endure}"/>
<button class="controlled-display roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{repeating_npcs_$X_endure_action}"/>
<input class="display-control" name="attr_force" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_force}"/>
<button class="controlled-display roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{repeating_npcs_$X_force_action}"/>
<input class="display-control" name="attr_mobility" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_mobility}"/>
<button class="controlled-display roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{repeating_npcs_$X_mobility_action}"/>
<input class="display-control" name="attr_ranged_combat" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_ranged_combat}"/>
<button class="controlled-display roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{repeating_npcs_$X_ranged_combat_action}"/>
<input class="display-control" name="attr_stealth" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_stealth}"/>
<button class="controlled-display roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{repeating_npcs_$X_stealth_action}"/>
<input class="display-control" name="attr_scout" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_scout}"/>
<button class="controlled-display roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{repeating_npcs_$X_scout_action}"/>
<input class="display-control" name="attr_survival" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_survival}"/>
<button class="controlled-display roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{repeating_npcs_$X_survival_action}"/>
<input class="display-control" name="attr_tech" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_tech}"/>
<button class="controlled-display roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{repeating_npcs_$X_tech_action}"/>
<input class="display-control" name="attr_leadership" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_leadership}"/>
<button class="controlled-display roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{repeating_npcs_$X_leadership_action}"/>
<input class="display-control" name="attr_manipulation" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_manipulation}"/>
<button class="controlled-display roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{repeating_npcs_$X_manipulation_action}"/>
<input class="display-control" name="attr_medicine" value="10" hidden="" type="checkbox" title="@{repeating_npcs_$X_medicine}"/>
<button class="controlled-display roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{repeating_npcs_$X_medicine_action}"/>
</div>
</div>
</div>
<input class="display-control--non-zero" name="attr_gear" value="" type="hidden" title="@{repeating_npcs_$X_gear}"/>
<div class="flex-box controlled-display"><span class="capitalize bold" data-i18n="gear"></span><span name="attr_gear" title="@{repeating_npcs_$X_gear}"></span>
</div>
<input class="display-control--non-zero" name="attr_weapons" value="" type="hidden" title="@{repeating_npcs_$X_weapons}"/>
<button class="flex-box controlled-display roller" name="roll_weapons" value="@{weapons_action}" type="roll"><span class="capitalize bold" data-i18n="weapons"></span><span name="attr_weapons" title="@{repeating_npcs_$X_weapons}"></span>
</button>
<button name="act_weapons-action" hidden="" type="action">
</button>
<input name="attr_weapons_action" type="hidden" title="@{repeating_npcs_$X_weapons_action}"/>
</div>
<div class="expanded border-back-interior">
<label class="input-label stacked"><span class="input-label__text" data-i18n="name"></span>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_npcs_$X_name}"/>
</label>
<label class="input-label stacked"><span class="input-label__text" data-i18n="descriptor"></span>
<input class="input-label__input" name="attr_descriptor" type="text" title="@{repeating_npcs_$X_descriptor}"/>
</label>
<div class="flex-box flex-wrap npc-skill-container">
<button class="bold capitalize roller" name="roll_npc_untrained_skills" data-i18n="skills" style="background: white; width: 100%" value="@{npc_untrained_skills_action}" type="roll">
</button>
<button name="act_npc-untrained-skills-action" hidden="" type="action">
</button>
<input name="attr_npc_untrained_skills_action" type="hidden" title="@{repeating_npcs_$X_npc_untrained_skills_action}"/>
<div class="npc-skill-edit">
<div class="input-label justify-end">
<button class="roller" name="roll_close_combat" data-i18n="close combat" value="@{close_combat_action}" type="roll">
</button>
<button name="act_close-combat-action" hidden="" type="action">
</button>
<input name="attr_close_combat_action" type="hidden" title="@{repeating_npcs_$X_close_combat_action}"/>
<select class="red-border" name="attr_close_combat" title="@{repeating_npcs_$X_close_combat}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_endure" data-i18n="endure" value="@{endure_action}" type="roll">
</button>
<button name="act_endure-action" hidden="" type="action">
</button>
<input name="attr_endure_action" type="hidden" title="@{repeating_npcs_$X_endure_action}"/>
<select class="red-border" name="attr_endure" title="@{repeating_npcs_$X_endure}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_force" data-i18n="force" value="@{force_action}" type="roll">
</button>
<button name="act_force-action" hidden="" type="action">
</button>
<input name="attr_force_action" type="hidden" title="@{repeating_npcs_$X_force_action}"/>
<select class="red-border" name="attr_force" title="@{repeating_npcs_$X_force}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_mobility" data-i18n="mobility" value="@{mobility_action}" type="roll">
</button>
<button name="act_mobility-action" hidden="" type="action">
</button>
<input name="attr_mobility_action" type="hidden" title="@{repeating_npcs_$X_mobility_action}"/>
<select class="red-border" name="attr_mobility" title="@{repeating_npcs_$X_mobility}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_ranged_combat" data-i18n="ranged combat" value="@{ranged_combat_action}" type="roll">
</button>
<button name="act_ranged-combat-action" hidden="" type="action">
</button>
<input name="attr_ranged_combat_action" type="hidden" title="@{repeating_npcs_$X_ranged_combat_action}"/>
<select class="red-border" name="attr_ranged_combat" title="@{repeating_npcs_$X_ranged_combat}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_stealth" data-i18n="stealth" value="@{stealth_action}" type="roll">
</button>
<button name="act_stealth-action" hidden="" type="action">
</button>
<input name="attr_stealth_action" type="hidden" title="@{repeating_npcs_$X_stealth_action}"/>
<select class="red-border" name="attr_stealth" title="@{repeating_npcs_$X_stealth}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_scout" data-i18n="scout" value="@{scout_action}" type="roll">
</button>
<button name="act_scout-action" hidden="" type="action">
</button>
<input name="attr_scout_action" type="hidden" title="@{repeating_npcs_$X_scout_action}"/>
<select class="red-border" name="attr_scout" title="@{repeating_npcs_$X_scout}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_survival" data-i18n="survival" value="@{survival_action}" type="roll">
</button>
<button name="act_survival-action" hidden="" type="action">
</button>
<input name="attr_survival_action" type="hidden" title="@{repeating_npcs_$X_survival_action}"/>
<select class="red-border" name="attr_survival" title="@{repeating_npcs_$X_survival}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_tech" data-i18n="tech" value="@{tech_action}" type="roll">
</button>
<button name="act_tech-action" hidden="" type="action">
</button>
<input name="attr_tech_action" type="hidden" title="@{repeating_npcs_$X_tech_action}"/>
<select class="red-border" name="attr_tech" title="@{repeating_npcs_$X_tech}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_leadership" data-i18n="leadership" value="@{leadership_action}" type="roll">
</button>
<button name="act_leadership-action" hidden="" type="action">
</button>
<input name="attr_leadership_action" type="hidden" title="@{repeating_npcs_$X_leadership_action}"/>
<select class="red-border" name="attr_leadership" title="@{repeating_npcs_$X_leadership}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_manipulation" data-i18n="manipulation" value="@{manipulation_action}" type="roll">
</button>
<button name="act_manipulation-action" hidden="" type="action">
</button>
<input name="attr_manipulation_action" type="hidden" title="@{repeating_npcs_$X_manipulation_action}"/>
<select class="red-border" name="attr_manipulation" title="@{repeating_npcs_$X_manipulation}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
<div class="input-label justify-end">
<button class="roller" name="roll_medicine" data-i18n="medicine" value="@{medicine_action}" type="roll">
</button>
<button name="act_medicine-action" hidden="" type="action">
</button>
<input name="attr_medicine_action" type="hidden" title="@{repeating_npcs_$X_medicine_action}"/>
<select class="red-border" name="attr_medicine" title="@{repeating_npcs_$X_medicine}">
<option value="4" data-i18n="untrained" selected="">
</option>
<option data-i18n="trained" value="5">
</option>
<option data-i18n="expert" value="8">
</option>
<option data-i18n="master" value="10">
</option>
</select>
</div>
</div>
</div>
<input class="display-control--zero" name="attr_character_id" value="" type="hidden" title="@{repeating_npcs_$X_character_id}"/>
<label class="input-label stacked controlled-display"><span class="input-label__text" data-i18n="gear"></span>
<input class="input-label__input" name="attr_gear" type="text" title="@{repeating_npcs_$X_gear}"/>
</label>
<input class="display-control--zero" name="attr_character_id" value="" type="hidden" title="@{repeating_npcs_$X_character_id}"/>
<div class="input-label input-label--button stacked controlled-display">
<button class="roller" name="roll_weapons" data-i18n="weapons" value="@{weapons_action}" type="roll">
</button>
<input class="input-label__input" name="attr_weapons" type="text" title="@{repeating_npcs_$X_weapons}"/>
</div>
<button name="act_weapons-action" hidden="" type="action">
</button>
<input name="attr_weapons_action" type="hidden" title="@{repeating_npcs_$X_weapons_action}"/>
<label class="input-label stacked grid-span-all"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_npcs_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" type="text" title="@{repeating_npcs_$X_description}"></textarea>
</div>
</label>
</div>
</fieldset>
</div>
</article>
<article class="tabs__container tabs--walking-dead__container tabs--walking-dead__container--gm gm-section border-back-container collapse-container" data-container-tab="walking-dead" data-tab="gm">
<div class="threat-container"><span class="threat-number size1" name="attr_threat" value="0" title="@{threat}">0</span>
<button class="threat-minus size1 roller" name="roll_decrease_threat" value="@{decrease_threat_action}" type="roll">-
</button>
<button name="act_decrease-threat-action" hidden="" type="action">
</button>
<input name="attr_decrease_threat_action" type="hidden" title="@{decrease_threat_action}"/>
<h3 class="threat-head" data-i18n="threat meter"></h3>
<button class="threat-add size1 roller" name="roll_increase_threat" value="@{increase_threat_action}" type="roll">+
</button>
<button name="act_increase-threat-action" hidden="" type="action">
</button>
<input name="attr_increase_threat_action" type="hidden" title="@{increase_threat_action}"/>
<button class="uppercase compendium-dependent disabled threat-attack roller" name="roll_swarm_compendium_attack" role="heading" aria-level="3" data-i18n="attack" value="@{swarm_compendium_attack_action}" type="roll">
</button>
<button name="act_swarm-compendium-attack-action" hidden="" type="action">
</button>
<input name="attr_swarm_compendium_attack_action" type="hidden" title="@{swarm_compendium_attack_action}"/>
<button class="uppercase compendium-independent threat-attack roller" name="roll_swarm_attack" role="heading" aria-level="3" data-i18n="attack" value="@{swarm_attack_action}" type="roll">
</button>
<button name="act_swarm-attack-action" hidden="" type="action">
</button>
<input name="attr_swarm_attack_action" type="hidden" title="@{swarm_attack_action}"/>
</div><span class="swarm-situation" name="attr_threat_situation" value="threat-situation-0" data-i18n-dynamic="" title="@{threat_situation}"></span>
<div class="swarm-details border-back">
<label class="input-label justify-space-between swarm-threat header"><span data-i18n="swarm threat"></span>
<input class="red-border" name="attr_swarm_threat" readonly="" value="0" type="number" title="@{swarm_threat}"/>
</label>
<label class="input-label justify-space-between swarm-walkers"><span data-i18n="number of walkers"></span>
<input class="number red-border" name="attr_walker_number" type="text" readonly="" value="<5" title="@{walker_number}"/>
</label>
<label class="input-label justify-space-between swarm-size"><span data-i18n="swarm size"></span>
<input class="red-border" name="attr_swarm_size" value="0" type="number" title="@{swarm_size}"/>
</label>
</div>
<input class="display-control--non-zero" name="attr_swarm_show" value="" hidden="" type="hidden" title="@{swarm_show}"/>
<div class="swarm-info controlled-display">
<h5 data-i18n="skills"></h5>
<h5 data-i18n="attack"></h5>
<input name="attr_swarm_skills" value="" type="hidden" title="@{swarm_skills}"/><span name="attr_swarm_skills" value="" title="@{swarm_skills}"></span>
<input name="attr_swarm_attack" value="" type="hidden" title="@{swarm_attack}"/><span name="attr_swarm_attack" value="" title="@{swarm_attack}"></span>
</div>
<div class="brawl-container">
<h3 data-i18n="brawl phases"></h3>
<ol class="brawl-table red-border">
<li class="avoid-break-inside"><span data-i18n="taking cover"></span></li>
<li class="avoid-break-inside"><span data-i18n="ranged combat"></span></li>
<li class="avoid-break-inside"><span data-i18n="close combat"></span></li>
<li class="avoid-break-inside"><span data-i18n="movement"></span></li>
<li class="avoid-break-inside"><span data-i18n="first aid"></span></li>
<li class="avoid-break-inside"><span data-i18n="other"></span></li>
</ol>
</div>
</article>
<article class="tabs__container tabs--walking-dead__container tabs--walking-dead__container--travel-log travel-page" data-container-tab="walking-dead" data-tab="travel-log">
<div class="travelInfo"><img class="logo" src="https://files.d20.io/images/368479329/HgW2WAq5CUmayPMeTQow3A/original.png"/>
<label class="input-label stacked travel-notes"><span class="input-label__text" data-i18n="notes"></span>
<input class="input-label__input" name="attr_Notes" type="text" title="@{Notes}"/>
</label>
</div>
<div class="travel-log border-back-interior">
<h3 class="header spacer"></h3>
<h3 class="header" data-i18n="terrain"></h3>
<h3 class="header" data-i18n="threat"></h3>
<h3 class="header" data-i18n="comments"></h3><span class="border-back-interior" hidden=""></span>
<fieldset class="repeating_travelLog">
<label class="input-label stacked label-coordinates"><span class="input-label__text" data-i18n="coordinates"></span>
<input class="input-label__input" name="attr_coordinates" type="text" title="@{repeating_travelLog_$X_coordinates}"/>
</label>
<label class="input-label stacked label-date"><span class="input-label__text" data-i18n="date"></span>
<input class="input-label__input" name="attr_date" type="text" title="@{repeating_travelLog_$X_date}"/>
</label>
<textarea class="_terrain"> </textarea>
<textarea class="_threat"></textarea>
<section class="head-section dynamic">
<h3 class="header" data-i18n="comments"></h3>
<textarea class="_comments"></textarea>
</section>
</fieldset>
</div>
</article>
<article class="tabs__container tabs--walking-dead__container tabs--walking-dead__container--vehicle vehicle-page" data-container-tab="walking-dead" data-tab="vehicle">
<section class="head-section vehicle-attribute-section">
<div class="header">
<input class="underline" name="attr_character_name" type="text" title="@{character_name}"/>
<div class="sub-header">
<label class="input-label"><span class="input-label__text" data-i18n="driver"></span>
<input class="underline input-label__input" name="attr_driver" type="text" title="@{driver}"/>
</label>
</div>
</div>
<div class="section-content">
<div class="input-label input-label--button">
<button class="capitalize roller" name="roll_maneuverability" data-i18n="maneuverability" value="@{maneuverability_action}" type="roll">
</button>
<input class="underline input-label__input" name="attr_maneuverability" type="number" value="0" title="@{maneuverability}"/>
</div>
<button name="act_maneuverability-action" hidden="" type="action">
</button>
<input name="attr_maneuverability_action" type="hidden" title="@{maneuverability_action}"/>
<label class="input-label"><span class="capitalize input-label__text" data-i18n="damage"></span>
<input class="underline input-label__input" name="attr_damage" type="number" value="0" title="@{damage}"/>
</label>
<div class="input-label">
<label class="input-label"><span class="capitalize input-label__text" data-i18n="hull"></span>
<input class="underline input-label__input" name="attr_hull" type="number" value="0" title="@{hull}"/>
</label><span class="slash">/</span>
<input class="underline" name="attr_hull_max" value="0" type="number" title="@{hull|max}"/>
</div>
<div class="input-label input-label--button">
<button class="capitalize roller" name="roll_armor" data-i18n="armor" value="@{armor_action}" type="roll">
</button>
<input class="underline input-label__input" name="attr_armor" type="number" value="0" title="@{armor}"/>
</div>
<button name="act_armor-action" hidden="" type="action">
</button>
<input name="attr_armor_action" type="hidden" title="@{armor_action}"/>
<div class="flex-box flex-column issues">
<h4 data-i18n="issues"></h4>
<div class="adaptive adaptive--text underlined"><span class="adaptive--text__span" name="attr_character_issues" title="@{character_issues}"></span>
<textarea class="adaptive--text__textarea" name="attr_character_issues" title="@{character_issues}"></textarea>
</div>
</div>
</div>
</section>
<section class="head-section pc-weapon-section vehicle-weapons">
<div class="header column-subgrid grid-span-all">
<h3 data-i18n="weapons"></h3>
<h4 data-i18n="damage"></h4>
<h4 data-i18n="bonus"></h4>
<h4 data-i18n="range"></h4>
</div>
<div class="section-content column-subgrid grid-span-all pc-weapon-content">
<button class="repcontrol-button repcontrol-button--add" name="act_add-weapons" type="action">
</button>
<fieldset class="repeating_weapons"><!-- fieldset prefix: -->
<input class="collapse" name="attr_collapse" value="1" type="checkbox" title="@{repeating_weapons_$X_collapse}"/>
<div class="cardExpanded expanded">
</div>
<button class="collapsed embossed roller" name="roll_roll" value="@{action}" type="roll"><span name="attr_name" title="@{repeating_weapons_$X_name}"></span>
</button>
<button name="act_action" hidden="" type="action">
</button>
<input name="attr_action" type="hidden" title="@{repeating_weapons_$X_action}"/><span class="collapsed summary-details" name="attr_damage" title="@{repeating_weapons_$X_damage}"></span><span class="collapsed summary-details" name="attr_bonus" title="@{repeating_weapons_$X_bonus}"></span><span class="collapsed summary-details" name="attr_range" title="@{repeating_weapons_$X_range}"></span>
<div class="input-label input-label--button expanded">
<button class="icon-roller roller" name="roll_roll" value="@{action}" type="roll">
</button>
<input class="input-label__input" name="attr_name" type="text" title="@{repeating_weapons_$X_name}"/>
</div>
<button name="act_action" hidden="" type="action">
</button>
<input name="attr_action" type="hidden" title="@{repeating_weapons_$X_action}"/>
<input class="red-border expanded summary-details" name="attr_damage" type="number" data-i18n-placeholder="damage" title="@{repeating_weapons_$X_damage}"/>
<input class="red-border expanded summary-details" name="attr_bonus" type="number" data-i18n-placeholder="bonus" title="@{repeating_weapons_$X_bonus}"/>
<input class="red-border expanded summary-details" name="attr_range" type="text" data-i18n-placeholder="range" title="@{repeating_weapons_$X_range}"/>
<div class="expanded grid-span-all weapon-details">
<label class="input-label" style="justify-self: end;"><span class="input-label__text" data-i18n="skill"></span>
<select class="input-label__input" name="attr_skill" title="@{repeating_weapons_$X_skill}">
<option value="close combat" data-i18n="close combat" selected="">
</option>
<option value="endure" data-i18n="endure">
</option>
<option value="force" data-i18n="force">
</option>
<option value="mobility" data-i18n="mobility">
</option>
<option value="ranged combat" data-i18n="ranged combat">
</option>
<option value="stealth" data-i18n="stealth">
</option>
<option value="scout" data-i18n="scout">
</option>
<option value="survival" data-i18n="survival">
</option>
<option value="tech" data-i18n="tech">
</option>
<option value="leadership" data-i18n="leadership">
</option>
<option value="manipulation" data-i18n="manipulation">
</option>
<option value="medicine" data-i18n="medicine">
</option>
</select>
</label>
<label class="input-label" style="justify-self:end;"><span class="input-label__text" data-i18n="user"></span>
<select class="crew-select input-label__input" name="attr_user" triggeredFuncs='["dynamicPopulate"]' title="@{repeating_weapons_$X_user}">
<option value="" data-i18n="none" selected="">
</option>
</select>
</label>
<label class="input-label stacked grid-span-all"><span data-i18n="description"></span>
<div class="adaptive adaptive--text"><span class="adaptive--text__span" name="attr_description" title="@{repeating_weapons_$X_description}"></span>
<textarea class="adaptive--text__textarea" name="attr_description" title="@{repeating_weapons_$X_description}"></textarea>
</div>
</label>
</div>
</fieldset>
</div>
</section>
<section class="head-section vehicle-crew">
<div class="header flex-box justify-center">
<h3 data-i18n="crew"></h3>
</div>
<div class="section-content">
<button class="repcontrol-button repcontrol-button--add" name="act_add-crew" type="action">
</button>
<fieldset class="repeating_crew">
<input class="embossed" name="attr_name" type="text" title="@{repeating_crew_$X_name}"/>
</fieldset>
</div>
</section>
</article>
<article class="tabs__container tabs--walking-dead__container tabs--walking-dead__container--settings setting-page" data-container-tab="walking-dead" data-tab="settings">
<label class="input-label justify-space-between"><span data-i18n="whisper gm"></span>
<select class="red-border" name="attr_whisper" title="@{whisper}">
<option data-i18n="never" selected="" value="">
</option>
<option data-i18n="always" value="/w gm ">
</option>
</select>
</label>
<label class="input-label justify-space-between red-border"><span data-i18n="sheet type"></span>
<select class="red-border" name="attr_sheet_type" title="@{sheet_type}">
<option value="character" data-i18n="character" selected="">
</option>
<option value="single player" data-i18n="single player">
</option>
<option value="npc" data-i18n="npc">
</option>
<option value="gm" data-i18n="gm">
</option>
<option value="faction" data-i18n="faction">
</option>
<option value="haven" data-i18n="haven">
</option>
<option value="travel log" data-i18n="travel log">
</option>
<option value="vehicle" data-i18n="vehicle">
</option>
</select>
</label>
</article>
</div>
</div>
</div>
<input name="attr_template_start" value="@{whisper}&{template:walking_dead} {{character_name=@{character_name}}} {{character_id=@{character_id}}}" type="hidden" title="@{template_start}"/>
<rolltemplate class="sheet-rolltemplate-walking_dead">
<div class="template walking_dead">
<section class="head-section">
<div class="header template-header">{{#title}}
<h3>{{title}}</h3>{{/title}}{{#character_name}}{{#character_id}}
<h4 class="character_name">[{{character_name}}](http://journal.roll20.net/character/{{character_id}})</h4>{{/character_id}}{{^character_id}}
<h4 class="character_name">{{character_name}}</h4>{{/character_id}}{{/character_name}}
</div>
<div class="section-content template-content">{{#successes}}
<div class="results">
<h5 data-i18n="successes"></h5>{{computed::successes}}{{#^rollTotal() computed::messed_up 0}}<span data-i18n="you messed up!"></span>{{/^rollTotal() computed::messed_up 0}}
</div>{{/successes}}{{#base_1}}
<div class="results dice">
<div class="base">{{base_1}}{{base_2}}{{base_3}}{{base_4}}{{base_5}}{{base_6}}{{base_7}}{{base_8}}{{base_9}}{{base_10}}{{base_11}}{{base_12}}{{base_13}}{{base_14}}{{base_15}}{{base_16}}{{base_17}}{{base_18}}{{base_19}}{{base_20}}{{base_21}}{{base_22}}{{base_23}}{{base_24}}{{base_25}}{{base_26}}{{base_27}}{{base_28}}{{base_29}}
</div>
<div class="stress">{{stress_1}}{{stress_2}}{{stress_3}}{{stress_4}}{{stress_5}}{{stress_6}}{{stress_7}}{{stress_8}}{{stress_9}}{{stress_10}}{{stress_11}}{{stress_12}}{{stress_13}}{{stress_14}}{{stress_15}}{{stress_16}}{{stress_17}}{{stress_18}}{{stress_19}}{{stress_20}}{{stress_21}}{{stress_22}}{{stress_23}}{{stress_24}}{{stress_25}}{{stress_26}}{{stress_27}}{{stress_28}}{{stress_29}}
</div>{{#no_dice}}
<h3 data-i18n="no dice to roll"></h3>{{/no_dice}}
</div>{{/base_1}}{{^base_1}}{{#stress_1}}
<div class="results dice">
<div class="base">{{base_1}}{{base_2}}{{base_3}}{{base_4}}{{base_5}}{{base_6}}{{base_7}}{{base_8}}{{base_9}}{{base_10}}{{base_11}}{{base_12}}{{base_13}}{{base_14}}{{base_15}}{{base_16}}{{base_17}}{{base_18}}{{base_19}}{{base_20}}{{base_21}}{{base_22}}{{base_23}}{{base_24}}{{base_25}}{{base_26}}{{base_27}}{{base_28}}{{base_29}}
</div>
<div class="stress">{{stress_1}}{{stress_2}}{{stress_3}}{{stress_4}}{{stress_5}}{{stress_6}}{{stress_7}}{{stress_8}}{{stress_9}}{{stress_10}}{{stress_11}}{{stress_12}}{{stress_13}}{{stress_14}}{{stress_15}}{{stress_16}}{{stress_17}}{{stress_18}}{{stress_19}}{{stress_20}}{{stress_21}}{{stress_22}}{{stress_23}}{{stress_24}}{{stress_25}}{{stress_26}}{{stress_27}}{{stress_28}}{{stress_29}}
</div>{{#no_dice}}
<h3 data-i18n="no dice to roll"></h3>{{/no_dice}}
</div>{{/stress_1}}{{/base_1}}{{#damage}}
<div class="results">
<h5 data-i18n="base damage"></h5><span>{{damage}}</span>
</div>{{/damage}}{{#roll}}
<div class="results">{{#^rollTotal() computed::roll_label 0}}
<h5 class="computed-label computed-control">{{computed::roll_label}}</h5>{{/^rollTotal() computed::roll_label 0}}{{#roll_label}}
<h5 class="hide-if-computed">{{roll_label}}</h5>{{/roll_label}}{{^roll_label}}
<h5 data-i18n="roll"></h5>{{/roll_label}}<span>{{roll}}</span>
</div>{{/roll}}{{#range}}
<div class="results">
<h5 data-i18n="range"></h5><span>{{range}}</span>
</div>{{/range}}{{#comment}}
<div class="results plain textarea"><span>{{comment}}</span></div>{{/comment}}{{#description}}
<h5 data-i18n="description"></h5>
<div class="results plain textarea"><span>{{description}}</span></div>{{/description}}{{#character_name}}{{#^rollTotal() computed::push_through 0}}{{#base_1}}
<div class="push-container flex-box justify-center">{{#push_label}}[{{push_label}}](~{{character_name}}|push||{{computed::push_through}}){{/push_label}}{{^push_label}}[push](~{{character_name}}|push||{{computed::push_through}}){{/push_label}}
</div>{{/base_1}}{{^base_1}}{{#stress_1}}
<div class="push-container flex-box justify-center">{{#push_label}}[{{push_label}}](~{{character_name}}|push||{{computed::push_through}}){{/push_label}}{{^push_label}}[push](~{{character_name}}|push||{{computed::push_through}}){{/push_label}}
</div>{{/stress_1}}{{/base_1}}{{/^rollTotal() computed::push_through 0}}{{/character_name}}
</div>
</section>
</div>
</rolltemplate>
<script type="text/worker">//# sourceURL=walking_dead.js
const k = (function(){
const kFuncs = {};
const cascades = {"attr_character_name":{"name":"character_name","type":"text","defaultValue":"","affects":[],"triggeredFuncs":["setActionCalls","locateNPC","claimHaven"],"listenerFunc":"accessSheet","listener":"change:character_name"},"act_k-network-call":{"name":"k-network-call","type":"action","triggeredFuncs":["kReceive"],"affects":[],"addFuncs":[],"listener":"clicked:k-network-call","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_character_id":{"name":"character_id","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:character_id","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_script_character_name":{"name":"script_character_name","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:script_character_name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_sheet_version":{"name":"sheet_version","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:sheet_version","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_push":{"name":"push","type":"action","triggeredFuncs":["pushRoll"],"affects":[],"addFuncs":[],"listener":"clicked:push","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_drop_name":{"name":"drop_name","type":"hidden","triggeredFuncs":["handleCompendiumDrop"],"affects":[],"addFuncs":[],"listener":"change:drop_name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_drop_data":{"name":"drop_data","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:drop_data","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_walking_dead_tab":{"name":"walking_dead_tab","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:walking_dead_tab","listenerFunc":"accessSheet","defaultValue":"nav-tabs-walking-dead--settings","calculation":"","initialFunc":"","formula":""},"act_nav-tabs-walking-dead--character":{"name":"nav-tabs-walking-dead--character","type":"action","triggeredFuncs":["kSwitchTab"],"affects":[],"addFuncs":[],"listener":"clicked:nav-tabs-walking-dead--character","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_nav-tabs-walking-dead--npc":{"name":"nav-tabs-walking-dead--npc","type":"action","triggeredFuncs":["kSwitchTab"],"affects":[],"addFuncs":[],"listener":"clicked:nav-tabs-walking-dead--npc","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_nav-tabs-walking-dead--challenge":{"name":"nav-tabs-walking-dead--challenge","type":"action","triggeredFuncs":["kSwitchTab"],"affects":[],"addFuncs":[],"listener":"clicked:nav-tabs-walking-dead--challenge","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_nav-tabs-walking-dead--haven":{"name":"nav-tabs-walking-dead--haven","type":"action","triggeredFuncs":["kSwitchTab"],"affects":[],"addFuncs":[],"listener":"clicked:nav-tabs-walking-dead--haven","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_nav-tabs-walking-dead--faction":{"name":"nav-tabs-walking-dead--faction","type":"action","triggeredFuncs":["kSwitchTab"],"affects":[],"addFuncs":[],"listener":"clicked:nav-tabs-walking-dead--faction","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_nav-tabs-walking-dead--gm":{"name":"nav-tabs-walking-dead--gm","type":"action","triggeredFuncs":["kSwitchTab"],"affects":[],"addFuncs":[],"listener":"clicked:nav-tabs-walking-dead--gm","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_nav-tabs-walking-dead--travel-log":{"name":"nav-tabs-walking-dead--travel-log","type":"action","triggeredFuncs":["kSwitchTab"],"affects":[],"addFuncs":[],"listener":"clicked:nav-tabs-walking-dead--travel-log","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_nav-tabs-walking-dead--vehicle":{"name":"nav-tabs-walking-dead--vehicle","type":"action","triggeredFuncs":["kSwitchTab"],"affects":[],"addFuncs":[],"listener":"clicked:nav-tabs-walking-dead--vehicle","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_nav-tabs-walking-dead--settings":{"name":"nav-tabs-walking-dead--settings","type":"action","triggeredFuncs":["kSwitchTab"],"affects":[],"addFuncs":[],"listener":"clicked:nav-tabs-walking-dead--settings","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_archetype":{"name":"archetype","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:archetype","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_character_description":{"name":"character_description","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:character_description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_pc_anchor":{"name":"pc_anchor","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:pc_anchor","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_npc_anchor":{"name":"npc_anchor","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:npc_anchor","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_character_notes":{"name":"character_notes","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:character_notes","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_drive":{"name":"drive","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:drive","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_drive_used":{"name":"drive_used","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:drive_used","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_character_issues":{"name":"character_issues","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:character_issues","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_stress":{"name":"stress","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:stress","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_experience":{"name":"experience","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:experience","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_strength-action":{"name":"strength-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:strength-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_strength_action":{"name":"strength_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:strength_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_strength":{"name":"strength","type":"number","triggeredFuncs":[],"affects":["encumbrance_max"],"addFuncs":[],"listener":"change:strength","listenerFunc":"accessSheet","defaultValue":2,"calculation":"","initialFunc":"","formula":""},"act_close-combat-action":{"name":"close-combat-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:close-combat-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"","ability":"strength"},"attr_close_combat_action":{"name":"close_combat_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:close_combat_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_close_combat":{"name":"close_combat","type":"number","triggeredFuncs":["locateNPC"],"affects":["npc_is_untrained","npc_is_trained","npc_is_expert","npc_is_master","npc is untrained","npc is trained","npc is expert","npc is master"],"addFuncs":[],"listener":"change:close_combat","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_endure-action":{"name":"endure-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:endure-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"","ability":"strength"},"attr_endure_action":{"name":"endure_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:endure_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_endure":{"name":"endure","type":"number","triggeredFuncs":["locateNPC"],"affects":["npc_is_untrained","npc_is_trained","npc_is_expert","npc_is_master","npc is untrained","npc is trained","npc is expert","npc is master"],"addFuncs":[],"listener":"change:endure","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_force-action":{"name":"force-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:force-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"","ability":"strength"},"attr_force_action":{"name":"force_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:force_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_force":{"name":"force","type":"number","triggeredFuncs":["locateNPC"],"affects":["npc_is_untrained","npc_is_trained","npc_is_expert","npc_is_master","npc is untrained","npc is trained","npc is expert","npc is master"],"addFuncs":[],"listener":"change:force","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_agility-action":{"name":"agility-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:agility-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_agility_action":{"name":"agility_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:agility_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_agility":{"name":"agility","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:agility","listenerFunc":"accessSheet","defaultValue":2,"calculation":"","initialFunc":"","formula":""},"act_mobility-action":{"name":"mobility-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:mobility-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"","ability":"agility"},"attr_mobility_action":{"name":"mobility_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:mobility_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_mobility":{"name":"mobility","type":"number","triggeredFuncs":["locateNPC"],"affects":["npc_is_untrained","npc_is_trained","npc_is_expert","npc_is_master","npc is untrained","npc is trained","npc is expert","npc is master"],"addFuncs":[],"listener":"change:mobility","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_ranged-combat-action":{"name":"ranged-combat-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:ranged-combat-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"","ability":"agility"},"attr_ranged_combat_action":{"name":"ranged_combat_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:ranged_combat_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_ranged_combat":{"name":"ranged_combat","type":"number","triggeredFuncs":["locateNPC"],"affects":["npc_is_untrained","npc_is_trained","npc_is_expert","npc_is_master","npc is untrained","npc is trained","npc is expert","npc is master"],"addFuncs":[],"listener":"change:ranged_combat","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_stealth-action":{"name":"stealth-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:stealth-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"","ability":"agility"},"attr_stealth_action":{"name":"stealth_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:stealth_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_stealth":{"name":"stealth","type":"number","triggeredFuncs":["locateNPC"],"affects":["npc_is_untrained","npc_is_trained","npc_is_expert","npc_is_master","npc is untrained","npc is trained","npc is expert","npc is master"],"addFuncs":[],"listener":"change:stealth","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_wits-action":{"name":"wits-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:wits-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_wits_action":{"name":"wits_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:wits_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_wits":{"name":"wits","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:wits","listenerFunc":"accessSheet","defaultValue":2,"calculation":"","initialFunc":"","formula":""},"act_scout-action":{"name":"scout-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:scout-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"","ability":"wits"},"attr_scout_action":{"name":"scout_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:scout_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_scout":{"name":"scout","type":"number","triggeredFuncs":["locateNPC"],"affects":["npc_is_untrained","npc_is_trained","npc_is_expert","npc_is_master","npc is untrained","npc is trained","npc is expert","npc is master"],"addFuncs":[],"listener":"change:scout","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_survival-action":{"name":"survival-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:survival-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"","ability":"wits"},"attr_survival_action":{"name":"survival_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:survival_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_survival":{"name":"survival","type":"number","triggeredFuncs":["locateNPC"],"affects":["npc_is_untrained","npc_is_trained","npc_is_expert","npc_is_master","npc is untrained","npc is trained","npc is expert","npc is master"],"addFuncs":[],"listener":"change:survival","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_tech-action":{"name":"tech-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:tech-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"","ability":"wits"},"attr_tech_action":{"name":"tech_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:tech_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_tech":{"name":"tech","type":"number","triggeredFuncs":["locateNPC"],"affects":["npc_is_untrained","npc_is_trained","npc_is_expert","npc_is_master","npc is untrained","npc is trained","npc is expert","npc is master"],"addFuncs":[],"listener":"change:tech","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_empathy-action":{"name":"empathy-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:empathy-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_empathy_action":{"name":"empathy_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:empathy_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_empathy":{"name":"empathy","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:empathy","listenerFunc":"accessSheet","defaultValue":2,"calculation":"","initialFunc":"","formula":""},"act_leadership-action":{"name":"leadership-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:leadership-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"","ability":"empathy"},"attr_leadership_action":{"name":"leadership_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:leadership_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_leadership":{"name":"leadership","type":"number","triggeredFuncs":["locateNPC"],"affects":["npc_is_untrained","npc_is_trained","npc_is_expert","npc_is_master","npc is untrained","npc is trained","npc is expert","npc is master"],"addFuncs":[],"listener":"change:leadership","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_manipulation-action":{"name":"manipulation-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:manipulation-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"","ability":"empathy"},"attr_manipulation_action":{"name":"manipulation_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:manipulation_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_manipulation":{"name":"manipulation","type":"number","triggeredFuncs":["locateNPC"],"affects":["npc_is_untrained","npc_is_trained","npc_is_expert","npc_is_master","npc is untrained","npc is trained","npc is expert","npc is master"],"addFuncs":[],"listener":"change:manipulation","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_medicine-action":{"name":"medicine-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:medicine-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"","ability":"empathy"},"attr_medicine_action":{"name":"medicine_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:medicine_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_medicine":{"name":"medicine","type":"number","triggeredFuncs":["locateNPC"],"affects":["npc_is_untrained","npc_is_trained","npc_is_expert","npc_is_master","npc is untrained","npc is trained","npc is expert","npc is master"],"addFuncs":[],"listener":"change:medicine","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_armor_name":{"name":"armor_name","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:armor_name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_armor_protection":{"name":"armor_protection","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:armor_protection","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_armor_penalty":{"name":"armor_penalty","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:armor_penalty","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_add-weapons":{"name":"add-weapons","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:add-weapons","listenerFunc":"addItem","defaultValue":"","calculation":"","initialFunc":"","formula":""},"fieldset_repeating_weapons":{"name":"repeating_weapons","type":"fieldset","triggeredFuncs":[],"affects":["encumbrance"],"addFuncs":["storeRow"],"listener":"remove:repeating_weapons","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_weapons_$x_collapse":{"name":"repeating_weapons_$x_collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_weapons:collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_weapons_$x_name":{"name":"repeating_weapons_$x_name","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_weapons:name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_repeating_weapons_$x_action":{"name":"repeating_weapons_$x_action","type":"action","triggeredFuncs":["rollWeapon"],"affects":[],"addFuncs":[],"listener":"clicked:repeating_weapons:action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_weapons_$x_action":{"name":"repeating_weapons_$x_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_weapons:action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_weapons_$x_damage":{"name":"repeating_weapons_$x_damage","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_weapons:damage","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_weapons_$x_bonus":{"name":"repeating_weapons_$x_bonus","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_weapons:bonus","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_weapons_$x_range":{"name":"repeating_weapons_$x_range","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_weapons:range","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_weapons_$x_skill":{"name":"repeating_weapons_$x_skill","type":"select","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_weapons:skill","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_weapons_$x_slots":{"name":"repeating_weapons_$x_slots","type":"text","triggeredFuncs":[],"affects":["encumbrance"],"addFuncs":[],"listener":"change:repeating_weapons:slots","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_weapons_$x_description":{"name":"repeating_weapons_$x_description","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_weapons:description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_health":{"name":"health","type":"radio","triggeredFuncs":["applyStress"],"affects":[],"addFuncs":[],"listener":"change:health","listenerFunc":"accessSheet","defaultValue":3,"calculation":"","initialFunc":"","formula":""},"act_add-injury":{"name":"add-injury","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:add-injury","listenerFunc":"addItem","defaultValue":"","calculation":"","initialFunc":"","formula":""},"fieldset_repeating_injury":{"name":"repeating_injury","type":"fieldset","triggeredFuncs":[],"affects":[],"addFuncs":["storeRow"],"listener":"remove:repeating_injury","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_injury_$x_collapse":{"name":"repeating_injury_$x_collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_injury:collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_injury_$x_name":{"name":"repeating_injury_$x_name","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_injury:name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_injury_$x_penalty":{"name":"repeating_injury_$x_penalty","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_injury:penalty","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_injury_$x_limit":{"name":"repeating_injury_$x_limit","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_injury:limit","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_injury_$x_recovery":{"name":"repeating_injury_$x_recovery","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_injury:recovery","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_critical-injuries-action":{"name":"critical-injuries-action","type":"action","triggeredFuncs":["rollCriticalTable"],"affects":[],"addFuncs":[],"listener":"clicked:critical-injuries-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_critical_injuries_action":{"name":"critical_injuries_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:critical_injuries_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_talent_session":{"name":"talent_session","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:talent_session","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"saveTalent","formula":""},"attr_talent_name":{"name":"talent_name","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:talent_name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"saveTalent","formula":""},"attr_talent_description":{"name":"talent_description","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:talent_description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"saveTalent","formula":""},"attr_talent_used":{"name":"talent_used","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:talent_used","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"saveTalent","formula":""},"attr_talent_row_id":{"name":"talent_row_id","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:talent_row_id","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_add-talent":{"name":"add-talent","type":"action","triggeredFuncs":["createTalent"],"affects":[],"addFuncs":[],"listener":"clicked:add-talent","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"fieldset_repeating_talents":{"name":"repeating_talents","type":"fieldset","triggeredFuncs":["removeTalent"],"affects":[],"addFuncs":[],"listener":"remove:repeating_talents","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_talents_$x_is_selected":{"name":"repeating_talents_$x_is_selected","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_talents:is_selected","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_talents_$x_display":{"name":"repeating_talents_$x_display","type":"action","triggeredFuncs":["displayTalent"],"affects":[],"addFuncs":[],"listener":"clicked:repeating_talents:display","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_talents_$x_name":{"name":"repeating_talents_$x_name","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_talents:name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_talents_$x_session":{"name":"repeating_talents_$x_session","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_talents:session","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_talents_$x_description":{"name":"repeating_talents_$x_description","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_talents:description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_talents_$x_used":{"name":"repeating_talents_$x_used","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_talents:used","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_encumbrance":{"name":"encumbrance","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:encumbrance","listenerFunc":"accessSheet","defaultValue":0,"calculation":"calcEncumbrance","initialFunc":"","formula":""},"attr_encumbrance_max":{"name":"encumbrance_max","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:encumbrance_max","listenerFunc":"accessSheet","defaultValue":2,"calculation":"calcEncumbranceMax","initialFunc":"","formula":""},"act_add-gear":{"name":"add-gear","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:add-gear","listenerFunc":"addItem","defaultValue":"","calculation":"","initialFunc":"","formula":""},"fieldset_repeating_gear":{"name":"repeating_gear","type":"fieldset","triggeredFuncs":[],"affects":["encumbrance"],"addFuncs":["storeRow"],"listener":"remove:repeating_gear","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_gear_$x_equipped":{"name":"repeating_gear_$x_equipped","type":"checkbox","triggeredFuncs":["equipItem"],"affects":["encumbrance"],"addFuncs":[],"listener":"change:repeating_gear:equipped","listenerFunc":"accessSheet","defaultValue":1,"calculation":"","initialFunc":"","formula":""},"attr_repeating_gear_$x_collapse":{"name":"repeating_gear_$x_collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_gear:collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_gear_$x_quantity":{"name":"repeating_gear_$x_quantity","type":"span","triggeredFuncs":[],"affects":["encumbrance"],"addFuncs":[],"listener":"change:repeating_gear:quantity","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_gear_$x_slots":{"name":"repeating_gear_$x_slots","type":"span","triggeredFuncs":[],"affects":["encumbrance"],"addFuncs":[],"listener":"change:repeating_gear:slots","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_gear_$x_name":{"name":"repeating_gear_$x_name","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_gear:name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_gear_$x_bonus":{"name":"repeating_gear_$x_bonus","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_gear:bonus","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_gear_$x_affects":{"name":"repeating_gear_$x_affects","type":"select","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_gear:affects","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_gear_$x_description":{"name":"repeating_gear_$x_description","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_gear:description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_gear_$x_location":{"name":"repeating_gear_$x_location","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_gear:location","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_add-stored-gear":{"name":"add-stored-gear","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:add-stored-gear","listenerFunc":"addItem","defaultValue":"","calculation":"","initialFunc":"","formula":""},"fieldset_repeating_stored-gear":{"name":"repeating_stored-gear","type":"fieldset","triggeredFuncs":[],"affects":[],"addFuncs":["storeRow"],"listener":"remove:repeating_stored-gear","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_stored-gear_$x_equipped":{"name":"repeating_stored-gear_$x_equipped","type":"checkbox","triggeredFuncs":["equipItem"],"affects":["encumbrance"],"addFuncs":[],"listener":"change:repeating_stored-gear:equipped","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_stored-gear_$x_collapse":{"name":"repeating_stored-gear_$x_collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_stored-gear:collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_stored-gear_$x_quantity":{"name":"repeating_stored-gear_$x_quantity","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_stored-gear:quantity","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_stored-gear_$x_slots":{"name":"repeating_stored-gear_$x_slots","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_stored-gear:slots","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_stored-gear_$x_name":{"name":"repeating_stored-gear_$x_name","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_stored-gear:name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_stored-gear_$x_location":{"name":"repeating_stored-gear_$x_location","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_stored-gear:location","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_stored-gear_$x_bonus":{"name":"repeating_stored-gear_$x_bonus","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_stored-gear:bonus","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_stored-gear_$x_affects":{"name":"repeating_stored-gear_$x_affects","type":"select","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_stored-gear:affects","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_stored-gear_$x_description":{"name":"repeating_stored-gear_$x_description","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_stored-gear:description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_npc_collapse":{"name":"npc_collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:npc_collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_npc_descriptor":{"name":"npc_descriptor","type":"text","triggeredFuncs":["locateNPC"],"affects":[],"addFuncs":[],"listener":"change:npc_descriptor","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_npc_faction":{"name":"npc_faction","type":"text","triggeredFuncs":["locateNPC"],"affects":[],"addFuncs":[],"listener":"change:npc_faction","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_npc_haven":{"name":"npc_haven","type":"text","triggeredFuncs":["locateNPC"],"affects":[],"addFuncs":[],"listener":"change:npc_haven","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_npc-untrained-skills-action":{"name":"npc-untrained-skills-action","type":"action","triggeredFuncs":["rollUntrained"],"affects":[],"addFuncs":[],"listener":"clicked:npc-untrained-skills-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_npc_untrained_skills_action":{"name":"npc_untrained_skills_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:npc_untrained_skills_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_npc_is_untrained":{"name":"npc_is_untrained","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:npc_is_untrained","listenerFunc":"accessSheet","defaultValue":1,"calculation":"calcNPCTraining","initialFunc":"","formula":"","dice":4},"attr_npc_is_trained":{"name":"npc_is_trained","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:npc_is_trained","listenerFunc":"accessSheet","defaultValue":0,"calculation":"calcNPCTraining","initialFunc":"","formula":"","dice":5},"attr_npc_is_expert":{"name":"npc_is_expert","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:npc_is_expert","listenerFunc":"accessSheet","defaultValue":0,"calculation":"calcNPCTraining","initialFunc":"","formula":"","dice":8},"attr_npc_is_master":{"name":"npc_is_master","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:npc_is_master","listenerFunc":"accessSheet","defaultValue":0,"calculation":"calcNPCTraining","initialFunc":"","formula":"","dice":10},"act_add-issues":{"name":"add-issues","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:add-issues","listenerFunc":"addItem","defaultValue":"","calculation":"","initialFunc":"","formula":""},"fieldset_repeating_issues":{"name":"repeating_issues","type":"fieldset","triggeredFuncs":[],"affects":[],"addFuncs":["storeRow"],"listener":"remove:repeating_issues","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_issues_$x_collapse":{"name":"repeating_issues_$x_collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_issues:collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_issues_$x_name":{"name":"repeating_issues_$x_name","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_issues:name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_issues_$x_source":{"name":"repeating_issues_$x_source","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_issues:source","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_issues_$x_description":{"name":"repeating_issues_$x_description","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_issues:description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_add-npcs":{"name":"add-npcs","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:add-npcs","listenerFunc":"addItem","defaultValue":"","calculation":"","initialFunc":"","formula":""},"fieldset_repeating_npcs":{"name":"repeating_npcs","type":"fieldset","triggeredFuncs":["exileNPC"],"affects":[],"addFuncs":["storeRow"],"listener":"remove:repeating_npcs","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_collapse":{"name":"repeating_npcs_$x_collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_name":{"name":"repeating_npcs_$x_name","type":"span","triggeredFuncs":["syncConnectedNPC"],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_descriptor":{"name":"repeating_npcs_$x_descriptor","type":"span","triggeredFuncs":["syncConnectedNPC"],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:descriptor","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_npc_is_untrained":{"name":"repeating_npcs_$x_npc_is_untrained","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:npc_is_untrained","listenerFunc":"accessSheet","defaultValue":1,"calculation":"calcNPCTraining","initialFunc":"","formula":"","dice":4},"act_repeating_npcs_$x_npc-untrained-skills-action":{"name":"repeating_npcs_$x_npc-untrained-skills-action","type":"action","triggeredFuncs":["rollUntrained"],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:npc-untrained-skills-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_npc_untrained_skills_action":{"name":"repeating_npcs_$x_npc_untrained_skills_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:npc_untrained_skills_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_npc_is_trained":{"name":"repeating_npcs_$x_npc_is_trained","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:npc_is_trained","listenerFunc":"accessSheet","defaultValue":0,"calculation":"calcNPCTraining","initialFunc":"","formula":"","dice":5},"attr_repeating_npcs_$x_close_combat":{"name":"repeating_npcs_$x_close_combat","type":"checkbox","triggeredFuncs":["syncConnectedNPC"],"affects":["repeating_npcs_$x_npc_is_untrained","repeating_npcs_$x_npc_is_trained","repeating_npcs_$x_npc_is_expert","repeating_npcs_$x_npc_is_master","repeating npcs $X npc is untrained","repeating npcs $X npc is trained","repeating npcs $X npc is expert","repeating npcs $X npc is master"],"addFuncs":[],"listener":"change:repeating_npcs:close_combat","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_close-combat-action":{"name":"repeating_npcs_$x_close-combat-action","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:close-combat-action","listenerFunc":"initiateRoll","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_close_combat_action":{"name":"repeating_npcs_$x_close_combat_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:close_combat_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_endure":{"name":"repeating_npcs_$x_endure","type":"checkbox","triggeredFuncs":["syncConnectedNPC"],"affects":["repeating_npcs_$x_npc_is_untrained","repeating_npcs_$x_npc_is_trained","repeating_npcs_$x_npc_is_expert","repeating_npcs_$x_npc_is_master","repeating npcs $X npc is untrained","repeating npcs $X npc is trained","repeating npcs $X npc is expert","repeating npcs $X npc is master"],"addFuncs":[],"listener":"change:repeating_npcs:endure","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_endure-action":{"name":"repeating_npcs_$x_endure-action","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:endure-action","listenerFunc":"initiateRoll","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_endure_action":{"name":"repeating_npcs_$x_endure_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:endure_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_force":{"name":"repeating_npcs_$x_force","type":"checkbox","triggeredFuncs":["syncConnectedNPC"],"affects":["repeating_npcs_$x_npc_is_untrained","repeating_npcs_$x_npc_is_trained","repeating_npcs_$x_npc_is_expert","repeating_npcs_$x_npc_is_master","repeating npcs $X npc is untrained","repeating npcs $X npc is trained","repeating npcs $X npc is expert","repeating npcs $X npc is master"],"addFuncs":[],"listener":"change:repeating_npcs:force","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_force-action":{"name":"repeating_npcs_$x_force-action","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:force-action","listenerFunc":"initiateRoll","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_force_action":{"name":"repeating_npcs_$x_force_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:force_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_mobility":{"name":"repeating_npcs_$x_mobility","type":"checkbox","triggeredFuncs":["syncConnectedNPC"],"affects":["repeating_npcs_$x_npc_is_untrained","repeating_npcs_$x_npc_is_trained","repeating_npcs_$x_npc_is_expert","repeating_npcs_$x_npc_is_master","repeating npcs $X npc is untrained","repeating npcs $X npc is trained","repeating npcs $X npc is expert","repeating npcs $X npc is master"],"addFuncs":[],"listener":"change:repeating_npcs:mobility","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_mobility-action":{"name":"repeating_npcs_$x_mobility-action","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:mobility-action","listenerFunc":"initiateRoll","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_mobility_action":{"name":"repeating_npcs_$x_mobility_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:mobility_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_ranged_combat":{"name":"repeating_npcs_$x_ranged_combat","type":"checkbox","triggeredFuncs":["syncConnectedNPC"],"affects":["repeating_npcs_$x_npc_is_untrained","repeating_npcs_$x_npc_is_trained","repeating_npcs_$x_npc_is_expert","repeating_npcs_$x_npc_is_master","repeating npcs $X npc is untrained","repeating npcs $X npc is trained","repeating npcs $X npc is expert","repeating npcs $X npc is master"],"addFuncs":[],"listener":"change:repeating_npcs:ranged_combat","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_ranged-combat-action":{"name":"repeating_npcs_$x_ranged-combat-action","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:ranged-combat-action","listenerFunc":"initiateRoll","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_ranged_combat_action":{"name":"repeating_npcs_$x_ranged_combat_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:ranged_combat_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_stealth":{"name":"repeating_npcs_$x_stealth","type":"checkbox","triggeredFuncs":["syncConnectedNPC"],"affects":["repeating_npcs_$x_npc_is_untrained","repeating_npcs_$x_npc_is_trained","repeating_npcs_$x_npc_is_expert","repeating_npcs_$x_npc_is_master","repeating npcs $X npc is untrained","repeating npcs $X npc is trained","repeating npcs $X npc is expert","repeating npcs $X npc is master"],"addFuncs":[],"listener":"change:repeating_npcs:stealth","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_stealth-action":{"name":"repeating_npcs_$x_stealth-action","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:stealth-action","listenerFunc":"initiateRoll","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_stealth_action":{"name":"repeating_npcs_$x_stealth_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:stealth_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_scout":{"name":"repeating_npcs_$x_scout","type":"checkbox","triggeredFuncs":["syncConnectedNPC"],"affects":["repeating_npcs_$x_npc_is_untrained","repeating_npcs_$x_npc_is_trained","repeating_npcs_$x_npc_is_expert","repeating_npcs_$x_npc_is_master","repeating npcs $X npc is untrained","repeating npcs $X npc is trained","repeating npcs $X npc is expert","repeating npcs $X npc is master"],"addFuncs":[],"listener":"change:repeating_npcs:scout","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_scout-action":{"name":"repeating_npcs_$x_scout-action","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:scout-action","listenerFunc":"initiateRoll","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_scout_action":{"name":"repeating_npcs_$x_scout_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:scout_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_survival":{"name":"repeating_npcs_$x_survival","type":"checkbox","triggeredFuncs":["syncConnectedNPC"],"affects":["repeating_npcs_$x_npc_is_untrained","repeating_npcs_$x_npc_is_trained","repeating_npcs_$x_npc_is_expert","repeating_npcs_$x_npc_is_master","repeating npcs $X npc is untrained","repeating npcs $X npc is trained","repeating npcs $X npc is expert","repeating npcs $X npc is master"],"addFuncs":[],"listener":"change:repeating_npcs:survival","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_survival-action":{"name":"repeating_npcs_$x_survival-action","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:survival-action","listenerFunc":"initiateRoll","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_survival_action":{"name":"repeating_npcs_$x_survival_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:survival_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_tech":{"name":"repeating_npcs_$x_tech","type":"checkbox","triggeredFuncs":["syncConnectedNPC"],"affects":["repeating_npcs_$x_npc_is_untrained","repeating_npcs_$x_npc_is_trained","repeating_npcs_$x_npc_is_expert","repeating_npcs_$x_npc_is_master","repeating npcs $X npc is untrained","repeating npcs $X npc is trained","repeating npcs $X npc is expert","repeating npcs $X npc is master"],"addFuncs":[],"listener":"change:repeating_npcs:tech","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_tech-action":{"name":"repeating_npcs_$x_tech-action","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:tech-action","listenerFunc":"initiateRoll","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_tech_action":{"name":"repeating_npcs_$x_tech_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:tech_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_leadership":{"name":"repeating_npcs_$x_leadership","type":"checkbox","triggeredFuncs":["syncConnectedNPC"],"affects":["repeating_npcs_$x_npc_is_untrained","repeating_npcs_$x_npc_is_trained","repeating_npcs_$x_npc_is_expert","repeating_npcs_$x_npc_is_master","repeating npcs $X npc is untrained","repeating npcs $X npc is trained","repeating npcs $X npc is expert","repeating npcs $X npc is master"],"addFuncs":[],"listener":"change:repeating_npcs:leadership","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_leadership-action":{"name":"repeating_npcs_$x_leadership-action","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:leadership-action","listenerFunc":"initiateRoll","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_leadership_action":{"name":"repeating_npcs_$x_leadership_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:leadership_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_manipulation":{"name":"repeating_npcs_$x_manipulation","type":"checkbox","triggeredFuncs":["syncConnectedNPC"],"affects":["repeating_npcs_$x_npc_is_untrained","repeating_npcs_$x_npc_is_trained","repeating_npcs_$x_npc_is_expert","repeating_npcs_$x_npc_is_master","repeating npcs $X npc is untrained","repeating npcs $X npc is trained","repeating npcs $X npc is expert","repeating npcs $X npc is master"],"addFuncs":[],"listener":"change:repeating_npcs:manipulation","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_manipulation-action":{"name":"repeating_npcs_$x_manipulation-action","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:manipulation-action","listenerFunc":"initiateRoll","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_manipulation_action":{"name":"repeating_npcs_$x_manipulation_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:manipulation_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_medicine":{"name":"repeating_npcs_$x_medicine","type":"checkbox","triggeredFuncs":["syncConnectedNPC"],"affects":["repeating_npcs_$x_npc_is_untrained","repeating_npcs_$x_npc_is_trained","repeating_npcs_$x_npc_is_expert","repeating_npcs_$x_npc_is_master","repeating npcs $X npc is untrained","repeating npcs $X npc is trained","repeating npcs $X npc is expert","repeating npcs $X npc is master"],"addFuncs":[],"listener":"change:repeating_npcs:medicine","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_medicine-action":{"name":"repeating_npcs_$x_medicine-action","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:medicine-action","listenerFunc":"initiateRoll","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_medicine_action":{"name":"repeating_npcs_$x_medicine_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:medicine_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_npc_is_expert":{"name":"repeating_npcs_$x_npc_is_expert","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:npc_is_expert","listenerFunc":"accessSheet","defaultValue":0,"calculation":"calcNPCTraining","initialFunc":"","formula":"","dice":8},"attr_repeating_npcs_$x_npc_is_master":{"name":"repeating_npcs_$x_npc_is_master","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:npc_is_master","listenerFunc":"accessSheet","defaultValue":0,"calculation":"calcNPCTraining","initialFunc":"","formula":"","dice":10},"attr_repeating_npcs_$x_gear":{"name":"repeating_npcs_$x_gear","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:gear","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_weapons":{"name":"repeating_npcs_$x_weapons","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:weapons","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_repeating_npcs_$x_weapons-action":{"name":"repeating_npcs_$x_weapons-action","type":"action","triggeredFuncs":["rollNPC","rollRepeatNPCWeapon"],"affects":[],"addFuncs":[],"listener":"clicked:repeating_npcs:weapons-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_weapons_action":{"name":"repeating_npcs_$x_weapons_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:weapons_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_character_id":{"name":"repeating_npcs_$x_character_id","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:character_id","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_npcs_$x_description":{"name":"repeating_npcs_$x_description","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_npcs:description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_add-rumors":{"name":"add-rumors","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:add-rumors","listenerFunc":"addItem","defaultValue":"","calculation":"","initialFunc":"","formula":""},"fieldset_repeating_rumors":{"name":"repeating_rumors","type":"fieldset","triggeredFuncs":[],"affects":[],"addFuncs":["storeRow"],"listener":"remove:repeating_rumors","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_rumors_$x_collapse":{"name":"repeating_rumors_$x_collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_rumors:collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_rumors_$x_name":{"name":"repeating_rumors_$x_name","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_rumors:name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_rumors_$x_clock":{"name":"repeating_rumors_$x_clock","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_rumors:clock","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_rumors_$x_description":{"name":"repeating_rumors_$x_description","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_rumors:description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_add-challenges":{"name":"add-challenges","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:add-challenges","listenerFunc":"addItem","defaultValue":"","calculation":"","initialFunc":"","formula":""},"fieldset_repeating_challenges":{"name":"repeating_challenges","type":"fieldset","triggeredFuncs":[],"affects":[],"addFuncs":["storeRow"],"listener":"remove:repeating_challenges","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_challenges_$x_collapse":{"name":"repeating_challenges_$x_collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_challenges:collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_challenges_$x_name":{"name":"repeating_challenges_$x_name","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_challenges:name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_challenges_$x_description":{"name":"repeating_challenges_$x_description","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_challenges:description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_endgame_collapse":{"name":"endgame_collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:endgame_collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_endgame_name":{"name":"endgame_name","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:endgame_name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_clock":{"name":"clock","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:clock","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_endgame_description":{"name":"endgame_description","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:endgame_description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_add-factions":{"name":"add-factions","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:add-factions","listenerFunc":"addItem","defaultValue":"","calculation":"","initialFunc":"","formula":""},"fieldset_repeating_factions":{"name":"repeating_factions","type":"fieldset","triggeredFuncs":[],"affects":[],"addFuncs":["storeRow"],"listener":"remove:repeating_factions","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_factions_$x_collapse":{"name":"repeating_factions_$x_collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_factions:collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_factions_$x_name":{"name":"repeating_factions_$x_name","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_factions:name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_factions_$x_clock":{"name":"repeating_factions_$x_clock","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_factions:clock","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_factions_$x_description":{"name":"repeating_factions_$x_description","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_factions:description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_capacity":{"name":"capacity","type":"number","triggeredFuncs":["annexedBy"],"affects":[],"addFuncs":[],"listener":"change:capacity","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_defense":{"name":"defense","type":"number","triggeredFuncs":["annexedBy"],"affects":[],"addFuncs":[],"listener":"change:defense","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_issues":{"name":"issues","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:issues","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_overall":{"name":"overall","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:overall","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_structures":{"name":"structures","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:structures","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_surroudings":{"name":"surroudings","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:surroudings","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_food_sources":{"name":"food_sources","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:food_sources","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_stored-gear_$x_owner":{"name":"repeating_stored-gear_$x_owner","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_stored-gear:owner","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_stored-gear_$x_connected_json":{"name":"repeating_stored-gear_$x_connected_json","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_stored-gear:connected_json","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_add-projects":{"name":"add-projects","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:add-projects","listenerFunc":"addItem","defaultValue":"","calculation":"","initialFunc":"","formula":""},"fieldset_repeating_projects":{"name":"repeating_projects","type":"fieldset","triggeredFuncs":[],"affects":[],"addFuncs":["storeRow"],"listener":"remove:repeating_projects","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_projects_$x_collapse":{"name":"repeating_projects_$x_collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_projects:collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_projects_$x_name":{"name":"repeating_projects_$x_name","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_projects:name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_projects_$x_effect":{"name":"repeating_projects_$x_effect","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_projects:effect","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_projects_$x_workforce":{"name":"repeating_projects_$x_workforce","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_projects:workforce","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_repeating_projects_$x_finish_date":{"name":"repeating_projects_$x_finish_date","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_projects:finish_date","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_projects_$x_requirements":{"name":"repeating_projects_$x_requirements","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_projects:requirements","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_collapse":{"name":"collapse","type":"checkbox","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:collapse","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_haven_name":{"name":"haven_name","type":"text","triggeredFuncs":["claimHaven"],"affects":[],"addFuncs":[],"listener":"change:haven_name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_haven_description":{"name":"haven_description","type":"span","triggeredFuncs":["claimHaven"],"affects":[],"addFuncs":[],"listener":"change:haven_description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_haven_capacity":{"name":"haven_capacity","type":"number","triggeredFuncs":["claimHaven"],"affects":[],"addFuncs":[],"listener":"change:haven_capacity","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_haven_defense":{"name":"haven_defense","type":"number","triggeredFuncs":["claimHaven"],"affects":[],"addFuncs":[],"listener":"change:haven_defense","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_challenges_description":{"name":"challenges_description","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:challenges_description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_challenge_description":{"name":"challenge_description","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:challenge_description","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_threat":{"name":"threat","type":"span","triggeredFuncs":[],"affects":["swarm_skills","swarm_attack","swarm skills","swarm attack","threat_situation","swarm_threat"],"addFuncs":[],"listener":"change:threat","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_decrease-threat-action":{"name":"decrease-threat-action","type":"action","triggeredFuncs":["decreaseThreat"],"affects":[],"addFuncs":[],"listener":"clicked:decrease-threat-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_decrease_threat_action":{"name":"decrease_threat_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:decrease_threat_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_increase-threat-action":{"name":"increase-threat-action","type":"action","triggeredFuncs":["increaseThreat"],"affects":[],"addFuncs":[],"listener":"clicked:increase-threat-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_increase_threat_action":{"name":"increase_threat_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:increase_threat_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_swarm-compendium-attack-action":{"name":"swarm-compendium-attack-action","type":"action","triggeredFuncs":["swarmCompendiumAttack"],"affects":[],"addFuncs":[],"listener":"clicked:swarm-compendium-attack-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_swarm_compendium_attack_action":{"name":"swarm_compendium_attack_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:swarm_compendium_attack_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_swarm-attack-action":{"name":"swarm-attack-action","type":"action","triggeredFuncs":["swarmAttack"],"affects":[],"addFuncs":[],"listener":"clicked:swarm-attack-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_swarm_attack_action":{"name":"swarm_attack_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:swarm_attack_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_threat_situation":{"name":"threat_situation","type":"span","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:threat_situation","listenerFunc":"accessSheet","defaultValue":"threat-situation-0","calculation":"","initialFunc":"","formula":"threat-situation-@{threat}"},"attr_swarm_threat":{"name":"swarm_threat","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:swarm_threat","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":"@{swarm_size} + @{threat}"},"attr_walker_number":{"name":"walker_number","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:walker_number","listenerFunc":"accessSheet","defaultValue":"<5","calculation":"calcWalkerNumber","initialFunc":"","formula":""},"attr_swarm_size":{"name":"swarm_size","type":"number","triggeredFuncs":[],"affects":["swarm_threat","walker_number","walker number","swarm threat"],"addFuncs":[],"listener":"change:swarm_size","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_swarm_show":{"name":"swarm_show","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:swarm_show","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":"@{swarm_skills}@{swarm_attack}"},"attr_swarm_skills":{"name":"swarm_skills","type":"hidden","triggeredFuncs":[],"affects":["swarm_show","swarm_show"],"addFuncs":[],"listener":"change:swarm_skills","listenerFunc":"accessSheet","defaultValue":"","calculation":"calcSwarmSkills","initialFunc":"","formula":""},"attr_swarm_attack":{"name":"swarm_attack","type":"hidden","triggeredFuncs":[],"affects":["swarm_show","swarm_show"],"addFuncs":[],"listener":"change:swarm_attack","listenerFunc":"accessSheet","defaultValue":"","calculation":"calcSwarmAttack","initialFunc":"","formula":""},"attr_notes":{"name":"notes","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:notes","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_travellog_$x_coordinates":{"name":"repeating_travellog_$x_coordinates","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_travellog:coordinates","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_travellog_$x_date":{"name":"repeating_travellog_$x_date","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_travellog:date","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_driver":{"name":"driver","type":"text","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:driver","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_maneuverability":{"name":"maneuverability","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:maneuverability","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_maneuverability-action":{"name":"maneuverability-action","type":"action","triggeredFuncs":["rollManeuverability"],"affects":[],"addFuncs":[],"listener":"clicked:maneuverability-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_maneuverability_action":{"name":"maneuverability_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:maneuverability_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_damage":{"name":"damage","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:damage","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_hull":{"name":"hull","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:hull","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_hull_max":{"name":"hull_max","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:hull_max","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"attr_armor":{"name":"armor","type":"number","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:armor","listenerFunc":"accessSheet","defaultValue":0,"calculation":"","initialFunc":"","formula":""},"act_armor-action":{"name":"armor-action","type":"action","triggeredFuncs":["rollPool"],"affects":[],"addFuncs":[],"listener":"clicked:armor-action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_armor_action":{"name":"armor_action","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:armor_action","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"fieldset_repeating_crew":{"name":"repeating_crew","type":"fieldset","triggeredFuncs":["dynamicPopulate"],"affects":[],"addFuncs":["dynamicPopulate"],"listener":"remove:repeating_crew","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_crew_$x_name":{"name":"repeating_crew_$x_name","triggeredFuncs":["dynamicPopulate"],"affects":[],"addFuncs":[],"listener":"change:repeating_crew:name","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_repeating_weapons_$x_user":{"name":"repeating_weapons_$x_user","type":"select","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:repeating_weapons:user","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"act_add-crew":{"name":"add-crew","type":"action","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"clicked:add-crew","listenerFunc":"addItem","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_whisper":{"name":"whisper","type":"select","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:whisper","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_sheet_type":{"name":"sheet_type","type":"select","triggeredFuncs":["sheetTypeDisplay"],"affects":[],"addFuncs":[],"listener":"change:sheet_type","listenerFunc":"accessSheet","defaultValue":"","calculation":"","initialFunc":"","formula":""},"attr_template_start":{"name":"template_start","type":"hidden","triggeredFuncs":[],"affects":[],"addFuncs":[],"listener":"change:template_start","listenerFunc":"accessSheet","defaultValue":"@{whisper}&{template:walking_dead} {{character_name=@{character_name}}} {{character_id=@{character_id}}}","calculation":"","initialFunc":"","formula":""}};
kFuncs.cascades = cascades;
const repeatingSectionDetails = [{"section":"repeating_weapons","fields":["collapse","name","action","damage","bonus","range","skill","slots","description","user"]},{"section":"repeating_injury","fields":["collapse","name","penalty","limit","recovery"]},{"section":"repeating_talents","fields":["is_selected","name","session","description","used"]},{"section":"repeating_gear","fields":["equipped","collapse","quantity","slots","name","bonus","affects","description","location"]},{"section":"repeating_stored-gear","fields":["equipped","collapse","quantity","slots","name","location","bonus","affects","description","owner","connected_json"]},{"section":"repeating_issues","fields":["collapse","name","source","description"]},{"section":"repeating_npcs","fields":["collapse","name","descriptor","npc_is_untrained","npc_untrained_skills_action","npc_is_trained","close_combat","close_combat_action","endure","endure_action","force","force_action","mobility","mobility_action","ranged_combat","ranged_combat_action","stealth","stealth_action","scout","scout_action","survival","survival_action","tech","tech_action","leadership","leadership_action","manipulation","manipulation_action","medicine","medicine_action","npc_is_expert","npc_is_master","gear","weapons","weapons_action","character_id","description"]},{"section":"repeating_rumors","fields":["collapse","name","clock","description"]},{"section":"repeating_challenges","fields":["collapse","name","description"]},{"section":"repeating_factions","fields":["collapse","name","clock","description"]},{"section":"repeating_projects","fields":["collapse","name","effect","workforce","finish_date","requirements"]},{"section":"repeating_travelLog","fields":["coordinates","date"]},{"section":"repeating_crew","fields":["name"]}];
kFuncs.repeatingSectionDetails = repeatingSectionDetails;
const persistentTabs = ["walking_dead_tab"];
kFuncs.persistentTabs = persistentTabs;
/**
* The K-scaffold provides several variables to allow your scripts to tap into its information flow.
* @namespace Sheetworkers.Variables
*/
/**
* This stores the name of your sheet for use in the logging functions {@link log} and {@link debug}. Accessible by `k.sheetName`
* @memberof Variables
* @var
* @type {string}
*/
let sheetName = 'kScaffold Powered Sheet';
kFuncs.sheetName = sheetName;
/**
* This stores the version of your sheet for use in the logging functions{@link log} and {@link debug}. It is also stored in the sheet_version attribute on your character sheet. Accessible via `k.version`
* @memberof Variables
* @var
* @type {number}
*/
let version = 0;
kFuncs.version = version;
/**
* A boolean flag that tells the script whether to enable or disable {@link debug} calls. If the version of the sheet is `0`, or an attribute named `debug_mode` is found on opening this is set to true for your entire session. Otherwise, it remains false.
* @memberof Variables
* @var
* @type {boolean}
*/
let debugMode = false;
kFuncs.debugMode = debugMode;
const funcs = {};
kFuncs.funcs = funcs;
const updateHandlers = {};
const openHandlers = {};
const initialSetups = {};
const allHandlers = {};
const addFuncs = {};
const kscaffoldJSVersion = '1.0.0';
const kscaffoldPUGVersion = '1.0.0';
/**
* Defines the rollstring that rolls made using k.startRoll begin with. Defaults to "&{template:default}".
* @memberof Variables
* @var
* @type {string}
*/
let defaultRollStart = '&{template:default}';
kFuncs.defaultRollStart = defaultRollStart;/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/
/*jshint -W014,-W084,-W030,-W033*/
/**
* These are utility functions that are not directly related to Roll20 systems. They provide easy methods for everything from processing text and numbers to querying the user for input.
* @namespace Sheetworkers.Utilities
* @alias Utilities
*/
/**
* Replaces problem characters to use a string as a regex
* @memberof Utilities
* @param {string} text - The text to replace characters in
* @returns {string}
* @example
* const textForRegex = k.sanitizeForRegex('.some thing[with characters]');
* console.log(textForRegex);// => "\.some thing\[with characters\]"
*/
const sanitizeForRegex = function(text){
return text.replace(/\.|\||\(|\)|\[|\]|\-|\+|\?|\/|\{|\}|\^|\$|\*/g,'\\$&');
};
kFuncs.sanitizeForRegex = sanitizeForRegex;
/**
* Converts a value to a number, it\'s default value, or `0` if no default value passed.
* @memberof Utilities
* @param {string|number} val - Value to convert to a number
* @param {number} def - The default value, uses 0 if not passed
* @returns {number|undefined}
* @example
* const num = k.value('100');
* console.log(num);// => 100
*/
const value = function(val,def){
const convertVal = +val;
if(def !== undefined && isNaN(def)){
throw(`K-scaffold Error: invalid default for value(). Default: ${def}`);
}
return convertVal === 0 ?
convertVal :
(+val||def||0);
};
kFuncs.value = value;
/**
* Extracts the section (e.g. `repeating_equipment`), rowID (e.g `-;lkj098J:LKj`), and field name (e.g. `bulk`) from a repeating attribute name.
* @memberof Utilities
* @param {string} string - The string to parse
* @returns {array} - Array of matches. Index 0: the section name, e.g. repeating_equipment | Index 1:the row ID | index 2: The name of the attribute
* @returns {string[]}
* @example
* //Extract info from a full repeating name
* const [section,rowID,attrName] = k.parseRepeatName('repeating_equipment_-8908asdflkjZlkj23_name');
* console.log(section);// => "repeating_equipment"
* console.log(rowID);// => "-8908asdflkjZlkj23"
* console.log(attrName);// => "name"
*
* //Extract info from just a row name
* const [section,rowID,attrName] = k.parseRepeatName('repeating_equipment_-8908asdflkjZlkj23');
* console.log(section);// => "repeating_equipment"
* console.log(rowID);// => "-8908asdflkjZlkj23"
* console.log(attrName);// => undefined
*/
const parseRepeatName = function(string){
let match = string.match(/(repeating_[^_]+)_([^_]+)(?:_(.+))?/);
match.shift();
return match;
};
kFuncs.parseRepeatName = parseRepeatName;
/**
* Parses out the components of a trigger name similar to [parseRepeatName](#parserepeatname). Aliases: parseClickTrigger.
*
* Aliases: `k.parseClickTrigger`
* @memberof Utilities
* @param {string} string The triggerName property of the
* @returns {array} - For a repeating button named `repeating_equipment_-LKJhpoi98;lj_roll`, the array will be `['repeating_equipment','-LKJhpoi98;lj','roll']`. For a non repeating button named `roll`, the array will be `[undefined,undefined,'roll']`
* @returns {string[]}
* @example
* //Parse a non repeating trigger
* const [section,rowID,attrName] = k.parseTriggerName('clicked:some-button');
* console.log(section);// => undefined
* console.log(rowID);// => undefined
* console.log(attrName);// => "some-button"
*
* //Parse a repeating trigger
* const [section,rowID,attrName] = k.parseTriggerName('clicked:repeating_attack_-234lkjpd8fu8usadf_some-button');
* console.log(section);// => "repeating_attack"
* console.log(rowID);// => "-234lkjpd8fu8usadf"
* console.log(attrName);// => "some-button"
*
* //Parse a repeating name
* const [section,rowID,attrName] = k.parseTriggerName('repeating_attack_-234lkjpd8fu8usadf_some-button');
* console.log(section);// => "repeating_attack"
* console.log(rowID);// => "-234lkjpd8fu8usadf"
* console.log(attrName);// => "some-button"
*/
const parseTriggerName = function(string){
let match = string.replace(/^clicked:/,'').match(/(?:(repeating_[^_]+)_([^_]+)_)?(.+)/);
match.shift();
return match;
};
kFuncs.parseTriggerName = parseTriggerName;
const parseClickTrigger = parseTriggerName;
kFuncs.parseClickTrigger = parseClickTrigger;
/**
* Parses out the attribute name from the htmlattribute name.
* @memberof Utilities
* @param {string} string - The triggerName property of the [event](https://wiki.roll20.net/Sheet_Worker_Scripts#eventInfo_Object).
* @returns {string}
* @example
* //Parse a name
* const attrName = k.parseHtmlName('attr_attribute_1');
* console.log(attrName);// => "attribute_1"
*/
const parseHTMLName = function(string){
let match = string.match(/(?:attr|act|roll)_(.+)/);
match.shift();
return match[0];
};
kFuncs.parseHTMLName = parseHTMLName;
/**
* Capitalize each word in a string
* @memberof Utilities
* @param {string} string - The string to capitalize
* @returns {string}
* @example
* const capitalized = k.capitalize('a word');
* console.log(capitalized);// => "A Word"
*/
const capitalize = function(string){
return string.replace(/(?:^|\s+|\/)[a-z]/ig,(letter)=>letter.toUpperCase());
};
kFuncs.capitalize = capitalize;
/**
* Extracts a roll query result for use in later functions. Must be awaited as per [startRoll documentation](https://wiki.roll20.net/Sheet_Worker_Scripts#Roll_Parsing.28NEW.29). Stolen from [Oosh\'s Adventures with Startroll thread](https://app.roll20.net/forum/post/10346883/adventures-with-startroll).
* @memberof Utilities
* @param {string} query - The query should be just the text as the `?{` and `}` at the start/end of the query are added by the function.
* @returns {Promise} - Resolves to the selected value from the roll query
* @example
* const rollFunction = async function(){
* //Get the result of a choose from list query
* const queryResult = await extractQueryResult('Prompt Text Here|Option 1|Option 2');
* console.log(queryResult);//=> "Option 1" or "Option 2" depending on what the user selects
*
* //Get free form input from the user
* const freeResult = await extractQueryResult('Prompt Text Here');
* consoel.log(freeResult);// => Whatever the user entered
* }
*/
const extractQueryResult = async function(query){
debug('entering extractQueryResult');
const rollObj = {
query:`[[0[response=?{${query}}]]]`
};
let {roll} = await _startRoll(rollObj,'!');
roll.finish();
return roll.results.query.expression.replace(/^.+?response=|\]$/g,'');
};
kFuncs.extractQueryResult = extractQueryResult;
/**
* Simulates a query for ensuring that async/await works correctly in the sheetworker environment when doing conditional startRolls. E.g. if you have an if/else and only one of the conditions results in `startRoll` being called (and thus an `await`), the sheetworker environment would normally crash. Awaiting this in the condition that does not actually need to call `startRoll` will keep the environment in sync.
* @memberof Utilities
* @param {string|number} [value] - The value to return. Optional.
* @returns {Promise} - Resolves to the value passed to the function
* @example
* const rollFunction = async function(){
* //Get the result of a choose from list query
* const queryResult = await pseudoQuery('a value');
* console.log(queryResult);//=> "a value"
* }
*/
const pseudoQuery = async function(value){
const rollObj = {
query:`[[0[response=${value}]]]`
};
let {roll} = await _startRoll(rollObj,'!');
roll.finish();
return roll.results.query.expression.replace(/^.+?response=|\]$/g,'');
};
kFuncs.pseudoQuery = pseudoQuery;
/**
* An alias for console.log.
* @memberof Utilities
* @param {any} msg - The message can be a straight string, an object, or an array. If it is an object or array, the object will be broken down so that each key is used as a label to output followed by the value of that key. If the value of the key is an object or array, it will be output via `console.table`.
*/
const log = function(msg){
if(typeof msg === 'string'){
console.log(`%c${kFuncs.sheetName} log| ${msg}`,"background-color:#159ccf");
}else if(typeof msg === 'object'){
Object.keys(msg).forEach((m)=>{
if(typeof msg[m] === 'string'){
console.log(`%c${kFuncs.sheetName} log| ${m}: ${msg[m]}`,"background-color:#159ccf");
}else{
console.log(`%c${kFuncs.sheetName} log| ${typeof msg[m]} ${m}`,"background-color:#159ccf");
console.table(msg[m]);
}
});
}
};
kFuncs.log = log;
/**
* Alias for console.log that only triggers when debug mode is enabled or when the sheet\'s version is `0`. Useful for entering test logs that will not pollute the console on the live sheet.
* @memberof Utilities
* @param {any} msg - 'See {@link k.log}
* @param {boolean} force - Pass as a truthy value to force the debug output to be output to the console regardless of debug mode.
* @returns {void}
*/
const debug = function(msg,force){
if(!kFuncs.debugMode && !force && kFuncs.version > 0) return;
if(typeof msg === 'string'){
console.warn(`%c${kFuncs.sheetName} DEBUG| ${msg}`,"background-color:tan;color:red;");
}else if(typeof msg === 'object'){
Object.keys(msg).forEach((m)=>{
if(typeof msg[m] === 'string'){
console.warn(`%c${kFuncs.sheetName} DEBUG| ${m}: ${msg[m]}`,"background-color:tan;color:red;");
}else{
console.warn(`%c${kFuncs.sheetName} DEBUG| ${typeof msg[m]} ${m}`,"background-color:tan;color:red;font-weight:bold;");
console.table(msg[m]);
}
});
}
};
kFuncs.debug = debug;
/**
* Orders the section id arrays for all sections in the `sections` object to match the repOrder attribute.
* @memberof Utilities
* @param {attributesProxy} attributes - The attributes object that must have a value for the reporder for each section.
* @param {object[]} sections - Object containing the IDs for the repeating sections, indexed by repeating section name.
*/
const orderSections = function(attributes,sections){
Object.keys(sections).forEach((section)=>{
attributes.attributes[`_reporder_${section}`] = commaArray(attributes[`_reporder_${section}`]);
sections[section] = orderSection(attributes.attributes[`_reporder_${section}`],sections[section]);
});
};
kFuncs.orderSections = orderSections;
/**
* Orders a single ID array.
* @memberof Utilities
* @param {string[]} repOrder - Array of IDs in the order they are in on the sheet.
* @param {string[]} IDs - Array of IDs to be ordered. Aka the default ID Array passed to the getSectionIDs callback
* @returns {string[]} - The ordered id array
*/
const orderSection = function(repOrder,IDs=[]){
const idArr = [...repOrder.filter(v => v),...IDs.filter(id => !repOrder.includes(id.toLowerCase()))];
return idArr;
};
kFuncs.orderSection = orderSection;
/**
* Splits a comma delimited string into an array
* @memberof Utilities
* @param {string} string - The string to split.
* @returns {array} - The string segments of the comma delimited list.
*/
const commaArray = function(string=''){
return string.toLowerCase().split(/\s*,\s*/);
};
kFuncs.commaArray = commaArray;
// Roll escape functions for passing data in action button calls. Base64 encodes/decodes the data.
const RE = {
chars: {
'"': '%quot;',
',': '%comma;',
':': '%colon;',
'}': '%rcub;',
'{': '%lcub;',
},
escape(data) {
return typeof data === 'object' ?
`KDATA${btoa(JSON.stringify(data))}` :
`KSTRING${btoa(data)}`;
},
unescape(string) {
const isData = typeof string === 'string' &&
(
string.startsWith('KDATA') ||
string.startsWith('KSTRING')
);
return isData ?
(
string.startsWith('KDATA') ?
JSON.parse(atob(string.replace(/^KDATA/,''))) :
atob(string.replace(/^KSTRING/,''))
) :
string;
}
};
/**
* Encodes data in Base64. This is useful for passing roll information to action buttons called from roll buttons.
* @function
* @param {string|object|any[]} data - The data that you want to Base64 encode
* @returns {string} - The encoded data
* @memberof! Utilities
*/
const escape = RE.escape;
/**
* Decodes Base64 encoded strings that were created by the K-scaffold
* @function
* @param {string|object|any[]} string - The string of encoded data to decode. If this is not a string, or is not a string that was encoded by the K-scaffold, it will be returned as is.
* @returns {string|object|any[]}
* @memberof! Utilities
*/
const unescape = RE.unescape;
Object.assign(kFuncs,{escape,unescape});
/**
* Parses a macro so that it is reduced to the final values of all attributes contained in the macro. Will drill down up to 99 levels deep. If the string was not parseable, string will be returned with as much parsed as possible.
* @memberof Utilities
* @param {string} mutStr - The string macro to parse
* @param {AttributesProxy} attributes - The K-scaffold Attributes Proxy
* @param {Object} sections - The K-scaffold sections object
* @returns {string} - The string with all attributes replaced by their values (if possible).
*/
const parseMacro = (str,attributes,sections) => {
let iter = 0;
let mutStr = str;
while(mutStr.match(/@{.+?}/) && iter < 99){
mutStr = mutStr.replace(/@{(.+?)}/g,(match,name) => {
name = name.replace(/\|/,'_');
return attributes[name] !== null && attributes[name] !== undefined ?
attributes[name] :
`@(${name})`;
})
iter++;
}
mutStr = mutStr.replace(/@\((.+?)\)/g,'@{$1}');
return mutStr;
}
kFuncs.parseMacro = parseMacro;
/**
* Sends data to another character sheet to cause a change on that sheet. WARNING, this function should not be used in response to an attribute change to avoid spamming the chat with api messages.
*
* ![k.send.gif](/k-scaffold/k.send.gif)
* @memberof Utilities
* @param {string} characterName - The character to connect to
* @param {string} funcName - Name of the function to call similar to function name used in {@link callFunc}.
* @param {...any} args - The arguments to pass to the function call no the other sheet. These are passed after the normal destructure object for a K-scaffold function call.
* @example
* //Function that is called by the source sheet
* const dispatchPartner = async function({trigger,attributes,sections,casc}){
* const partnerName = await (
* attributes.partner_name ?
* k.pseudoQuery(attributes.partner_name) :
* k.extractQueryResult('Partner name')
* );
* attributes.partner_name = partnerName;
* //passing the attributes of the source sheet
* k.send(partnerName,'receivePartner',attributes);
* attributes.set();
* };
* k.registerFuncs({dispatchPartner});
*
* //Function called on target sheet. Partner is the attributes from the source sheet
* const receivePartner = function({trigger,attributes,sections,casc},partner){
* attributes.from_partner = partner.for_partner;
* attributes.partner_name = partner.character_name;
* };
* k.registerFuncs({receivePartner });
*/
const send = async function(characterName,funcName,...args){
const data = RE.escape({
funcName,
args
});
const roll = await startRoll(`!@{${characterName}|character_name}%{${characterName}|k-network-call||${data}}&{noerror}`);
finishRoll(roll.rollId);
};
kFuncs.send = send;
const kReceive = function({trigger,attributes,sections,casc}) {
const data = trigger.rollData;
callFunc(data.funcName,{attributes,sections,casc},...data.args);
};
funcs.kReceive = kReceive;/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/
/*jshint -W014,-W084,-W030,-W033*/
//# Attribute Obj Proxy handler
const createAttrProxy = function(attrs,sections,casc){
//creates a proxy for the attributes object so that values can be worked with more easily.
const getCascObj = function(event){
const eventName = event.triggerName || event.sourceAttribute;
let typePrefix = eventName.startsWith('clicked:') ?
'act_' :
event.removedInfo ?
'fieldset_' :
'attr_';
let cascName = `${typePrefix}${eventName.replace(/(?:removed?|clicked):/,'')}`;
let cascObj = casc[cascName];
k.debug({[cascName]:cascObj});
if(event && cascObj){
Object.assign(cascObj,event);
if(event.originalRollId){
cascObj.rollData = RE.unescape(event.originalRollId);
}
}
return cascObj || {};
};
const triggerFunctions = function(obj){
if(obj.triggeredFuncs && obj.triggeredFuncs.length){
debug(`triggering functions for ${obj.name}`);
obj.triggeredFuncs && obj.triggeredFuncs.forEach(func=>funcs[func] ?
funcs[func]({trigger:obj,attributes,sections,casc}) :
debug(`!!!Warning!!! no function named ${func} found. Triggered function not called for ${obj.name}`,true));
}
};
const initialFunction = function(obj){
if(obj.initialFunc){
debug(`initial functions for ${obj.name}`);
funcs[obj.initialFunc] ?
funcs[obj.initialFunc]({trigger:obj,attributes,sections}) :
debug(`!!!Warning!!! no function named ${obj.initialFunc} found. Initial function not called for ${obj.name}`,true);
}
};
const alwaysFunctions = function(trigger){
Object.values(allHandlers).forEach((handler)=>{
handler({trigger,attributes,sections,casc});
});
};
const processChange = function({event,trigger}){
if(event && !trigger){
debug(`${event.sourceAttribute} change detected. No trigger found`);
return;
}
if(!attributes || !sections || !casc){
debug(`!!! Insufficient arguments || attributes > ${!!attributes} | sections > ${!!sections} | casc > ${!!casc} !!!`);
return;
}
debug({trigger});
if(event){
debug('checking for initial & always functions');
if(Array.isArray(trigger.affects)){
attributes.queue.push(...trigger.affects);
}
alwaysFunctions(trigger,attributes,sections,casc);//Functions that should be run for all events.
initialFunction(trigger,attributes,sections,casc);//functions that should only be run if the attribute was the thing changed by the user
}
if(trigger){
debug(`processing ${trigger.name}`);
triggerFunctions(trigger,attributes,sections,casc);
if(!event){
// Handle autocalc formula
if(trigger.formula){
attributes[trigger.name] = parseKFormula({trigger,attributes,sections,casc});
}
// handle calculation of element
if(
trigger.calculation &&
funcs[trigger.calculation]
){
attributes[trigger.name] = funcs[trigger.calculation]({trigger,attributes,sections,casc});
}else if(trigger.calculation && !funcs[trigger.calculation]){
debug(`K-Scaffold Error: No function named ${trigger.calculation} found`);
}
}
}
attributes.set();
};
const attrTarget = {
updates:{},
attributes:{...attrs},
repOrders:{},
queue: [],
casc:{},
alwaysFunctions,
processChange,
triggerFunctions,
initialFunction,
getCascObj
};
const attrHandler = {
get:function(obj,prop){//gets the most value of the attribute.
//If it is a repeating order, returns the array, otherwise returns the update value or the original value
if(prop === 'toJSON'){
return () => ({...obj.attributes,...obj.updates});
} else if(prop === 'set'){
return function(){
let {callback,vocal} = arguments[0] ? arguments[0] : {};
if(sections && casc && attributes.queue.length){
const triggerName = attributes.queue.shift();
const trigger = getCascObj({sourceAttribute:triggerName});
processChange({trigger,attributes,sections,casc});
}else{
debug({updates:obj.updates});
const trueCallback = Object.keys(obj.repOrders).length ?
function(){
Object.entries(obj.repOrders).forEach(([section,order])=>{
_setSectionOrder(section,order)
});
callback && callback();
}:
callback;
Object.keys(obj.updates).forEach((key)=>obj.attributes[key] = obj.updates[key]);
const update = obj.updates;
obj.updates = {};
set(update,vocal,trueCallback);
}
}
}else if(Object.keys(obj).some(key=>key===prop)){
return Reflect.get(...arguments)
}else{
let retValue;
switch(true){
case obj.repOrders.hasOwnProperty(prop):
retValue = obj.repOrders[prop];
break;
case obj.updates.hasOwnProperty(prop):
retValue = obj.updates[prop];
break;
default:
retValue = obj.attributes[prop];
break;
}
let cascRef = `attr_${prop.replace(/(repeating_[^_]+_)[^_]+/,'$1\$X')}`;
let numRetVal = +retValue;
if(!Number.isNaN(numRetVal) && retValue !== ''){
retValue = numRetVal;
}else if(cascades[cascRef] && (typeof cascades[cascRef].defaultValue === 'number' || cascades[cascRef].type === 'number')){
retValue = cascades[cascRef].defaultValue;
}
return retValue;
}
},
set:function(obj,prop,value){
//Sets the value. Also verifies that the value is a valid attribute value
//e.g. not undefined, null, or NaN
if(value || value===0 || value===''){
if(/reporder|^repeating_[^_]+$/.test(prop)){
let section = prop.replace(/_reporder_/,'');
obj.repOrders[section] = value;
}else if(`${obj.attributes}` !== `${value}` ||
(obj.updates[prop] && `${obj.updates}` !== `${value}`)
){
if(sections && casc){
const trigger = getCascObj({sourceAttribute:prop});
if(Array.isArray(trigger.affects)){
attributes.queue.push(...trigger.affects);
}
}
obj.updates[prop] = value;
}
}else{
debug(`!!!Warning: Attempted to set ${prop} to an invalid value:${value}; value not stored!!!`);
}
return true;
},
deleteProperty(obj,prop){
//removes the property from the original attributes, updates, and the reporders
Object.keys(obj).forEach((key)=>{
delete obj[key][prop.toLowerCase()];
});
}
};
const attributes = new Proxy(attrTarget,attrHandler);
return attributes;
};
/**
* Function that registers a function for being called via the funcs object. Returns true if the function was successfully registered, and false if it could not be registered for any reason.
* @memberof Utilities
* @param {object} funcObj - Object with keys that are names to register functions under and values that are functions.
* @param {object} optionsObj - Object that contains options to use for this registration.
* @param {string[]} optionsObj.type - Array that contains the types of specialized functions that apply to the functions being registered. Valid types are `"opener"`, `"updater"`, and `"default"`. `"default"` is always used, and never needs to be passed.
* @returns {boolean} - True if the registration succeeded, false if it failed.
* @example
* //Basic Registration
* const myFunc = function({trigger,attributes,sections,casc}){};
* k.registerFuncs({myFunc});
*
* //Register a function to run on sheet open
* const openFunc = function({trigger,attributes,sections,casc}){};
* k.registerFuncs({openFunc},{type:['opener']})
*
* //Register a function to run on all events
* const allFunc = function({trigger,attributes,sections,casc}){};
* k.registerFuncs({allFunc},{type:['all']})
*/
const registerFuncs = function(funcObj,optionsObj = {}){
if(typeof funcObj !== 'object' || typeof optionsObj !== 'object'){
debug(`!!!! K-scaffold error: Improper arguments to register functions !!!!`);
return false;
}
const typeArr = optionsObj.type ? ['default',...optionsObj.type] : ['default'];
const typeSwitch = {
'opener':openHandlers,
'updater':updateHandlers,
'new':initialSetups,
'all':allHandlers,
'default':funcs
};
let setState;
Object.entries(funcObj).map(([prop,value])=>{
typeArr.forEach((type)=>{
if(typeSwitch[type][prop]){
debug(`!!! Duplicate function name for ${prop} as ${type}!!!`);
setState = false;
}else if(typeof value === 'function'){
typeSwitch[type][prop] = value;
setState = setState !== false ? true : false;
}else{
debug(`!!! K-scaffold error: Function registration requires a function. Invalid value to register as ${type} !!!`);
setState = false;
}
});
});
return setState;
};
kFuncs.registerFuncs = registerFuncs;
/**
* Function that sets up the action calls used in the roller mixin.
* @memberof Sheetworkers
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
*/
const setActionCalls = function({attributes,sections}){
actionAttributes.forEach((base)=>{
let [section,,field] = k.parseTriggerName(base);
let fieldAction = field.replace(/_/g,'-');
if(section){
sections[section].forEach((id)=>{
attributes[`${section}_${id}_${field}`] = `%{${attributes.character_name}|${section}_${id}_${fieldAction}}`;
});
}else{
attributes[`${field}`] = `%{${attributes.character_name}|${fieldAction}}`;
}
});
};
funcs.setActionCalls = setActionCalls;
kFuncs.setActionCalls = setActionCalls;
/**
* Function that reduces Roll20 macro syntax formulas down to their calculated value.
* @memberof Sheetworkers
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
*/
const parseKFormula = ({trigger,attributes,sections,casc}) => {
const [baseSection,rowID,attrName] = parseTriggerName(trigger.name);
const repeatBlockRx = baseSection ?
/(@{repeating_.+?_\$X_.+?})/g :
/={([^)]*repeating_[^_]+[^)]*)}=/g;
let mutFormula = trigger.formula;
mutFormula = mutFormula.replace(repeatBlockRx,(match,repeatMacro) => {
const [section] = repeatMacro.match(/repeating_[^_]+/);
const idArray = baseSection ?
[rowID] :
sections[section];
return idArray.map(id => {
return `(${repeatMacro.replace(/repeating_[^_]+?_[^_]+?_([^}]+)/g,`${section}_${id}_$1`)})`;
}).join(
trigger.type === 'number' ?
' + ' :
''
);
});
mutFormula = parseMacro(mutFormula,attributes)
.replace(/@{.+?}/g,'0');
const mathKeys = ['floor','ceil','round','abs'];
mathKeys.forEach(func => mutFormula = mutFormula.replace(new RegExp(`${func}\\(`,'g'),`Math.${func}(`));
const mathRx = new RegExp(`Math\\.(?:${mathKeys.join('|')})`,'g');
let noAlphaStr = mutFormula
.replace(mathRx,'');
return trigger.type !== 'text' ?
(
!noAlphaStr.match(/[a-z]/i) ?
eval(mutFormula) :
undefined
) :
mutFormula;
};
funcs.parseKFormula = parseKFormula;
kFuncs.parseKFormula = parseKFormula;
/**
* Function to call a function previously registered to the funcs object. May not be used that much in actual sheets, but very useful when writing unit tests for your sheet. Either returns the function or null if no function exists.
* @memberof Sheetworkers
* @param {string} funcName - The name of the function to invoke.
* @param {...any} args - The arguments to call the function with.
* @returns {function|null}
* @example
* //Call myFunc with two arguments
* k.callFunc('myFunc','an argument','another argument');
*/
const callFunc = function(funcName,...args){
if(funcs[funcName]){
debug(`calling ${funcName}`);
return funcs[funcName](...args);
}else{
debug(`Invalid function name: ${funcName}`);
return null;
}
};
kFuncs.callFunc = callFunc;/**@namespace Sheetworkers */
/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/
/*jshint -W014,-W084,-W030,-W033*/
//Sheet Updaters and styling functions
/**
* Function that calls the K-scaffold's update and sheet initialization routines.
*/
const updateSheet = function(){
log('updating sheet');
getAllAttrs({props:['debug_mode',...baseGet],callback:(attributes,sections,casc)=>{
kFuncs.debugMode = kFuncs.debugMode || !!attributes.debug_mode;
debug({sheet_version:attributes.sheet_version});
if(!attributes.sheet_version){
Object.entries(initialSetups).forEach(([funcName,handler])=>{
if(typeof funcs[funcName] === 'function'){
debug(`running ${funcName}`);
funcs[funcName]({attributes,sections,casc});
}else{
debug(`!!!Warning!!! no function named ${funcName} found. Initial sheet setup not performed.`);
}
});
}else{
Object.entries(updateHandlers).forEach(([ver,handler])=>{
if(attributes.sheet_version < +ver){
handler({attributes,sections,casc});
}
});
}
k.debug({openHandlers});
Object.entries(openHandlers).forEach(([funcName,func])=>{
if(typeof funcs[funcName] === 'function'){
debug(`running ${funcName}`);
funcs[funcName]({attributes,sections,casc});
}else{
debug(`!!!Warning!!! no function named ${funcName} found. Sheet open handling not performed.`);
}
});
setActionCalls({attributes,sections});
attributes.sheet_version = kFuncs.version;
log(`Sheet Update applied. Current Sheet Version ${kFuncs.version}`);
attributes.set();
log('Sheet ready for use');
}});
};
kFuncs.updateSheet = updateSheet;
const initialSetup = function(attributes,sections){
debug('Initial sheet setup');
};
/**
* This is the default listener function for attributes that the K-Scaffold uses. It utilizes the `triggerFuncs`, `listenerFunc`, `calculation`, and `affects` properties of the K-scaffold trigger object (see the Pug section of the scaffold for more details).
* @memberof Sheetworkers
* @param {Roll20Event} event - The Roll20 event object
* @returns {void}
* @example
* //Call from an attribute change
* on('change:an_attribute',k.accessSheet);
*/
const accessSheet = function(event){
debug({funcs:Object.keys(funcs)});
debug({event});
getAllAttrs({callback:(attributes,sections,casc)=>{
let trigger = attributes.getCascObj(event,casc);
attributes.processChange({event,trigger,attributes,sections,casc});
}});
};
funcs.accessSheet = accessSheet;/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/
/*jshint -W014,-W084,-W030,-W033*/
/*
Cascade Expansion functions
*/
//Expands the repeating section templates in cascades to reflect the rows actually available
const expandCascade = function(cascade,sections){
return _.keys(cascade).reduce((memo,key)=>{//iterate through cascades and replace references to repeating attributes with correct row ids.
if(/^(?:act|attr)_repeating_/.test(key)){//If the attribute is a repeating attribute, do special logic
expandRepeating(memo,key,cascade,sections);
}else if(key){//for non repeating attributes do this logic
expandNormal(memo,key,cascade,sections);
}
return memo;
},{});
};
const expandRepeating = function(memo,key,cascade,sections){
key.replace(/((?:attr|act)_)(repeating_[^_]+)_[^_]+?_(.+)/,(match,type,section,field)=>{
(sections[section]||[]).forEach((id)=>{
memo[`${type}${section}_${id}_${field}`]=_.clone(cascade[key]);//clone the details so that each row's attributes have correct ids
memo[`${type}${section}_${id}_${field}`].name = `${section}_${id}_${field}`;
if(key.startsWith('attr_')){
memo[`${type}${section}_${id}_${field}`].affects = memo[`${type}${section}_${id}_${field}`].affects.reduce((m,affected)=>{
if(affected.startsWith(section)){//otherwise if the affected attribute is in the same section, simply set the affected attribute to have the same row id.
m.push(applyID(affected,id));
}else if(/repeating/.test(affected)){//If the affected attribute isn't in the same repeating section but is still a repeating attribute, add all the rows of that section
addAllRows(affected,m,sections);
}else{//otherwise the affected attribute is a non repeating attribute. Simply add it to the computed affected array
m.push(affected);
}
return m;
},[]);
}
});
});
};
const applyID = function(affected,id){
return affected.replace(/(repeating_[^_]+_)[^_]+(.+)/,`$1${id}$2`);
};
const expandNormal = function(memo,key,cascade,sections){
memo[key] = _.clone(cascade[key]);
if(key.startsWith('attr_')){
memo[key].affects = memo[key].affects || [];
memo[key].affects = memo[key].affects.reduce((m,a)=>{
if(/^repeating/.test(a)){
addAllRows(a,m,sections);
}else{
m.push(a);
}
return m;
},[]);
}
};
const addAllRows = function(affected,memo,sections){
affected.replace(/(repeating_[^_]+?)_[^_]+?_(.+)/,(match,section,field)=>{
sections[section].forEach(id=>memo.push(`${section}_${id}_${field}`));
});
};/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/
/*jshint -W014,-W084,-W030,-W033*/
/**
* These are functions that provide K-scaffold aliases for the basic Roll20 sheetworker functions. These functions also provide many additional features on top of the standard Roll20 sheetworkers.
* @namespace Sheetworkers.Sheetworker Aliases
*/
/**
* Alias for [setSectionOrder()](https://wiki.roll20.net/Sheet_Worker_Scripts#setSectionOrder.28.3CRepeating_Section_Name.3E.2C_.3CSection_Array.3E.2C_.3CCallback.3E.29) that allows you to use the section name in either `repeating_section` or `section` formats. Note that the Roll20 sheetworker [setSectionOrder](https://wiki.roll20.net/Sheet_Worker_Scripts#setSectionOrder.28.3CRepeating_Section_Name.3E.2C_.3CSection_Array.3E.2C_.3CCallback.3E.29) currently causes some display issues on sheets.
* @memberof Sheetworker Aliases
* @name setSectionOrder
* @param {string} section - The name of the section, with or without `repeating_`
* @param {string[]} order - Array of ids describing the desired order of the section.
* @returns {void}
* @example
* //Set the order of a repeating_weapon section
* k.setSectionOrder('repeating_equipment',['id1','id2','id3']);
* //Can also specify the section name without the repeating_ prefix
* k.setSectionOrder('equipment',['id1','id2','id3']);
*/
const _setSectionOrder = function(section,order){
let trueSection = section.replace(/repeating_/,'');
setSectionOrder(trueSection,order);
};
kFuncs.setSectionOrder = _setSectionOrder;
/**
* Alias for [removeRepeatingRow](https://wiki.roll20.net/Sheet_Worker_Scripts#removeRepeatingRow.28_RowID_.29) that also removes the row from the current object of attribute values and array of section IDs to ensure that erroneous updates are not issued.
* @memberof Sheetworker Aliases
* @name removeRepeatingRow
* @param {string} row - The row id to be removed
* @param {attributesProxy} attributes - The attribute values currently in memory
* @param {object} sections - Object that contains arrays of all the IDs in sections on the sheet indexed by repeating name.
* @returns {void}
* @example
* //Remove a repeating Row
* k.getAllAttrs({
* callback:(attributes,sections)=>{
* const rowID = sections.repeating_equipment[0];
* k.removeRepeatingRow(`repeating_equipment_${rowID}`,attributes,sections);
* console.log(sections.repeating_equipment); // => rowID no longer exists in the array.
* console.log(attributes[`repeating_equipment_${rowID}_name`]); // => undefined
* }
* })
*/
const _removeRepeatingRow = function(row,attributes,sections){
debug(`removing ${row}`);
Object.keys(attributes.attributes).forEach((key)=>{
if(key.startsWith(row)){
delete attributes[key];
}
});
let [,section,rowID] = row.match(/(repeating_[^_]+)_(.+)/,'');
sections[section] = sections[section].filter((id)=>id!==rowID);
removeRepeatingRow(row);
};
kFuncs.removeRepeatingRow = _removeRepeatingRow;
/**
* Alias for [getAttrs()](https://wiki.roll20.net/Sheet_Worker_Scripts#getAttrs.28attributeNameArray.2C_callback.29) that converts the default object of attribute values into an {@link attributesProxy} and passes that back to the callback function.
* @memberof Sheetworker Aliases
* @name getAttrs
* @param {string[]} [props=baseGet] - Array of attribute names to get the value of. Defaults to {@link baseGet} if not passed.
* @param {function(attributesProxy)} callback - The function to call after the attribute values have been gotten. An {@link attributesProxy} is passed to the callback.
* @example
* //Gets the attributes named in props.
* k.getAttrs({
* props:['attribute_1','attribute_2'],
* callback:(attributes)=>{
* //Work with the attributes as you would in a normal getAttrs, or use the superpowers of the K-scaffold attributes object like so:
* attributes.attribute_1 = 'new value';
* attributes.set();
* }
* })
*/
const _getAttrs = function({props=baseGet,callback}){
getAttrs(props,(values)=>{
const attributes = createAttrProxy(values);
callback(attributes);
});
};
kFuncs.getAttrs = _getAttrs;
/**
* Alias for [getAttrs()](https://wiki.roll20.net/Sheet_Worker_Scripts#getAttrs.28attributeNameArray.2C_callback.29) and [getSectionIDs](https://wiki.roll20.net/Sheet_Worker_Scripts#getSectionIDs.28section_name.2Ccallback.29) that combines the actions of both sheetworker functions and converts the default object of attribute values into an {@link attributesProxy}. Also gets the details on how to handle all attributes from the master {@link cascades} object and.
* @memberof Sheetworker Aliases
* @param {Object} args
* @param {string[]} [args.props=baseGet] - Array of attribute names to get the value of. Defaults to {@link baseGet} if not passed.
* @param {repeatingSectionDetails} sectionDetails - Array of details about a section to get the IDs for and attributes that need to be gotten.
* @param {function(attributesProxy,sectionObj,expandedCascade):void} args.callback - The function to call after the attribute values have been gotten. An {@link attributesProxy} is passed to the callback along with a {@link sectionObj} and {@link expandedCascade}.
* @example
* //Get every K-scaffold linked attribute on the sheet
* k.getAllAttrs({
* callback:(attributes,sections,casc)=>{
* //Work with the attributes as you please.
* attributes.some_attribute = 'a value';
* attributes.set();//Apply our change
* }
* })
*/
const getAllAttrs = function({props=baseGet,sectionDetails=repeatingSectionDetails,callback}){
getSections(sectionDetails,(repeats,sections)=>{
getAttrs([...props,...repeats],(values)=>{
const casc = expandCascade(cascades,sections);
const attributes = createAttrProxy(values,sections,casc);
orderSections(attributes,sections);
callback(attributes,sections,casc);
})
});
};
kFuncs.getAllAttrs = getAllAttrs;
/**
* Alias for [getSectionIDs()](https://wiki.roll20.net/Sheet_Worker_Scripts#getSectionIDs.28section_name.2Ccallback.29) that allows you to iterate through several functions at once. Also assembles an array of repeating attributes to get.
* @memberof Sheetworker Aliases
* @param {object[]} sectionDetails - Array of details about a section to get the IDs for and attributes that need to be gotten.
* @param {string} sectionDetails.section - The full name of the repeating section including the `repeating_` prefix.
* @param {string[]} sectionDetails.fields - Array of field names that need to be gotten from the repeating section
* @param {function(string[],sectionObj)} callback - The function to call once all IDs have been gotten and the array of repating attributes to get has been assembled. The callback is passed the array of repating attributes to get and a {@link sectionObj}.
* @example
* // Get some section details
* const sectionDetails = {
* {section:'repeating_equipment',fields:['name','weight','cost']},
* {section:'repeating_weapon',fields:['name','attack','damage']}
* };
* k.getSections(sectionDetails,(attributeNames,sections)=>{
* console.log(attributeNames);// => Array containing all row specific attribute names
* console.log(sections);// => Object with arrays containing the row ids. Indexed by section name (e.g. repeating_eqiupment)
* })
*/
const getSections = function(sectionDetails,callback){
let queueClone = _.clone(sectionDetails);
const worker = (queue,repeatAttrs=[],sections={})=>{
let detail = queue.shift();
getSectionIDs(detail.section,(IDs)=>{
sections[detail.section] = IDs;
IDs.forEach((id)=>{
detail.fields.forEach((f)=>{
repeatAttrs.push(`${detail.section}_${id}_${f}`);
});
});
repeatAttrs.push(`_reporder_${detail.section}`);
if(queue.length){
worker(queue,repeatAttrs,sections);
}else{
callback(repeatAttrs,sections);
}
});
};
if(!queueClone[0]){
callback([],{});
}else{
worker(queueClone);
}
};
kFuncs.getSections = getSections;
// Sets the attributes while always calling with {silent:true}
// Can be awaited to get the values returned from _setAttrs
/**
* Alias for [setAttrs()](https://wiki.roll20.net/Sheet_Worker_Scripts#setAttrs.28values.2Coptions.2Ccallback.29) that sets silently by default.
* @memberof Sheetworker Aliases
* @alias setAttrs
* @param {object} obj - The object containting attributes to set
* @param {boolean} [vocal=false] - Whether to set silently (default value) or not.
* @param {function()} [callback] - The callback function to invoke after the setting has been completed. No arguments are passed to the callback function.
* @example
* //Set some attributes silently
* k.setAttrs({attribute_1:'new value'})
* //Set some attributes and triggers listeners
* k.setAttrs({attribute_1:'new value',true})
* //Set some attributes and call a callback function
* k.setAttrs({attribute_1:'new value'},null,()=>{
* //Do something after the attribute is set
* })
*/
const set = function(obj,vocal=false,callback){
setAttrs(obj,{silent:!vocal},callback);
};
kFuncs.setAttrs = set;
const generateCustomID = function(string){
if(!string.startsWith('-')){
string = `-${string}`;
}
rowID = generateRowID();
let re = new RegExp(`^.{${string.length}}`);
return `${string}${rowID.replace(re,'')}`;
};
/**
* Alias for generateRowID that adds the new id to the {@link sectionObj}. Also allows for creation of custom IDs that conform to the section ID requirements.
* @memberof Sheetworker Aliases
* @name generateRowID
* @param {sectionObj} sections
* @param {string} [customText] - Custom text to start the ID with. This text should not be longer than the standard repeating section ID format.
* @returns {string} - The created ID
* @example
* k.getAllAttrs({
* callback:(attributes,sections,casc)=>{
* //Create a new row ID
* const rowID = k.generateRowID('repeating_equipment',sections);
* console.log(rowID);// => repeating_equipment_-p8rg908ug0suzz
* //Create a custom row ID
* const customID = k.generateRowID('repeating_equipment',sections,'custom');
* console.log(customID);// => repeating_equipment_-custom98uadj89kj
* }
* });
*/
const _generateRowID = function(section,sections,customText){
let rowID = customText ?
generateCustomID(customText) :
generateRowID();
section = section.match(/^repeating_[^_]+$/) ?
section :
`repeating_${section}`;
sections[section] = sections[section] || [];
sections[section].push(rowID);
return `${section}_${rowID}`;
};
kFuncs.generateRowID = _generateRowID;
/**
* An alias for [Roll20's getTranslationByKey](https://wiki.roll20.net/Sheet_Worker_Scripts#getTranslationByKey.28.5Bkey.5D.29) that also supports data-i18n-vars syntax replacement and returns the translation key if no value is found instead of `false`.
* @memberof Sheetworker Aliases
* @name getTranslationByKey
* @param {string} key - The translation key to look up.
* @param {string[]} [variables = []] - An array of variable values to replace variable indexes with.
* @returns {string}
*/
const _getTranslationByKey = (key,variables = []) => {
let translate = getTranslationByKey(key) || key;
console.warn('getTranslationByKey',getTranslationByKey(key));
console.warn('translate:',translate);
variables.forEach((v,i) => {
translate = translate.replace(new RegExp(`\\{\\{${i}\\}\\}`,'g'),v);
});
return translate;
}
kFuncs.getTranslationByKey = _getTranslationByKey;
/**
* Assembles the roll string from the roll object
* @param {object} rollObj - object describing the roll
* @param {string} [rollStart = '@{template_start}'] - The string to start the roll with.
* @returns {string}
*/
const assembleRoll = (rollObj,rollStart = kFuncs.defaultRollStart) => {
return Object.entries(rollObj).reduce((str,[field,content])=>{
return str += content ?
` {{${field}=${content}}}` :
'';
},`${rollStart}`);
};
/**
* @typedef {Object} kRoll
* @property {Object} roll - The roll object returned by [Roll20's startRoll](https://wiki.roll20.net/Custom_Roll_Parsing#Sheetworker_Functions).
* @property {Function} roll.finish - Finishes the associated roll passing it the computeObj and rollId.
* @property {Object} computeObj - object for storing manipulations to the roll. Assign manipulations to this, DO NOT reassign it to a new object.
*/
/**
*
* @param {object} rollObj - Object specifying the fields to pass to the rolltemplate. Object keys are field names. Object values are the field values.
* @param {string} [startString = '@{template_start}'] - Text that should be prepended to the roll string that results from rollObj.
* @returns {kRoll}
*/
const _startRoll = async (rollObj,startString) => {
const rollString = assembleRoll(rollObj,startString);
const roll = await startRoll(rollString);
const computeObj = {};
roll.finish = () => {
finishRoll(roll.rollId,computeObj);
};
return {roll, computeObj};
};
kFuncs.startRoll = _startRoll;/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/
/*jshint -W014,-W084,-W030,-W033*/
const listeners = {};
/**
* The array of attribute names that the k-scaffold gets by default. Does not incude repeating attributes.
* @memberof Variables
* @var
* @type {array}
*/
const baseGet = Object.entries(cascades).reduce((memo,[attrName,detailObj])=>{
if(!/repeating/.test(attrName) && detailObj.type !== 'action'){
memo.push(detailObj.name);
}
if(detailObj.listener){
listeners[detailObj.listener] = detailObj.listenerFunc;
}
return memo;
},[]);
kFuncs.baseGet = baseGet;
const registerEventHandlers = function(){
on('sheet:opened',updateSheet);
debug({funcKeys:Object.keys(funcs),funcs});
//Roll20 change and click listeners
Object.entries(listeners).forEach(([event,funcName])=>{
if(funcs[funcName]){
on(event,funcs[funcName]);
}else{
debug(`!!!Warning!!! no function named ${funcName} found. No listener created for ${event}`,true);
}
});
log(`kScaffold Loaded`);
};
setTimeout(registerEventHandlers,0);//Delay the execution of event registration to ensure all event properties are present.
/**
* Function to add a repeating section when the add button of a customControlFieldset or inlineFieldset is clicked.
* @memberof Sheetworkers
* @param {object} event - The R20 event object
*/
const addItem = function(event){
let [,,section] = parseClickTrigger(event.triggerName);
section = section.replace(/add-/,'');
getAllAttrs({
callback:(attributes,sections,casc) => {
let row = _generateRowID(section,sections);
debug({row});
attributes[`${row}_name`] = '';
setActionCalls({attributes,sections});
const trigger = cascades[`fieldset_repeating_${section}`];
if(trigger){
if(trigger.addFuncs){
trigger.addFuncs.forEach((funcName) => {
if(funcs[funcName]){
funcs[funcName]({attributes,sections,casc,trigger,newRow:row});
}
});
}
if(Array.isArray(trigger.affects)){
attributes.queue.push(...trigger.affects);
}
}
attributes.set({attributes,sections,casc});
}
});
};
funcs.addItem = addItem;/**
* The default tab navigation function of the K-scaffold. Courtesy of Riernar. It will add `k-active-tab` to the active tab-container and `k-active-button` to the active button. You can either write your own CSS to control display of these, or use the default CSS included in `scaffold/_k.scss`. Note that `k-active-button` has no default CSS as it is assumed that you will want to style the active button to match your system.
* @memberof Sheetworkers
* @param {Object} trigger - The trigger object
* @param {object} attributes - The attribute values of the character
*/
const kSwitchTab = function ({ trigger, attributes }) {
const [container, tab] = (
trigger.name.match(/nav-tabs-(.+)--(.+)/) ||
[]
).slice(1);
$20(`[data-container-tab="${container}"]`).removeClass('k-active-tab');
$20(`[data-container-tab="${container}"][data-tab="${tab}"]`).addClass('k-active-tab');
$20(`[data-container-button="${container}"]`).removeClass('k-active-button');
$20(`[data-container-button="${container}"][data-button="${tab}"]`).addClass('k-active-button');
const tabInputName = `${container.replace(/\-/g,'_')}_tab`;
if(persistentTabs.indexOf(tabInputName) > -1){
attributes[tabInputName] = trigger.name;
}
}
registerFuncs({ kSwitchTab });
/**
* Sets persistent tabs to their last active state
* @memberof Sheetworkers
* @param {object} attributes - The attribute values of the character
*/
const kTabOnOpen = function({trigger,attributes,sections,casc}){
if(typeof persistentTabs === 'undefined') return;
persistentTabs.forEach((tabInput) => {
const pseudoTrigger = {name:attributes[tabInput]};
kSwitchTab({trigger:pseudoTrigger, attributes});
});
};
registerFuncs({ kTabOnOpen },{type:['opener']});
return kFuncs;
}());
const actionAttributes = ["strength_action","close_combat_action","endure_action","force_action","agility_action","mobility_action","ranged_combat_action","stealth_action","wits_action","scout_action","survival_action","tech_action","empathy_action","leadership_action","manipulation_action","medicine_action","repeating_weapons_$X_action","critical_injuries_action","npc_untrained_skills_action","repeating_npcs_$X_npc_untrained_skills_action","repeating_npcs_$X_close_combat_action","repeating_npcs_$X_endure_action","repeating_npcs_$X_force_action","repeating_npcs_$X_mobility_action","repeating_npcs_$X_ranged_combat_action","repeating_npcs_$X_stealth_action","repeating_npcs_$X_scout_action","repeating_npcs_$X_survival_action","repeating_npcs_$X_tech_action","repeating_npcs_$X_leadership_action","repeating_npcs_$X_manipulation_action","repeating_npcs_$X_medicine_action","repeating_npcs_$X_weapons_action","decrease_threat_action","increase_threat_action","swarm_compendium_attack_action","swarm_attack_action","maneuverability_action","armor_action"];const attributeSkills = {"strength":["close combat","endure","force"],"agility":["mobility","ranged combat","stealth"],"wits":["scout","survival","tech"],"empathy":["leadership","manipulation","medicine"]};const itemCategories = ["Talents","Armor","Gear","NPCs","Weapons"];const specialCategories = {};const maxAttr = [];const sectionLookup = {};const tabs = ["character","challenge","npc","gm","faction","haven","travel log","vehicle"];const dynamicSelects = {".crew-select":[{"value":"","data-i18n":"none","selected":"","condition":"static","section":"repeating_crew"},{"value":"@{repeating_crew_$x_name}","condition":"dynamic","section":"repeating_crew"},{"value":"query","data-i18n":"query","condition":"isrepeating","section":"repeating_crew"}]};const dynamicAttributes = {".crew-select":["repeating_weapons_$X_user"]};const dynamicSources = {"repeating_crew":[".crew-select"],"repeating_crew_$x_name":[".crew-select"]};
/**
* Assembles and encodes the push data.
* @param {object} results - The results details
* @param {object} rollObj - The object detailing the roll that was sent.
*/
const assemblePushData = (results,rollObj) => {
let addlStress = 1;
const pushObj = Object.entries(rollObj).reduce((memo,[key,val]) => {
if(/(?:base|stress)_/.test(key)){
memo[key] = results[key].result === 6 ?
'[[6]]' :
`[[${results[key].expression}]]`;
if(/stress/.test(key)){
addlStress++;
}
}else if(
key !== 'successes' &&
key !== 'panic' &&
key !== 'push_through'
){
memo[key] = val
}
return memo;
},{});
pushObj[`stress_${addlStress}`] = '[[1d6]]';
const pushString = k.escape(pushObj);
k.debug({pushString});
return pushString;
};/**
* Assembles the roll string from the roll object
* @param {object} rollObj - object describing the roll
* @param {string} [rollStart = '@{template_start}'] - The string to start the roll with.
* @returns {string}
*/
const assembleRoll = (rollObj,rollStart = '@{template_start} {{successes=[[0[computed value]]]}} {{messed_up=[[0[computed value]]]}} {{push_label=^{push}}} {{push_through=[[0[computed value]]]}}') => {
return Object.entries(rollObj).reduce((str,[field,content])=>{
return str += content ?
` {{${field}=${content}}}` :
'';
},`${rollStart}`);
};/**
* Calculates how many dice to roll based on skill, attribute, and stress.
* @param {string} attrName - The reference to the attribute including section and rowID for repeating attribute
* @param {string} skillName - The name of the skill to roll
* @param {attributeProxy} attributes - The attributes object provided by the K-scaffold
* @returns {object}
*/
const calcDice = async ({attrName,skillName,attributes,sections,dieType = 'base',innateBonus=0,innateStress = 0}) => {
const skillDice = (attributes[skillName.replace(/ /g,'_')] || 0) + innateStress;
const attrDice = attributes.sheet_type === 'npc' ?
0 :
attributes[attrName] || 0;
const bonusDice = (+( await k.extractQueryResult(k.getTranslationByKey('roll bonus query')) ) || 0) + (+innateBonus || 0) + getGearMods(skillName,attributes,sections);
const injuryPenalty = sections.repeating_injury.reduce((tot,id) => {
return tot + (+attributes[`repeating_injury_${id}_penalty`] || 0);
},0);
let baseDice = dieType === 'base' ?
(( attrDice) + (skillDice) + bonusDice + injuryPenalty) :
0;
let stressDice = attrName === 'armor' ?
0 :
dieType === 'stress' ?
(( attributes[attrName] || 0 ) + (attributes[skillName] || 0) + bonusDice) :
attributes.stress;
if(baseDice < 0){
stressDice = Math.max(0, stressDice + baseDice);
baseDice = 0;
}
const totalDice = (num,typ) =>
[...Array(num).keys()].reduce((obj,n) => {
obj[`${typ}_${n+1}`] = '[[1d6]]';
return obj;
},{});
const baseObj = totalDice(baseDice,'base');
const stressObj = totalDice(stressDice,'stress');
if(Object.keys(baseObj).length || Object.keys(stressObj).length){
return {
...baseObj,
...stressObj
};
}else{
return {no_dice:true}
}
}/**
* Executes the roll. Uses a callback if any computations are required.
* @param {object} rollObj - Object describing the roll fields to be used
* @param {object} attributes - The character attributes
* @param {object[]} sections - The sections array
* @returns {Promise<object[]>} - Resolves to array with index 0 being the roll results object and index 1 being the computeObj with success/panics precalculated.
*/
const executeRoll = async ({rollObj,customString,attributes,sections}) => {
const {roll,computeObj} = await k.startRoll(rollObj,customString);
calcSuccess(roll.results,rollObj,computeObj);
return [roll, computeObj];
};/**
* Processes the push information and constructs the roll to be pushed.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const pushRoll = async function({trigger,attributes,sections,casc}){
if(!trigger.originalRollId) return;
k.debug('pushing');
attributes.stress = Math.min(attributes.stress + 1, 10);
const pushData = k.unescape(trigger.originalRollId);
const [roll,computeObj] = await executeRoll({rollObj:pushData,customString:'@{template_start} {{successes=[[0[computed value]]]}}',attributes,sections});
roll.finish();
};
k.registerFuncs({pushRoll});/**
* calculates the number of successes in a roll result
* @param {object} results - The results object.
* @returns
*/
const calcSuccess = (results = {},rollObj,computeObj) => {
const successPanic = Object.entries(results).reduce((memo,[key,obj]) => {
if(/(?:base|stress)_/.test(key)){
if(obj.result === 1 && /stress/.test(key)){
memo.messed_up++;
}else if(obj.result === 6){
memo.successes++;
}
}
return memo;
},{successes:0,messed_up:0});
if(!successPanic.messed_up){
successPanic.push_through = assemblePushData(results,rollObj);
}
Object.assign(computeObj,successPanic);
};const d66Roll = async (extraText = '') => {
const {
rollId: tableID,
results
} = await startRoll(`!{{table=[[[[1d6]][[1d6]]]]}} ${extraText}`);
finishRoll(tableID);
return results;
}
/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/
/*jshint -W014,-W084,-W030,-W033*/
const handleCompendiumDrop = function({attributes,sections,casc}){
clearDropAttributes();
let data = parseDropData(attributes.drop_data,attributes,sections,casc);
if(!data) return;
k.debug({data});
compendiumLookup({
origBlock:data,
attributes,sections,casc,
callback:async (lookupObj)=>{
k.debug({'threat data':data});
await processDropData({data:lookupObj,attributes,sections,casc});
k.debug('Drop processing complete');
// Ensure that dropped values don't get reset by other calculations
const updateKeys = Object.keys(lookupObj);
const iterateQueue = [...attributes.queue];
iterateQueue.forEach((q,i) =>{
if(updateKeys.includes(`data-cs-${q}`)){
const qI = attributes.queue.indexOf(q);
attributes.queue.splice(qI,1);
}
});
attributes.sheet_version = k.version;
attributes.encumbrance = calcEncumbrance({attributes,sections});
k.setActionCalls({attributes,sections});
attributes.set();
}
});
};
k.registerFuncs({handleCompendiumDrop});
const parseDropData = function(drop_data,attributes,sections,casc){
k.debug('parsing drop data');
k.debug({drop_data:`"${drop_data}"`});
try{
let data = JSON.parse(drop_data);
data.Name = attributes.drop_name;
data = Object.entries(data)
.reduce((memo,[key,val])=>{
if(val){
if(typeof val === 'string' && val.startsWith('[{')){
val = JSON.parse(val);
}
memo[key] = val;
}
return memo;
},{});
return processSpecialCategories(data,attributes,sections,casc);
}catch(err){
k.debug({'Invalid Drop Data! Drop aborted. Error:':err,drop_data},true);
return false;
}
};
const clearSheet = function(attributes,sections,casc){
Object.entries(sections).forEach(([section,idArray])=>{
idArray.forEach((id)=>{
k.removeRepeatingRow(`${section}_${id}`,attributes,sections);
});
});
Object.keys(attributes.attributes).forEach((attr)=>{
if(casc[`attr_${attr}`] && !/^(?:custom_)?bar_\d$/.test(attr)){
attributes[attr] = casc[`attr_${attr}`].hasOwnProperty('defaultValue') ?
casc[`attr_${attr}`].defaultValue :
'';
}
})
};
const clearDropAttributes = function(){
k.setAttrs({drop_name:'',drop_data:''});
};
const processDropData = function({data, attributes, sections, casc,section=''}){
section = section ? `${section}_` : '';
const worker = async (queue) => {
let [key,val] = queue.shift();
try{
let setKey = key.replace(/^(?:data-)?cs(?:list)?-/,'');
if(typeof val === 'string' && val.startsWith('[{')){
val = JSON.parse(val);
}
if(!Array.isArray(val) && (key.startsWith('cs-') || key.startsWith('data-cs-'))){
await k.pseudoQuery();
attributes[`${section}${setKey}`] = val;
if(maxAttr.includes(setKey)){
attributes[`${section}${setKey}_max`] = val;
}
}else if(Array.isArray(val) && key.startsWith('data-')){
let lookupKey = key.replace(/data-(?:cs(?:list)?-)?/,'');
if(repeatProcessors[lookupKey]){
k.debug(`processing ${lookupKey}`);
await repeatProcessors[lookupKey](lookupKey,val,attributes,sections,casc);
}else if(key.startsWith('data-cslist-')){
await k.pseudoQuery();
attributes[`${section}${setKey}`] = val.map((o)=>o.name).join(', ');
}else if(key === 'data-content'){
await k.pseudoQuery();
attributes[`${section}description`] = val.reduce((textArr,content)=>{
if(content.heading){
textArr.push(content.heading);
}
if(content.content){
let text = /list/.test(content.type) ? `• ${content.content}` : content.content;
textArr.push(text);
}
return textArr;
},[]).join('\n')
.replace(/\n{2,}/,'\n')
.replace(/\n+$/,'');
}
}
}catch(err){
k.debug({[`Invalid JSON entered for ${key} on ${data.display_name}`]:err,JSON:val});
}
if(queue.length){
return worker(queue);
}else{
return true;
}
};
return worker(Object.entries(data));
};
/**
* Does the basic prepwork for repeating section drops by creating the rowID and grabbing the item to work on. Passes the selected itemObj and the created section details to the callback function
* @param {string} lookupKey
* @param {array} arr
* @param {object} sections
* @param {function} callback
*/
const repeatWorker = async function(lookupKey,arr,sections,casc,callback){
const type = sectionLookup[lookupKey] || lookupKey.toLowerCase();
const worker = async (queue)=>{
const itemObj = queue.shift();
itemObj['data-cs-collapse'] = 1;
const section = k.generateRowID(type,sections);
addRowToCasc(section,casc);
await callback(itemObj,section);
if(queue.length){
return worker(queue);
}else{
return true;
}
};
return await worker([...arr]);
}
/**
* Adds the cascade objects for the indicated row to the casc object.
* @param {string} section - The row information (repeating section, and rowID)
* @param {object} casc - The cascade object for this particular character
* @param {number|string} [previousValue] - What to set the previous value to
*/
const addRowToCasc = function(section,casc,previousValue){
k.debug(`Adding ${section} to cascades`);
const match = section.match(/(.+?_.+?)_(.+)/);
match.shift();
const [repSection,rowID] = match;
k.debug({repSection,rowID});
Object
.entries(k.cascades)
.forEach(([key,obj]) => {
if(key.startsWith(`attr_${repSection}`)){
const newObj = {...obj};
newObj.name = newObj.name.replace(/\$X/,rowID)
const newKey = key.replace(/\$X/,rowID);
newObj.previousValue = previousValue === undefined ?
newObj.defaultValue :
previousValue;
newObj.affects = newObj.affects.map(a => a.replace(/\$X/,rowID));
casc[newKey] = newObj;
k.debug({[`casc[${newKey}]`]:casc[newKey]});
}
});
};/*jshint esversion: 11, laxcomma:true, eqeqeq:true*/
/*jshint -W014,-W084,-W030,-W033*/
//Initiate a compendium lookup
//Start of the actual compendium lookup functions
//Function to initiate the lookup. Parses the statblock to figure out what needs to be looked up in the compendium, and what attribute should be filtered for based on the category.
//ARGUMENTS
//statblock (object): base object dropped from the compendium
//callback (function): A function that will use the parsed compendium lookup data to finish the drag and drop of the item
//The callback function receives the parsed statblock as an argument
const compendiumLookup = function({queue, callback, origBlock, attributes, sections, casc, pass = 0}) {
pass++;
origBlock = origBlock || queue[0];
queue = queue || [origBlock];
let searchArray = [];
queue.forEach((statblock)=>{
searchArray = itemCategories.reduce((m, type) => {//Construct an array of items to search for.
let searchType = specialCategories[type] || type;
if (statblock[`data-${type}`]){
let searchNames = statblock[`data-${type}`].map((obj) => obj.name || obj['data-cs-name'] || '')
.join('|')
.replace(/\|{2,}/g,'')
.replace(/\|$/,'');
if(searchNames.length > 0){
let searchString = `Category:${searchType} data-cs-name:${searchNames}`;
m.push(searchString);
}
}
return m;
}, searchArray);
k.debug({searchArray});
if(searchArray.length){
lookupBurndown(statblock, searchArray, callback, origBlock, attributes, sections, casc,pass);
}else{
callback(origBlock);
}
});
};
//Actually queries the compendium to get details on the items in each category using the searchArray assembled in compendiumLookup
//ARGUMENTS
//statblock (object): the original object dropped from the compendium
//callback (function): A function that will use the parsed compendium lookup data to finish the drag and drop of the item
//The callback function receives the parsed statblock as an argument
const lookupBurndown = function(statblock, searchArray, callback, origBlock, attributes, sections, casc,pass) {
getCompendiumQuery(searchArray, (dataArr) => {
k.debug({dataArr});
const expansionIDs = dataArr
.reduce( (arr,obj)=>{
arr.push(k.value(obj.data.Expansion));
return arr;
},[])
.sort((a,b) => b - a);
itemCategories.forEach((oCategory) => {
const category = statblock[`data-${oCategory}`] ?
oCategory :
oCategory.toLowerCase();
if (statblock[`data-${category}`]) {
origBlock[`data-${category}`] = statblock[`data-${category}`].map((obj) => {
const fullItem = getItemDetails(obj, dataArr, expansionIDs);
fullItem['data-cs-name'] = fullItem['data-cs-name'] || fullItem.name;
return fullItem;
});
}
});
const queue = additionalLookups(statblock,origBlock);
if(queue.length /*&& pass < 2*/){
compendiumLookup({queue,callback,origBlock, attributes, sections, casc,pass});
}else{
callback(origBlock);
}
});
};
const additionalLookups = function(statblock,origBlock){
return Object.entries(statblock).reduce((memo,[prop,arr])=>{
if(prop.startsWith('data-') && Array.isArray(arr)){
let nestedData = arr.reduce((m,obj)=>{
Object.entries(obj).forEach(([nProp,nVal])=>{
/*commented code shouldn't be needed
if(
nProp.startsWith('data-') &&
typeof nVal === 'string' &&
nVal.startsWith('[{')
){
try{
let jArr = JSON.parse(nVal);
if(Array.isArray(jArr)){
jArr = jArr.map((o)=>{
o.datasource = obj['cs-name'] || obj.Category;
if(!o.datasource){
delete o.datasource;
}
return o;
});
origBlock[nProp] = origBlock[nProp] ?
[...origBlock[nProp],...jArr] :
[...jArr];
m.data[nProp] = jArr;
m.nested = true;
}
}catch(err){
//if the parse failed, do nothing
}
}else */
if(nProp === 'data-features'){
try{
if(typeof nVal === 'string'){
k.debug('string data-feature detected');
nVal = JSON.parse(nVal);
}
nVal.forEach((feature)=>{
if(!origBlock[`data-${feature.category}`] || origBlock[`data-${feature.category}`].every((o)=>o['data-cs-name'].toLowerCase() !== feature.name.toLowerCase())){
m.nested = true;
m.data[`data-${feature.category}`] = m.data[`data-${feature.category}`] || [];
m.data[`data-${feature.category}`].push({'data-cs-name':feature.name});
}
});
}catch(err){
k.debug({[`Invalid data-feature on ${obj['data-cs-name']}`]:err,'data-feature':nVal},true);
}
}
});
return m;
},{data:{},nested:false});
if(nestedData && nestedData.nested){
memo.push(nestedData.data);
}
}
return memo;
},[]);
};
//Finds the compendium item that most precisely matches the needs of the compendium item based on expansion ID and name property.
//If nothing matches based on expansion ID, simply returns the first item with appropriate name property.
//ARGUMENTS
//itemObj (object): the data on the Item to return that is included in the base statblock
//dataArr (array): The compendium items that were returned from getCompendiumQuery
const getItemDetails = function(itemObj, dataArr, expansionIDs) {
let objName = itemObj['data-cs-name'] || itemObj.name;
let compendiumObj;
expansionIDs.find((id) => {
compendiumObj = dataArr.find((dataObj) => k.value(dataObj.data.Expansion) === id &&
dataObj.data['data-cs-name'] === objName);
if (compendiumObj) {
return true;
} else {
return false;
}
});
if (!compendiumObj) { //If we didn't find an object matching the expansion pathways and the object name, just find the first item with a matching name
compendiumObj = dataArr.find((dataObj) =>
dataObj.data['data-cs-name'] === objName);
if (!compendiumObj) { //If there still isn't a matching compendium object, return the original Item
return itemObj;
}
}
Object.keys(compendiumObj.data).forEach((key) => {
itemObj[key] = itemObj[key] || compendiumObj.data[key];
});
return itemObj;
};/**
* Handles dropping of repeating section items that need no special handling. Provided as part of the compendium infrastructure as it is useful for nearly any project and can serve as a template for more specific drop functions.
* @param {string} lookupKey - The section name
* @param {object[]} arr - Array of data to parse
* @param {attributesProxy} attributes - The attributes for the character
* @param {object} sections - The object with keys equal to repeating section names and values of arrays of repeating ids
* @param {object} casc - The cascade object
* @param {array} sectionsToQuery - sections that need further user input before drop completes
*/
const basicDrop = (lookupKey,arr,attributes,sections,casc,sectionsToQuery) => {
return repeatWorker(lookupKey,arr,sections,casc,async (itemObj,section)=>{
await processDropData({data:itemObj,attributes,sections,casc,sectionsToQuery,section});
});
};/**
* Does all the generic handling for NPC type dropped items (e.g. Antagonists in Scion and Threats in TCF)
* @param {object} data - the data received from the drop
* @param {AttributesProxy} attributes - The attributes object from the K-scaffold
* @param {object} sections - The sections object form the k-scaffold
* @param {object} casc - The cascade object form the k-scaffold
*/
const npcHandler = (data,attributes,sections,casc) => {
clearSheet(attributes,sections,casc);
attributes.sheet_type = data?.Category?.replace(/s$/,'').toLowerCase() || 'pc';
attributes.allow_push = 0;
const tokenObj = {
width:70,
height:70,
};
// token bar association
const barNums = [1,2,3];
const barAttrs = ['hit_points','willpower_points'];
barAttrs.forEach(attr => {
const dataAttr = `data-cs-${attr}`;
if(data[dataAttr]){
const bar = barNums.find(n => attributes[`bar_${n}`] === attr);
tokenObj[`bar${bar}_value`] = data[dataAttr];
tokenObj[`bar${bar}_max`] = data[dataAttr];
data[`data-cs-${bar}_max`] = data[`data-cs-${bar}`];
}
});
if(attributes.sheet_type === 'npc'){
attributes.npc_collapse = 1;
}
setDefaultToken(tokenObj);
k.callFunc('kSwitchTab',{trigger:{name:`nav-tabs-walking-dead--${attributes.sheet_type}`},attributes});
sheetTypeDisplay({attributes});
};
const evalSlots = (itemObj,slots) => {
if(
slots &&
/^\d+\/\d+$/.test(slots)
){
itemObj['data-cs-slots'] = eval(slots);
}
};/**
* Handles dropping of armor and helmets.
* @param {string} lookupKey - The section name
* @param {object[]} arr - Array of data to parse
* @param {attributesProxy} attributes - The attributes for the character
* @param {object} sections - The object with keys equal to repeating section names and values of arrays of repeating ids
* @param {object} casc - The cascade object
* @param {array} sectionsToQuery - sections that need further user input before drop completes
*/
const armorDrop = async (lookupKey,arr,attributes,sections,casc,sectionsToQuery) => {
const proms = arr.map(async itemObj => {
const prefix = 'armor';
['name','protection','penalty'].forEach(key => {
if(itemObj[`data-cs-${key}`]){
itemObj[`data-cs-${prefix}_${key}`] = itemObj[`data-cs-${key}`];
}
delete itemObj[`data-cs-${key}`];
});
await processDropData({data:itemObj,attributes,sections,casc,sectionsToQuery});
});
await Promise.all(proms);
};/**
* function to handle dropping monster attacks
* @param {string} lookupKey - The section name
* @param {object[]} arr - Array of data to parse
* @param {attributesProxy} attributes - The attributes for the character
* @param {object} sections - The object with keys equal to repeating section names and values of arrays of repeating ids
* @param {object} casc - The cascade object
* @param {array} sectionsToQuery - sections that need further user input before drop completes
*/
const weaponDrop = (lookupKey,arr,attributes,sections,casc,sectionsToQuery) => {
return repeatWorker(lookupKey,arr,sections,casc,async (itemObj,section)=>{
itemObj['data-cs-skill'] = itemObj['data-cs-range'] ?
'ranged combat' :
'close combat';
evalSlots(itemObj,itemObj['data-cs-slots']);
await processDropData({data:itemObj,attributes,sections,casc,sectionsToQuery,section});
});
};const tableDrop = (lookupKey,arr,attributes,sections,casc,sectionsToQuery) => {
const tableTypes = {
'Critical Injuries': rollCriticalTable,
'Walker Attacks': swarmCompendiumAttack
};
const table = arr[0];
if(tableTypes[table.Name]){
tableTypes[table.Name]({attributes,sections,casc});
}
return k.pseudoQuery();
};/**
* Handles dropping of gear repeating section items. Does minimal editing of the gear data to make it valid for the sheet.
* @param {string} lookupKey - The section name
* @param {object[]} arr - Array of data to parse
* @param {attributesProxy} attributes - The attributes for the character
* @param {object} sections - The object with keys equal to repeating section names and values of arrays of repeating ids
* @param {object} casc - The cascade object
* @param {array} sectionsToQuery - sections that need further user input before drop completes
*/
const gearDrop = (lookupKey,arr,attributes,sections,casc,sectionsToQuery) => {
return repeatWorker(lookupKey,arr,sections,casc,async (itemObj,section)=>{
evalSlots(itemObj,itemObj[`data-cs-slots`]);
itemObj[`data-cs-quantity`] = itemObj[`data-cs-quantity`] || 1
if(itemObj['data-cs-affects']){
itemObj['data-cs-affects'] = itemObj['data-cs-affects'].toLowerCase();
}
await processDropData({data:itemObj,attributes,sections,casc,sectionsToQuery,section});
});
};/**
* Lookup for what specific drop function to use for a given drop type. Note that the key is the part after `data-` if it is in another compendium item (e)g. in a Monster), or is the same as the Compendium category (minus)anything after a space).
* @var
*/
const repeatProcessors = {
'gear': gearDrop,
'Gear': gearDrop,
'weapons': weaponDrop,
'Weapons': weaponDrop,
'armor': armorDrop,
'Armor': armorDrop,
'rollable tables': tableDrop,
'Rollable Tables': tableDrop,
'rollable': tableDrop,
'Rollable': tableDrop,
'talents': basicDrop,
'Talents': basicDrop
};/**
* Does the system specific handling for specialized drop categories.
* @param {object} data - the data received from the drop
* @param {AttributesProxy} attributes - The attributes object from the K-scaffold
* @param {object} sections - The sections object form the k-scaffold
* @param {object} casc - The cascade object form the k-scaffold
* @returns {object|[]} - The manipulated data object
*/
const processSpecialCategories = (data,attributes,sections,casc) => {
if(!/npcs|vehicles|havens|factions/i.test(data.Category)){
let category = data.Category.replace(/\s.+/,'');
data = {[`data-${category}`]:[data]};
if(data[`data-${category}`]['data-features']){
data[category]['data-features'].forEach((feature)=>{
let cat = k.capitalize(feature.category);
data[`data-${cat}`] = data[`data-${cat}`] || [];
data[`data-${cat}`].push({name:feature.name});
});
}
}else{
npcHandler(data,attributes,sections,casc);
}
return data;
};
/**
* Dispatches an event to a location to add/remove/edit an NPC to it.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const locateNPC = function({trigger,attributes,sections,casc}){
// filter for sheet being npc, and this being the direct effect of a user change.
if(
!trigger.triggerName ||
attributes.sheet_type !== 'npc' ||
(
trigger.name === 'character_name' &&
attributes.character_name === attributes.script_character_name
)
) {
if(trigger.name === 'character_name'){
attributes.script_character_name = '';
}
return;
}
const connectArray = ['npc_haven','npc_faction'].includes(trigger.name) ?
[trigger.name] :
['npc_haven','npc_faction'];
const charName = trigger.name === 'character_name' ?
trigger.previousValue :
attributes.character_name;
if(['npc_haven','npc_faction'].includes(trigger.name) && trigger.previousValue){
k.send(trigger.previousValue,'npcCitizenship',charName,attributes.character_id,attributes,sections);
}
connectArray.forEach(target => {
if(attributes[target]){
k.send(attributes[target],'npcCitizenship',charName,attributes,sections);
}
});
};
k.registerFuncs({locateNPC});/**
* Adds/removes an npc from being a member of a faction/haven
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const npcCitizenship = function({trigger,attributes,sections,casc},npcName,npc,npcSections){
let rowID = sections.repeating_npcs.find(id =>
npcName.toLowerCase() === attributes[`repeating_npcs_${id}_name`].toLowerCase());
if(npc[`npc_${attributes.sheet_type}`] && attributes.character_name.toLowerCase() === npc[`npc_${attributes.sheet_type}`].toLowerCase()){
const row = rowID ?
`repeating_npcs_${rowID}` :
k.generateRowID('repeating_npcs',sections);
Object.entries(npcSyncAttributes).forEach(([source,target]) => {
attributes[`${row}_${target}`] = npc[source];
const thisCasc = casc[`attr_${row}_${target}`];
if(thisCasc){
thisCasc.triggeredFuncs =
thisCasc.triggeredFuncs
.filter(func => func !== 'syncConnectedNPC')
}
})
attributes[`${row}_collapse`] = 1;
const gear = npcSections.repeating_gear.map(id => {
const gearRow = `repeating_gear_${id}`;
return `${npc[`${gearRow}_quantity`]}x ${npc[`${gearRow}_name`]}`;
});
const weapons = npcSections.repeating_weapons.map(id => {
const weaponRow = `repeating_weapons_${id}`;
return `${npc[`${weaponRow}_name`]}`;
});
attributes[`${row}_gear`] = gear.join(', ');
attributes[`${row}_weapons`] = weapons.join(', ');
}else if(attributes.character_name.toLowerCase() !== npc[`npc_${attributes.sheet_type}`].toLowerCase() && rowID){
k.removeRepeatingRow(`repeating_npcs_${rowID}`,attributes,sections);
}
};
k.registerFuncs({npcCitizenship});/**
* object storing the relationship between base NPC and embedded NPC attribute names.
*/
const npcSyncAttributes = {
// "non repeating attribute name": "repeating attribute name"
character_name: 'name',
npc_descriptor: 'descriptor',
character_description: 'description',
character_id: 'character_id'
};
Object.values(attributeSkills).forEach(arr => {
arr.forEach(skillName => npcSyncAttributes[skillName.replace(/ /g,'_')] = skillName.replace(/ /g,'_'));
})
/**
* Synchronizes changes to an embedded NPC with the source NPC
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const syncConnectedNPC = function({trigger,attributes,sections,casc}){
if(
!trigger.triggerName ||
!/^(haven|faction)$/.test(attributes.sheet_type)
) {
return;
}
const [section,rowID] = k.parseTriggerName(trigger.name);
const row = `${section}_${rowID}`;
const targets = trigger.name.includes('name') ?
[trigger.previousValue, attributes[`${row}_name`]] :
[attributes[`${row}_name`]];
const npcAttributes = Object.entries(npcSyncAttributes).reduce((memo,[npcAttr,repeatAttr]) => {
if(npcAttr !== 'character_id'){
memo[npcAttr] = attributes[`${row}_${repeatAttr}`];
}
return memo;
},{});
targets.forEach(targetName => {
if(!targetName) return;
k.send(targetName,'updateNPC',attributes.character_name,attributes.sheet_type,npcAttributes);
})
};
k.registerFuncs({syncConnectedNPC});/**
* updates an npc in response to a data message from a haven/faction
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const updateNPC = function({trigger,attributes,sections,casc},locationName,locationType,updateObj){
if(attributes.sheet_type !== 'npc') return;
if(
attributes[`npc_${locationType}`].toLowerCase() !== locationName.toLowerCase()
){
if(updateObj.character_name.toLowerCase() === attributes.character_name.toLowerCase()){
attributes[`npc_${locationType}`] = locationName;
locateNPC({trigger:{name:`npc_${locationType}`,triggerName:`npc_${locationType}`,previousValue:attributes.attributes[`npc_${locationType}`]},attributes,sections,casc});
}
return;
}
Object.entries(updateObj).forEach(([key,value]) => {
attributes[key] = value;
casc[`attr_${key}`].triggeredFuncs =
casc[`attr_${key}`].triggeredFuncs
.filter(func => func !== 'locateNPC')
});
attributes.script_character_name = attributes.character_name;
};
k.registerFuncs({updateNPC});const havenSyncAttributes = {
'character_name': 'haven_name',
'overall': 'haven_description',
'faction': 'character_name',
capacity: 'haven_capacity',
defense: 'haven_defense'
};
/**
* Dispatches update messages from a faction to a haven.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const claimHaven = function({trigger,attributes,sections,casc}){
// filter for sheet being faction, and this being the direct effect of a user change.
if(
!trigger.triggerName ||
attributes.sheet_type !== 'faction' ||
(
trigger.name === 'character_name' &&
attributes.character_name === attributes.script_character_name
)
) {
if(trigger.name === 'character_name'){
attributes.script_character_name = '';
}
return;
}
const targets = trigger.name === 'haven_name' ?
[trigger.previousValue,attributes.haven_name] :
[attributes.haven_name];
const havenAttributes = Object.entries(havenSyncAttributes).reduce((memo,[havenAttr,factionAttr]) => {
if(havenAttr !== 'character_id'){
memo[havenAttr] = attributes[factionAttr];
}
return memo;
},{});
const callback = trigger.name.includes('name') ?
'annexedBy' :
'';
targets.forEach(targetName => {
if(!targetName) return;
const func = targetName === attributes.haven_name ?
'updateHaven' :
'leaveFaction';
k.send(targetName,func,attributes.character_name,havenAttributes,callback);
})
};
k.registerFuncs({claimHaven});/**
* updates a haven in response to a data message from a faction
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const updateHaven = function({trigger,attributes,sections,casc},faction,updateObj,callback){
if(attributes.sheet_type !== 'haven') return;
if(callback){
attributes.faction = faction;
if(updateObj.character_name === attributes.character_name){
k.callFunc(callback,{trigger:{name:'faction'},attributes,sections,casc});
}
return;
}
Object.entries(updateObj).forEach(([key,value]) => {
attributes[key] = value;
casc[`attr_${key}`].triggeredFuncs =
casc[`attr_${key}`].triggeredFuncs
.filter(func => func !== 'annexedBy')
});
attributes.script_character_name = attributes.character_name;
};
k.registerFuncs({updateHaven});/**
* Dispatches an update message to a faction from a haven.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const annexedBy = function({trigger,attributes,sections,casc}){
// filter for sheet being haven, and this being the direct effect of a user change.
if(
!trigger.triggerName ||
attributes.sheet_type !== 'haven' ||
(
trigger.name === 'character_name' &&
attributes.character_name === attributes.script_character_name
)
) {
if(trigger.name === 'character_name'){
attributes.script_character_name = '';
}
return;
}
targets = trigger.name === 'faction' ?
[trigger.previousValue,attributes.faction] :
[attributes.faction];
const factionAttributes = Object.entries(havenSyncAttributes).reduce((memo,[havenAttr,factionAttr]) => {
if(factionAttr !== 'character_id'){
memo[factionAttr] = attributes[havenAttr];
}
return memo;
},{});
targets.forEach(targetName => {
if(!targetName) return;
const func = targetName === attributes.faction ?
'updateFaction' :
'releaseHaven';
k.send(targetName,func,attributes.character_name,factionAttributes);
})
};
k.registerFuncs({annexedBy});/**
* Updates the faction based on a call from a haven.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const updateFaction = function({trigger,attributes,sections,casc},havenName,updateObj){
if(attributes.sheet_type !== 'faction') return;
Object.entries(updateObj).forEach(([key,value]) => {
attributes[key] = value;
casc[`attr_${key}`].triggeredFuncs =
casc[`attr_${key}`].triggeredFuncs
.filter(func => func !== 'claimHaven');
});
if(attributes.attributes.haven_name && attributes.attributes.haven_name !== havenName){
k.send(attributes.attributes.haven_name,'updateHaven','',{},'annexedby')
}
attributes.script_character_name = attributes.character_name;
};
k.registerFuncs({updateFaction});/**
* Clears the faction entry on a haven when the haven name entry on that faction no longer matches.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const leaveFaction = function({trigger,attributes,sections,casc},faction){
if(attributes.faction !== faction || attributes.sheet_type !== 'haven') return;
attributes.faction = '';
casc.attr_faction.triggeredFuncs =
casc.attr_faction.triggeredFuncs
.filter(func => func !== 'annexedBy');
};
k.registerFuncs({leaveFaction});/**
* Clears the haven_name entry on a faction when the faction entry on that haven no longer matches.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const releaseHaven = function({trigger,attributes,sections,casc},haven){
if(attributes.haven_name !== haven || attributes.sheet_type !== 'faction') return;
['haven_name','haven_capacity','haven_description','haven_defense'].forEach(attr => {
attributes[attr] = casc[`attr_${attr}`].defaultValue;
casc[`attr_${attr}`].triggeredFuncs =
casc[`attr_${attr}`].triggeredFuncs
.filter(func => func !== 'annexedBy');
});
};
k.registerFuncs({releaseHaven});/**
*
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const storeRow = function({trigger,attributes,sections,casc,newRow}){
attributes[`${newRow}_row`] = newRow.toLowerCase().replace(/repeating_[^_]+_/,'');
};
k.registerFuncs({storeRow});/**
* Checks if the compendium is enabled. If it is, shows the critical injury roll button.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const checkForCompendium = function({trigger,attributes,sections,casc}){
getCompendiumPage('Critical Injuries',(ret) => {
const data = ret[0]?.data || ret.data;
if(data['data-Results']){
$20('.compendium-dependent').removeClass('disabled');
$20('.compendium-independent').addClass('disabled');
}
})
};
k.registerFuncs({checkForCompendium},{type:['opener']});k.version = 1;
k.defaultRollStart = '@{template_start} {{successes=[[0[computed value]]]}} {{messed_up=[[0[computed value]]]}} {{push_label=^{push}}} {{push_through=[[0[computed value]]]}}';
// Roll functions will go here
/**
* Rolls a pool of dice for a skill
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
* @param {object} message - arguments sent via k.send.
* @param {object} message.source - specific trigger specified by the remote call
* @param {object} message.bonusDice - additional dice that should be used
* @param {object} message.bonusStress - additional stress that should be used
* @param {object} message.baseObj - modifications to the rollObj.
*/
const rollPool = async function({trigger,attributes,sections,casc},message = {}){
const {source,baseObj} = message;
let {bonusDice = 0, bonusStress = 0} = message;
trigger = source || trigger;
const passedData = trigger?.originalRollId ?
k.unescape(trigger.originalRollId) :
{};
const skill = trigger.name.replace(/-action/,'').replace(/-/g,' ');
if(skill === 'mobility'){
bonusDice -= Math.abs(attributes.armor_penalty);
}
const rollObj = await calcDice({skillName: skill,attrName: trigger.ability,attributes,sections,innateBonus: bonusDice, innateStress: bonusStress});
rollObj.title = `^{${skill.replace(/_/g,' ')}}`;
Object.assign(rollObj,baseObj);
Object.assign(rollObj,passedData);
const [roll,computeObj] = await executeRoll({rollObj,attributes,sections});
roll.finish()
};
k.registerFuncs({rollPool});
/**
* Rolls weapon attacks for embedded NPCs. Does logic to determine whether to ask for which skill to roll, or which weapon to roll.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const rollRepeatNPCWeapon = function({trigger,attributes,sections,casc}){
};
k.registerFuncs({rollRepeatNPCWeapon});
/**
* Passes message to an NPC to remove the faction/haven when the npc is deleted from a faction/haven
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const exileNPC = function({trigger,attributes,sections,casc}){
const removed = trigger.removedInfo;
const nameKey = Object.keys(removed).find(k => /name$/.test(k));
const npcName = removed[nameKey];
k.send(npcName,'updateNPC',attributes.character_name,attributes.sheet_type,{[`npc_${attributes.sheet_type}`]:''});
};
k.registerFuncs({exileNPC});
/**
* Gets the total gear mods to apply to a skill
* @param {string} skill - the name of the skill
* @param {object} attributes - the scaffold Attribute Proxy
* @param {object} sections - the scaffold sections object
*/
const getGearMods = (skill,attributes,sections) => {
return sections.repeating_gear.reduce((m,id) => {
const row = `repeating_gear_${id}`;
if(attributes[`${row}_affects`] === skill){
m += attributes[`${row}_bonus`];
}
return m;
},0);
}
/**
* Populates a select based on the content of a repeating section or other dynamic content
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const dynamicPopulate = function({trigger,attributes,sections,casc}){
const genericName = trigger.name.replace(/(repeating_.+?_).+?(_.+)/,'$1$x$2');
populateSelects({genericName,attributes,sections,casc});
};
k.registerFuncs({dynamicPopulate});
/**
* populates the dynamic selects on the sheet.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const populateSelects = function({genericName,attributes,sections,casc}){
const selectors = genericName ?
dynamicSources[genericName] :
Object.keys(dynamicSelects);
selectors.forEach(selector => {
const details = dynamicSelects[selector];
const optionsArray = details.reduce((arr,origObj) => {
const obj = {...origObj};
const section = obj.section;
const condition = obj.condition;
delete obj.section;
delete obj.condition;
if(condition === 'dynamic' && section){
sections[section].forEach(id => {
const secObj = {...obj};
secObj['value'] = secObj['value']?.replace(/\$x/g,id);
secObj['data-i18n'] = secObj['data-i18n']?.replace(/\$x/g,id);
addOption(arr,secObj,attributes,sections);
})
}else if(
condition === 'static' ||
(
condition === 'isrepeating' &&
section &&
sections[section].length
)
){
addOption(arr,obj,attributes,sections);
}
return arr;
},[]);
populateListOptions({
elemSelector: selector,
optionsArray
});
dynamicAttributes[selector].forEach(full => {
const [section,,attr] = k.parseTriggerName(full);
if(section){
sections[section].forEach(id =>
updateSelect(`${section}_${id}_${attr}`,optionsArray,attributes,casc));
}else{
updateSelect(attr,optionsArray,attributes,casc);
}
})
})
};
k.registerFuncs({populateSelects},{type:['opener']});
const updateSelect = (attr,optionsArray,attributes,casc) => {
attributes[attr] = optionsArray.some(obj => obj.value === attributes[attr]) ?
attributes[attr] :
(casc[`attr_${attr}`].defaultValue || '');
};
const addOption = (memo,obj,attributes,sections) => {
['value','data-i18n'].forEach(prop => {
if(obj[prop]){
obj[prop] = k.parseMacro(obj[prop],attributes,sections);
}
});
if(obj['data-i18n']){
obj.label = k.getTranslationByKey(obj['data-i18n']);
}
delete obj['data-i18n'];
delete obj.selected
if(obj.value || obj.label){
memo.push(obj);
}
}
/**
* calculates whether an NPC is trained, expert, master.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const calcNPCTraining = function({trigger,attributes,sections,casc}){
const [section,rowID] = k.parseTriggerName(trigger.name);
const row = section ?
`${section}_${rowID}_` :
'';
// for untrained, we want to check if every skill is untrained, otherwise, just if at least one is.
const action = trigger.name.match(/untrained/) ?
'every' :
'some';
const isTrained = Object.values(attributeSkills).reduce((arr,skills) => {
arr.push(...skills);
return arr;
},[])
[action](skill => attributes[`${row}${skill.replace(/ /g,'_')}`] === trigger.dice);
return isTrained ?
1 :
0;
};
k.registerFuncs({calcNPCTraining });
/**
* Rolls skill checks for NPCs
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const rollUntrained = function({trigger,attributes,sections,casc}){
const [section,rowID] = k.parseTriggerName(trigger.name);
rollPool({trigger,attributes,sections,casc},{source:{name:'skills'},bonusDice:4});
};
k.registerFuncs({rollUntrained});
/**
* Moves gear items between stored and equipped.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const equipItem = function({trigger,attributes,sections,casc}){
const [section,rowID] = k.parseTriggerName(trigger.name);
const oldRow = `${section}_${rowID}`;
const newRow = k.generateRowID(
section === 'repeating_gear' ?
'repeating_stored-gear' :
'repeating_gear',
sections);
itemSend({trigger:{name:`${oldRow}_equipped`,newRow},attributes,sections,casc});
if(attributes.sheet_type !== 'haven'){
const rowKeys = ['name','collapse','quantity','slots','bonus','description'].forEach(key => {
attributes[`${newRow}_${key}`] = attributes[`${oldRow}_${key}`];
})
attributes[`${newRow}_equipped`] = /stored/.test(newRow) ?
0 :
1;
}
k.removeRepeatingRow(oldRow,attributes,sections);
};
k.registerFuncs({equipItem});
const itemProps = ['name','quantity','slots','bonus','description','collapse']
/**
*
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const itemSend = async function({trigger,attributes,sections,casc}){
const [section,rowID] = k.parseTriggerName(trigger.name);
const row = `${section}_${rowID}`;
const itemJSON = itemProps.reduce((obj,prop) => {
obj[prop] = attributes[`${row}_${prop}`];
return obj;
},{});
const targetAttr = attributes.sheet_type === 'character' ?
'location' :
'owner';
const query = attributes.sheet_type === 'character' ?
k.getTranslationByKey('Where is this item stored') :
k.getTranslationByKey('Who owns this item');
const targetName = await (
!attributes[`${row}_${targetAttr}`] ?
k.extractQueryResult(query) :
k.pseudoQuery(attributes[`${row}_${targetAttr}`])
);
const sourceAttr = attributes.sheet_type === 'character' ?
'owner' :
'location';
attributes[`${trigger.newRow}_${targetAttr}`] = targetName;
itemJSON[sourceAttr] = attributes.character_name;
const source = {
type: attributes.sheet_type,
section,
id: attributes[`${row}_row`]
};
attributes.set();
k.send(targetName,'itemReceive',itemJSON,source)
};
k.registerFuncs({itemSend});
/**
*
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const itemReceive = function({trigger,attributes,sections,casc},item,source){
const section = attributes.sheet_type === 'character' ?
'repeating_gear' :
'repeating_stored-gear';
const moveItem = () => {
const row = k.generateRowID(section,sections);
Object.entries(item).forEach(([key,value]) => {
attributes[`${row}_${key}`] = value;
});
};
const removeItem = () => {
const removeID = sections['repeating_stored-gear'].find(id =>{
return Object.keys(item).every(key => attributes[`repeating_stored-gear_${id}_${key}`] === item[key]);
});
k.removeRepeatingRow(`repeating_stored-gear_${removeID}`,attributes,sections);
}
if(
source.type === 'character'
){
if(!source.section.match(/stored/)){
moveItem();
}else{
removeItem();
}
}else{
moveItem();
removeItem();
}
};
k.registerFuncs({itemReceive});
/**
* Calculates the currently used encumbrance slots based on equipment quantities and size
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const calcEncumbrance = function({trigger,attributes,sections,casc}){
const rows = [
...sections.repeating_gear.map(id => `repeating_gear_${id}`),
...sections.repeating_weapons.map(id => `repeating_weapons_${id}`)
];
const total = rows.reduce((tot,row) => {
const usedSlots = typeof attributes[`${row}_slots`] === 'number' ?
attributes[`${row}_slots`] :
0;
const quantity = row.startsWith('repeating_weapons') ?
1 :
attributes[`${row}_quantity`];
tot += usedSlots * quantity;
return tot;
},0);
return total;
};
k.registerFuncs({calcEncumbrance});
/**
* Calculates the maximum encumbrance of the character.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const calcEncumbranceMax = function({trigger,attributes,sections,casc}){
return attributes.strength + 2;
};
k.registerFuncs({calcEncumbranceMax});
// This function is in it's own file because the pug parser did not like having it directly in the sfc for _pc_health
/**
* Rolls on the compendium's critical injury table.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const rollCriticalTable = function({trigger,attributes,sections,casc}){
getCompendiumPage('Critical Injuries',async (ret) => {
const data = ret[0]?.data || ret.data;
if(data['data-Results']){
const table = JSON.parse(data['data-Results']);
const {
table:{result:tableResult},
time:{result:timeResult}
} = await d66Roll('{{time=[[1d6]]}}');
const tableEntry = table
.find(t => +t.die === tableResult);
const rollObj = {
title: '^{Critical Injury}',
roll_label: tableEntry.injury,
roll: `[[${tableResult}]]`,
comment:
(tableEntry.lethal ?
`**^{time limit}:** ${tableEntry.limit.replace(/(?:a|b)/,timeResult)}\n`
+`**^{medical supplies}:** ${tableEntry.limit.match(/^a/) ? '^{advanced}' : '^{basic}'}\n` :
'') +
`**^{penalty}:** ${tableEntry.penalty}\n` +
`**^{recovery}:** ${tableEntry.recovery ? `^{${tableEntry.recovery}}` : '-'}`.trim()
};
const {roll} = await await k.startRoll(rollObj,'@{template_start}');
roll.finish();
const row = k.generateRowID('injury',sections);
['limit','penalty','recovery'].forEach(attr => {
attributes[`${row}_${attr}`] = tableEntry[attr];
})
attributes[`${row}_name`] = tableEntry.injury;
attributes[`${row}_collapse`] = 1;
attributes.set();
}
});
};
k.registerFuncs({rollCriticalTable});
/**
* Applies stress when broken.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const applyStress = function({trigger,attributes,sections,casc}){
if(
attributes.attributes.health !== 0 &&
attributes.health === 0
){
attributes.stress += 1;
}
};
k.registerFuncs({applyStress});
const talentAttributes = ['name','session','description','used'];
/**
* Creates a new talent
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const createTalent = function({trigger,attributes,sections,casc}){
clearTalent(attributes,casc);
selectTalent(attributes,sections);
};
k.registerFuncs({createTalent});
const clearTalent = (attributes,casc) => {
// Reset the display attributes
talentAttributes.forEach(attr => {
attributes[`talent_${attr}`] = casc[`attr_talent_${attr}`].defaultValue;
});
attributes.talent_row_id = '';
}
/**
* Removes a talent's data from the display
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const removeTalent = function({trigger,attributes,sections,casc}){
const [,rowID] = k.parseTriggerName(Object.keys(trigger.removedInfo)[0]);
if(attributes.talent_row_id.toLowerCase() === rowID.toLowerCase()){
clearTalent(attributes,casc);
}
};
k.registerFuncs({removeTalent});
/**
* Moves the talent's data to the display
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const displayTalent = function({trigger,attributes,sections,casc}){
clearTalent(attributes,casc);
const [section,rowID] = k.parseTriggerName(trigger.name);
const row = `${section}_${rowID}`;
attributes.talent_row_id = rowID;
talentAttributes.forEach(attr => {
attributes[`talent_${attr}`] = attributes[`${row}_${attr}`];
});
selectTalent(attributes,sections);
};
k.registerFuncs({displayTalent});
/**
* Saves updates to a talent to the repeating section
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const saveTalent = function({trigger,attributes,sections,casc}){
const targAttr = trigger.name.replace(/talent_/,'');
const row = attributes.talent_row_id ?
`repeating_talents_${attributes.talent_row_id}` :
k.generateRowID('talents',sections);
attributes.talent_row_id = row.replace(/repeating_talents_/,'');
attributes[`${row}_${targAttr}`] = attributes[trigger.name];
selectTalent(attributes,sections)
attributes[`${row}_is_selected`] = 1;
};
k.registerFuncs({saveTalent});
const selectTalent = (attributes,sections) => {
sections.repeating_talents.forEach(id => {
attributes[`repeating_talents_${id}_is_selected`] = id === attributes.talent_row_id ?
1 :
0;
});
};
/**
* Rolls an attack for a weapon
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const rollWeapon = async function({trigger,attributes,sections,casc},message = {}){
const {source,baseObj} = message;
let {skillName,attrName,bonusDice} = message;
trigger = source || trigger;
const [section,rowID] = k.parseTriggerName(trigger.name);
const row = `${section}_${rowID}`;
skillName = skillName || attributes[`${row}_skill`].replace(/ /g,'_');
attrName = attrName || casc[`act_${skillName.replace(/_/g,'-')}-action`].ability;
bonusDice = bonusDice || attributes[`${row}_bonus`];
if(
attributes.sheet_type === 'vehicle' &&
attributes[`${row}_user`] &&
attributes[`${row}_user`] !== 'none'
){
// if this is a vehicle rolling and it is using a crew member's dice pool, then send the command to the indicated character
k.send(
attributes[`${row}_user`],
'rollWeapon',
{
source: {name:'vehicle weapon'},
skillName,
attrName,
bonusDice,
baseObj:{
title: attributes[`${row}_name`],
damage: attributes[`${row}_damage`],
range: attributes[`${row}_range`]
}
}
)
return;
}
const rollObj = await calcDice({skillName,attrName,attributes,sections,innateBonus: bonusDice});
if(baseObj){
Object.assign(rollObj,baseObj);
}else{
rollObj.title = attributes[`${row}_name`];
rollObj.damage = attributes[`${row}_damage`];
rollObj.range = attributes[`${row}_range`];
}
const bpRx = /bp\s*(\d+)/ig
if(rollObj.damage && bpRx.test(rollObj.damage)){
rollObj.damage = rollObj.damage.replace(bpRx,(match,num) => `[[${num}d6>6]]`);
}
const [roll,computeObj] = await executeRoll({rollObj,attributes,sections});
roll.finish();
};
k.registerFuncs({rollWeapon});
/**
*
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const increaseThreat = function({trigger,attributes,sections,casc}){
attributes.threat = Math.min(attributes.threat + 1,6);
};
k.registerFuncs({increaseThreat });
/**
*
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const decreaseThreat = function({trigger,attributes,sections,casc}){
attributes.threat = Math.max(attributes.threat - 1,0);
};
k.registerFuncs({decreaseThreat });
/**
* assembles walker number text based on walker size attribute
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const calcWalkerNumber = function({trigger,attributes,sections,casc}){
const walkerText = ['<5','5-10','11-20','21-50','51-100','100+','1000+'];
const searchIndex = Math.max(
Math.min(
attributes.swarm_size,
6
),
0
);
return walkerText[searchIndex];
};
k.registerFuncs({calcWalkerNumber});
/**
*
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const calcSwarmSkills = function({trigger,attributes,sections,casc}){
const swarmSkills = ['','','','Endure, Force,Mobility,Ranged Combat, Stealth','Force,Mobility,Ranged Combat','Force, Close Combat,Ranged Combat','Force, Close Combat'];
const searchIndex = Math.max(
Math.min(
attributes.threat,
6
),
0
);
return swarmSkills[searchIndex];
};
k.registerFuncs({calcSwarmSkills});
/**
*
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const calcSwarmAttack = function({trigger,attributes,sections,casc}){
const swarmAttacks = ['','','','Single attack,block','Single attack,block','Single attack,block','Mass attack'];
const searchIndex = Math.max(
Math.min(
attributes.threat,
6
),
0
);
return swarmAttacks[searchIndex];
};
k.registerFuncs({calcSwarmAttack});
/**
* Rolls On the swarm attack table for when compendium is detected
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const swarmCompendiumAttack = function({trigger,attributes,sections,casc}){
const swarmPageName = k.capitalize(k.getTranslationByKey('walker attacks'));
getCompendiumPage(swarmPageName,async (ret) => {
const data = ret[0]?.data || ret.data;
const table = JSON.parse(data['data-Results']);
const {
table:{result:tableResult}
} = await d66Roll('{{time=[[1d6]]}}');
const tableEntry = table
.find(t => +t.die === tableResult);
const rollObj = {
title: '^{swarm attack}',
roll: `[[${tableResult}]]`,
comment: tableEntry.effect
}
const {roll} = await k.startRoll(rollObj,'@{template_start}');
roll.finish();
})
};
k.registerFuncs({swarmCompendiumAttack});
/**
* Rolls a basic d66 for when no compendium detected
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const swarmAttack = async function({trigger,attributes,sections,casc},table){
const rollObj = {
title:'^{swarm attack}',
roll:'[[[[1d6]][[1d6]]]]'
};
const {roll,computeObj} = await k.startRoll(rollObj,'@{template_start}');
roll.finish();
};
k.registerFuncs({swarmAttack});
/**
* Gets the stats for the driver. Calls `rollPool` to do the actual rolling.
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const rollManeuverability = function({trigger,attributes,sections,casc}){
if(attributes.driver){
k.send(
attributes.driver,
'rollPool',
{
source:{name:'mobility',ability:'agility'},
bonusDice: attributes.maneuverability,
baseObj:{
title: '^{maneuverability}'
}
}
);
}else{
rollPool({trigger,attributes,sections,casc});
}
};
k.registerFuncs({rollManeuverability});
/**
* Controls display of the sheet type nav controls
* @param {object} trigger - The trigger that caused the function to be called
* @param {object} attributes - The attribute values of the character
* @param {object[]} sections - All the repeating section IDs
* @param {object} casc - Expanded cascade object
*/
const sheetTypeDisplay = function({trigger,attributes,sections,casc}){
const validObj = {
'single player': ['character','challenge','travel log'],
};
const validPages = validObj[attributes.sheet_type] || [attributes.sheet_type];
tabs.forEach(tab => {
const action = validPages.includes(tab) ?
'removeClass' :
'addClass';
$20(`.tabs--walking-dead__button--${tab.replace(/ +/g,'-')}`)[action]('disabled');
});
};
k.registerFuncs({sheetTypeDisplay},{type:['opener']});
</script>