Files
NovaScar a75dbd8351 New Sheet FFfe
Made sure the files were .HTML and .CSS

this is a new sheet for Final Fantasy 5e which is a system i have made.
2026-05-13 12:11:16 -07:00

4135 lines
167 KiB
HTML

<div class="ff7-shell">
<input type="hidden" name="attr_sheet_mode" class="sheet-mode" value="character">
<input type="hidden" name="attr_sheet_tab" class="sheet-tab" value="overview">
<div class="ff7-header">
<div class="logo-panel">
<span class="logo-text">FINAL FANTASY 5E</span>
<span class="sub-text">Roll20 Tactical Sheet</span>
</div>
<div class="mode-buttons">
<button type="action" name="act_mode_character">Character</button>
<button type="action" name="act_mode_monster">Monster</button>
<button type="action" name="act_mode_vehicle">Vehicle</button>
</div>
</div>
<!-- =========================
CHARACTER MODE
========================== -->
<div class="mode-character">
<div class="tab-buttons character-tabs">
<button type="action" name="act_tab_overview">Overview</button>
<button type="action" name="act_tab_cp">CP Engine</button>
<button type="action" name="act_tab_combat">Combat</button>
<button type="action" name="act_tab_magic">Magic</button>
<button type="action" name="act_tab_equipment">Equipment</button>
<button type="action" name="act_tab_status">Status</button>
<button type="action" name="act_tab_bio">Bio</button>
</div>
<!-- =========================
CHARACTER OVERVIEW TAB
========================== -->
<div class="tab-panel tab-overview">
<div class="top-summary-grid">
<div class="ff7-card identity-card">
<h2>Character</h2>
<div class="identity-top-grid">
<div>
<label>Name</label>
<input type="text" name="attr_character_name" placeholder="Character Name">
</div>
<div>
<label>Total Level</label>
<input type="number" name="attr_level" value="1" readonly>
</div>
<div>
<label>Primary Job Level</label>
<input type="number" name="attr_primary_job_level" value="1">
</div>
<div>
<label>Secondary Job Level</label>
<input type="number" name="attr_secondary_job_level" value="0">
</div>
</div>
<div class="job-grid">
<div>
<label>Primary Job / Class</label>
<select name="attr_primary_job">
<option value="Freelancer">Freelancer</option>
<option value="Warrior">Warrior</option>
<option value="Fighter">Fighter</option>
<option value="Barbarian">Barbarian</option>
<option value="Paladin">Paladin</option>
<option value="Dark Knight">Dark Knight</option>
<option value="Gunbreaker">Gunbreaker</option>
<option value="Samurai">Samurai</option>
<option value="Monk">Monk</option>
<option value="Dragoon">Dragoon</option>
<option value="Reaper">Reaper</option>
<option value="Viper">Viper</option>
<option value="Rogue">Rogue</option>
<option value="Thief">Thief</option>
<option value="Ninja">Ninja</option>
<option value="Ranger">Ranger</option>
<option value="Archer">Archer</option>
<option value="Sniper">Sniper</option>
<option value="Machinist">Machinist</option>
<option value="Engineer">Engineer</option>
<option value="Artificer">Artificer</option>
<option value="Bard">Bard</option>
<option value="Dancer">Dancer</option>
<option value="Black Mage">Black Mage</option>
<option value="White Mage">White Mage</option>
<option value="Red Mage">Red Mage</option>
<option value="Blue Mage">Blue Mage</option>
<option value="Time Mage">Time Mage</option>
<option value="Green Mage">Green Mage</option>
<option value="Geomancer">Geomancer</option>
<option value="Summoner">Summoner</option>
<option value="Scholar">Scholar</option>
<option value="Sage">Sage</option>
<option value="Astrologian">Astrologian</option>
<option value="Wizard">Wizard</option>
<option value="Sorcerer">Sorcerer</option>
<option value="Warlock">Warlock</option>
<option value="Cleric">Cleric</option>
<option value="Druid">Druid</option>
<option value="Alchemist">Alchemist</option>
<option value="Chemist">Chemist</option>
<option value="Beastmaster">Beastmaster</option>
<option value="Puppetmaster">Puppetmaster</option>
<option value="Corsair">Corsair</option>
<option value="Gambler">Gambler</option>
<option value="Mime">Mime</option>
<option value="Oracle">Oracle</option>
<option value="Necromancer">Necromancer</option>
<option value="Berserker">Berserker</option>
<option value="Mystic Knight">Mystic Knight</option>
<option value="Rune Knight">Rune Knight</option>
<option value="Pictomancer">Pictomancer</option>
<option value="Onion Knight">Onion Knight</option>
<option value="Custom">Custom</option>
</select>
</div>
<div>
<label>Secondary Job / Class</label>
<select name="attr_secondary_job">
<option value="">None</option>
<option value="Freelancer">Freelancer</option>
<option value="Warrior">Warrior</option>
<option value="Fighter">Fighter</option>
<option value="Barbarian">Barbarian</option>
<option value="Paladin">Paladin</option>
<option value="Dark Knight">Dark Knight</option>
<option value="Gunbreaker">Gunbreaker</option>
<option value="Samurai">Samurai</option>
<option value="Monk">Monk</option>
<option value="Dragoon">Dragoon</option>
<option value="Reaper">Reaper</option>
<option value="Viper">Viper</option>
<option value="Rogue">Rogue</option>
<option value="Thief">Thief</option>
<option value="Ninja">Ninja</option>
<option value="Ranger">Ranger</option>
<option value="Archer">Archer</option>
<option value="Sniper">Sniper</option>
<option value="Machinist">Machinist</option>
<option value="Engineer">Engineer</option>
<option value="Artificer">Artificer</option>
<option value="Bard">Bard</option>
<option value="Dancer">Dancer</option>
<option value="Black Mage">Black Mage</option>
<option value="White Mage">White Mage</option>
<option value="Red Mage">Red Mage</option>
<option value="Blue Mage">Blue Mage</option>
<option value="Time Mage">Time Mage</option>
<option value="Green Mage">Green Mage</option>
<option value="Geomancer">Geomancer</option>
<option value="Summoner">Summoner</option>
<option value="Scholar">Scholar</option>
<option value="Sage">Sage</option>
<option value="Astrologian">Astrologian</option>
<option value="Wizard">Wizard</option>
<option value="Sorcerer">Sorcerer</option>
<option value="Warlock">Warlock</option>
<option value="Cleric">Cleric</option>
<option value="Druid">Druid</option>
<option value="Alchemist">Alchemist</option>
<option value="Chemist">Chemist</option>
<option value="Beastmaster">Beastmaster</option>
<option value="Puppetmaster">Puppetmaster</option>
<option value="Corsair">Corsair</option>
<option value="Gambler">Gambler</option>
<option value="Mime">Mime</option>
<option value="Oracle">Oracle</option>
<option value="Necromancer">Necromancer</option>
<option value="Berserker">Berserker</option>
<option value="Mystic Knight">Mystic Knight</option>
<option value="Rune Knight">Rune Knight</option>
<option value="Pictomancer">Pictomancer</option>
<option value="Onion Knight">Onion Knight</option>
<option value="Custom">Custom</option>
</select>
</div>
</div>
<div class="job-info-grid">
<div>
<label>Primary Role</label>
<input type="text" name="attr_primary_role" readonly>
</div>
<div>
<label>Primary Casting</label>
<input type="text" name="attr_job_spellcasting" readonly>
</div>
<div>
<label>Secondary Role</label>
<input type="text" name="attr_secondary_role" readonly>
</div>
<div>
<label>Secondary Casting</label>
<input type="text" name="attr_secondary_spellcasting" readonly>
</div>
</div>
</div>
<div class="ff7-card exp-card">
<h2>EXP Tracker</h2>
<div class="exp-grid">
<div>
<label>Current EXP</label>
<input type="number" name="attr_exp_current" value="0">
</div>
<div>
<label>Next Level EXP</label>
<input type="number" name="attr_exp_next" value="300">
</div>
<div>
<label>EXP to Next</label>
<input type="number" name="attr_exp_remaining" readonly>
</div>
<div>
<label>EXP Status</label>
<input type="text" name="attr_exp_status" readonly>
</div>
</div>
<div class="resource-adjust exp-adjust">
<input type="number" name="attr_exp_adjust" value="0" placeholder="EXP Amount">
<button type="action" name="act_exp_subtract">- EXP</button>
<button type="action" name="act_exp_add">+ EXP</button>
</div>
</div>
</div>
<div class="resource-bar">
<div class="resource hp">
<label>HP</label>
<div class="resource-main">
<input type="number" name="attr_hp_current" value="0">
<span>/</span>
<input type="number" name="attr_hp_max" value="0">
</div>
<div class="resource-adjust">
<input type="number" name="attr_hp_adjust" value="0" placeholder="Amount">
<button type="action" name="act_hp_subtract">- HP</button>
<button type="action" name="act_hp_add">+ HP</button>
</div>
</div>
<div class="resource mp">
<label>MP</label>
<div class="resource-main">
<input type="number" name="attr_mp_current" value="0">
<span>/</span>
<input type="number" name="attr_mp_max" value="0">
</div>
<div class="resource-adjust">
<input type="number" name="attr_mp_adjust" value="0" placeholder="Amount">
<button type="action" name="act_mp_subtract">- MP</button>
<button type="action" name="act_mp_add">+ MP</button>
</div>
</div>
<div class="resource limit">
<label>Limit</label>
<div class="resource-main">
<input type="number" name="attr_limit_current" value="0">
<span>/</span>
<input type="number" name="attr_limit_max" value="100">
</div>
<div class="resource-adjust">
<input type="number" name="attr_limit_adjust" value="0" placeholder="Amount">
<button type="action" name="act_limit_subtract">- Limit</button>
<button type="action" name="act_limit_add">+ Limit</button>
</div>
</div>
</div>
<div class="overview-grid">
<div class="ff7-card">
<h2>Lineage</h2>
<label>Race</label>
<select name="attr_race">
<option value="Hume">Hume</option>
<option value="Miqo'te">Miqo'te</option>
<option value="Elezen">Elezen</option>
<option value="Lalafell">Lalafell</option>
<option value="Roegadyn">Roegadyn</option>
<option value="Viera">Viera</option>
<option value="Au Ra">Au Ra</option>
<option value="Hrothgar">Hrothgar</option>
<option value="Moogle">Moogle</option>
<option value="Bangaa">Bangaa</option>
<option value="Al Bhed">Al Bhed</option>
<option value="Cetra">Cetra</option>
<option value="Burmecian">Burmecian</option>
<option value="Guado">Guado</option>
<option value="Nu Mou">Nu Mou</option>
<option value="Dwarf">Dwarf</option>
<option value="Garlean">Garlean</option>
<option value="Hybrid">Hybrid / Custom Lineage</option>
</select>
<label>Race Variant / Clan</label>
<select name="attr_race_variant">
<option value="">None / Default</option>
<option value="Midlander">Hume - Midlander</option>
<option value="Highlander">Hume - Highlander</option>
<option value="Seeker">Miqo'te - Seeker of the Sun</option>
<option value="Keeper">Miqo'te - Keeper of the Moon</option>
<option value="Wildwood">Elezen - Wildwood</option>
<option value="Duskwight">Elezen - Duskwight</option>
<option value="Rava">Viera - Rava</option>
<option value="Veena">Viera - Veena</option>
<option value="Raen">Au Ra - Raen</option>
<option value="Xaela">Au Ra - Xaela</option>
<option value="Tholl">Dwarf - Tholl Clan</option>
<option value="Gogg">Dwarf - Gogg Clan</option>
</select>
<div class="choice-grid">
<div>
<label>Bonus Choice 1</label>
<select name="attr_race_choice_1">
<option value="">None</option>
<option value="strength">STR</option>
<option value="dexterity">DEX</option>
<option value="constitution">CON</option>
<option value="intelligence">INT</option>
<option value="wisdom">WIS</option>
<option value="charisma">CHA</option>
</select>
</div>
<div>
<label>Bonus Choice 2</label>
<select name="attr_race_choice_2">
<option value="">None</option>
<option value="strength">STR</option>
<option value="dexterity">DEX</option>
<option value="constitution">CON</option>
<option value="intelligence">INT</option>
<option value="wisdom">WIS</option>
<option value="charisma">CHA</option>
</select>
</div>
</div>
<label>Race Features</label>
<textarea name="attr_race_features" placeholder="Race features, custom lineage notes, homebrew edits, or DM rulings."></textarea>
<label>Row</label>
<select name="attr_row_position">
<option value="vanguard">Vanguard</option>
<option value="rearguard">Rearguard</option>
</select>
</div>
<div class="ff7-card">
<h2>Attributes</h2>
<div class="stat-grid">
<div>
<label>STR Base</label>
<input type="number" name="attr_strength" value="10">
<span name="attr_strength_mod"></span>
</div>
<div>
<label>DEX Base</label>
<input type="number" name="attr_dexterity" value="10">
<span name="attr_dexterity_mod"></span>
</div>
<div>
<label>CON Base</label>
<input type="number" name="attr_constitution" value="10">
<span name="attr_constitution_mod"></span>
</div>
<div>
<label>INT Base</label>
<input type="number" name="attr_intelligence" value="10">
<span name="attr_intelligence_mod"></span>
</div>
<div>
<label>WIS Base</label>
<input type="number" name="attr_wisdom" value="10">
<span name="attr_wisdom_mod"></span>
</div>
<div>
<label>CHA Base</label>
<input type="number" name="attr_charisma" value="10">
<span name="attr_charisma_mod"></span>
</div>
</div>
<!-- Hidden effective totals still exist for automation, but are not displayed. -->
<input type="hidden" name="attr_strength_total">
<input type="hidden" name="attr_dexterity_total">
<input type="hidden" name="attr_constitution_total">
<input type="hidden" name="attr_intelligence_total">
<input type="hidden" name="attr_wisdom_total">
<input type="hidden" name="attr_charisma_total">
</div>
<div class="ff7-card">
<h2>Derived Stats</h2>
<div class="derived-grid">
<div>
<label>Proficiency</label>
<div class="display-stat-pair">
<input type="number" name="attr_proficiency_bonus" value="2">
<span name="attr_proficiency_bonus"></span>
</div>
</div>
<div>
<label>Armor Class</label>
<div class="display-stat-pair">
<input type="number" name="attr_ac">
<span name="attr_ac"></span>
</div>
</div>
<div>
<label>Speed</label>
<div class="display-stat-pair">
<input type="number" name="attr_speed">
<span name="attr_speed"></span>
</div>
</div>
<div>
<label>Fly Speed</label>
<div class="display-stat-pair">
<input type="number" name="attr_fly_speed" readonly>
<span name="attr_fly_speed"></span>
</div>
</div>
<div>
<label>Chassis</label>
<input type="text" name="attr_chassis">
</div>
<div>
<label>Hit Die</label>
<div class="display-stat-pair">
<input type="number" name="attr_hit_die">
<span>d<span name="attr_hit_die"></span></span>
</div>
</div>
</div>
<label>Initiative</label>
<div class="initiative-row">
<input type="number" name="attr_initiative">
<button type="roll" name="roll_character_initiative" value="!ff5e-card-init &quot;@{character_id}&quot; &quot;@{character_name}&quot; &quot;Character&quot; @{initiative}">
Roll Initiative
</button>
</div>
<label>Aetherial Ineptitude</label>
<input type="text" name="attr_aetherial_ineptitude" readonly>
<label>Limit Ready?</label>
<input type="text" name="attr_limit_ready" readonly>
</div>
<div class="ff7-card checks-card">
<h2>Checks, Saves & Skills</h2>
<h3>Ability Checks</h3>
<p class="sheet-help">
Ability checks can now use proficiency or expertise. This is useful for custom job features, tools, lore checks, or special campaign rules.
</p>
<div class="ability-check-grid">
<div class="ability-check-row header-row">
<span>Check</span>
<span>Prof</span>
<span>Expert</span>
<span>Misc</span>
<span>Total</span>
<span>Roll</span>
</div>
<div class="ability-check-row">
<span>STR Check</span>
<label><input type="checkbox" name="attr_check_strength_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_check_strength_expert" value="1"> Expert</label>
<input type="number" name="attr_check_strength_bonus" value="0">
<input type="number" name="attr_check_strength_total" readonly>
<button type="roll" name="roll_strength_check" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Strength Check&quot; &quot;Ability Check&quot; @{check_strength_total} &quot;Strength ability check.&quot;">Roll</button>
</div>
<div class="ability-check-row">
<span>DEX Check</span>
<label><input type="checkbox" name="attr_check_dexterity_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_check_dexterity_expert" value="1"> Expert</label>
<input type="number" name="attr_check_dexterity_bonus" value="0">
<input type="number" name="attr_check_dexterity_total" readonly>
<button type="roll" name="roll_dexterity_check" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Dexterity Check&quot; &quot;Ability Check&quot; @{check_dexterity_total} &quot;Dexterity ability check.&quot;">Roll</button>
</div>
<div class="ability-check-row">
<span>CON Check</span>
<label><input type="checkbox" name="attr_check_constitution_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_check_constitution_expert" value="1"> Expert</label>
<input type="number" name="attr_check_constitution_bonus" value="0">
<input type="number" name="attr_check_constitution_total" readonly>
<button type="roll" name="roll_constitution_check" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Constitution Check&quot; &quot;Ability Check&quot; @{check_constitution_total} &quot;Constitution ability check.&quot;">Roll</button>
</div>
<div class="ability-check-row">
<span>INT Check</span>
<label><input type="checkbox" name="attr_check_intelligence_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_check_intelligence_expert" value="1"> Expert</label>
<input type="number" name="attr_check_intelligence_bonus" value="0">
<input type="number" name="attr_check_intelligence_total" readonly>
<button type="roll" name="roll_intelligence_check" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Intelligence Check&quot; &quot;Ability Check&quot; @{check_intelligence_total} &quot;Intelligence ability check.&quot;">Roll</button>
</div>
<div class="ability-check-row">
<span>WIS Check</span>
<label><input type="checkbox" name="attr_check_wisdom_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_check_wisdom_expert" value="1"> Expert</label>
<input type="number" name="attr_check_wisdom_bonus" value="0">
<input type="number" name="attr_check_wisdom_total" readonly>
<button type="roll" name="roll_wisdom_check" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Wisdom Check&quot; &quot;Ability Check&quot; @{check_wisdom_total} &quot;Wisdom ability check.&quot;">Roll</button>
</div>
<div class="ability-check-row">
<span>CHA Check</span>
<label><input type="checkbox" name="attr_check_charisma_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_check_charisma_expert" value="1"> Expert</label>
<input type="number" name="attr_check_charisma_bonus" value="0">
<input type="number" name="attr_check_charisma_total" readonly>
<button type="roll" name="roll_charisma_check" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Charisma Check&quot; &quot;Ability Check&quot; @{check_charisma_total} &quot;Charisma ability check.&quot;">Roll</button>
</div>
</div>
<h3>Saving Throws</h3>
<div class="save-grid">
<div class="save-row header-row">
<span>Save</span>
<span>Prof</span>
<span>Misc</span>
<span>Total</span>
<span>Roll</span>
</div>
<div class="save-row">
<span>STR Save</span>
<label><input type="checkbox" name="attr_save_strength_prof" value="1"> Prof</label>
<input type="number" name="attr_save_strength_bonus" value="0">
<input type="number" name="attr_save_strength_total" readonly>
<button type="roll" name="roll_strength_save" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Strength Save&quot; &quot;Saving Throw&quot; @{save_strength_total} &quot;Strength saving throw.&quot;">Roll</button>
</div>
<div class="save-row">
<span>DEX Save</span>
<label><input type="checkbox" name="attr_save_dexterity_prof" value="1"> Prof</label>
<input type="number" name="attr_save_dexterity_bonus" value="0">
<input type="number" name="attr_save_dexterity_total" readonly>
<button type="roll" name="roll_dexterity_save" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Dexterity Save&quot; &quot;Saving Throw&quot; @{save_dexterity_total} &quot;Dexterity saving throw.&quot;">Roll</button>
</div>
<div class="save-row">
<span>CON Save</span>
<label><input type="checkbox" name="attr_save_constitution_prof" value="1"> Prof</label>
<input type="number" name="attr_save_constitution_bonus" value="0">
<input type="number" name="attr_save_constitution_total" readonly>
<button type="roll" name="roll_constitution_save" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Constitution Save&quot; &quot;Saving Throw&quot; @{save_constitution_total} &quot;Constitution saving throw.&quot;">Roll</button>
</div>
<div class="save-row">
<span>INT Save</span>
<label><input type="checkbox" name="attr_save_intelligence_prof" value="1"> Prof</label>
<input type="number" name="attr_save_intelligence_bonus" value="0">
<input type="number" name="attr_save_intelligence_total" readonly>
<button type="roll" name="roll_intelligence_save" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Intelligence Save&quot; &quot;Saving Throw&quot; @{save_intelligence_total} &quot;Intelligence saving throw.&quot;">Roll</button>
</div>
<div class="save-row">
<span>WIS Save</span>
<label><input type="checkbox" name="attr_save_wisdom_prof" value="1"> Prof</label>
<input type="number" name="attr_save_wisdom_bonus" value="0">
<input type="number" name="attr_save_wisdom_total" readonly>
<button type="roll" name="roll_wisdom_save" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Wisdom Save&quot; &quot;Saving Throw&quot; @{save_wisdom_total} &quot;Wisdom saving throw.&quot;">Roll</button>
</div>
<div class="save-row">
<span>CHA Save</span>
<label><input type="checkbox" name="attr_save_charisma_prof" value="1"> Prof</label>
<input type="number" name="attr_save_charisma_bonus" value="0">
<input type="number" name="attr_save_charisma_total" readonly>
<button type="roll" name="roll_charisma_save" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Charisma Save&quot; &quot;Saving Throw&quot; @{save_charisma_total} &quot;Charisma saving throw.&quot;">Roll</button>
</div>
</div>
<h3>Skills</h3>
<p class="sheet-help">
Skill totals update from the ability modifier, proficiency bonus, proficiency checkbox, expertise checkbox, and misc bonus.
</p>
<div class="skill-auto-grid">
<div class="skill-auto-row header-row">
<span>Skill</span>
<span>Prof</span>
<span>Expert</span>
<span>Misc</span>
<span>Total</span>
<span>Roll</span>
</div>
<div class="skill-auto-row">
<span>Acrobatics <small>DEX</small></span>
<label><input type="checkbox" name="attr_skill_acrobatics_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_acrobatics_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_acrobatics_bonus" value="0">
<input type="number" name="attr_skill_acrobatics" readonly>
<button type="roll" name="roll_skill_acrobatics" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Acrobatics&quot; &quot;Skill Check&quot; @{skill_acrobatics} &quot;Dexterity skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Animal Handling <small>WIS</small></span>
<label><input type="checkbox" name="attr_skill_animal_handling_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_animal_handling_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_animal_handling_bonus" value="0">
<input type="number" name="attr_skill_animal_handling" readonly>
<button type="roll" name="roll_skill_animal_handling" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Animal Handling&quot; &quot;Skill Check&quot; @{skill_animal_handling} &quot;Wisdom skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Arcana <small>INT</small></span>
<label><input type="checkbox" name="attr_skill_arcana_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_arcana_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_arcana_bonus" value="0">
<input type="number" name="attr_skill_arcana" readonly>
<button type="roll" name="roll_skill_arcana" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Arcana&quot; &quot;Skill Check&quot; @{skill_arcana} &quot;Intelligence skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Athletics <small>STR</small></span>
<label><input type="checkbox" name="attr_skill_athletics_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_athletics_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_athletics_bonus" value="0">
<input type="number" name="attr_skill_athletics" readonly>
<button type="roll" name="roll_skill_athletics" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Athletics&quot; &quot;Skill Check&quot; @{skill_athletics} &quot;Strength skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Deception <small>CHA</small></span>
<label><input type="checkbox" name="attr_skill_deception_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_deception_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_deception_bonus" value="0">
<input type="number" name="attr_skill_deception" readonly>
<button type="roll" name="roll_skill_deception" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Deception&quot; &quot;Skill Check&quot; @{skill_deception} &quot;Charisma skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>History <small>INT</small></span>
<label><input type="checkbox" name="attr_skill_history_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_history_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_history_bonus" value="0">
<input type="number" name="attr_skill_history" readonly>
<button type="roll" name="roll_skill_history" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;History&quot; &quot;Skill Check&quot; @{skill_history} &quot;Intelligence skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Insight <small>WIS</small></span>
<label><input type="checkbox" name="attr_skill_insight_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_insight_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_insight_bonus" value="0">
<input type="number" name="attr_skill_insight" readonly>
<button type="roll" name="roll_skill_insight" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Insight&quot; &quot;Skill Check&quot; @{skill_insight} &quot;Wisdom skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Intimidation <small>CHA</small></span>
<label><input type="checkbox" name="attr_skill_intimidation_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_intimidation_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_intimidation_bonus" value="0">
<input type="number" name="attr_skill_intimidation" readonly>
<button type="roll" name="roll_skill_intimidation" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Intimidation&quot; &quot;Skill Check&quot; @{skill_intimidation} &quot;Charisma skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Investigation <small>INT</small></span>
<label><input type="checkbox" name="attr_skill_investigation_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_investigation_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_investigation_bonus" value="0">
<input type="number" name="attr_skill_investigation" readonly>
<button type="roll" name="roll_skill_investigation" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Investigation&quot; &quot;Skill Check&quot; @{skill_investigation} &quot;Intelligence skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Medicine <small>WIS</small></span>
<label><input type="checkbox" name="attr_skill_medicine_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_medicine_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_medicine_bonus" value="0">
<input type="number" name="attr_skill_medicine" readonly>
<button type="roll" name="roll_skill_medicine" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Medicine&quot; &quot;Skill Check&quot; @{skill_medicine} &quot;Wisdom skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Nature <small>INT</small></span>
<label><input type="checkbox" name="attr_skill_nature_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_nature_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_nature_bonus" value="0">
<input type="number" name="attr_skill_nature" readonly>
<button type="roll" name="roll_skill_nature" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Nature&quot; &quot;Skill Check&quot; @{skill_nature} &quot;Intelligence skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Perception <small>WIS</small></span>
<label><input type="checkbox" name="attr_skill_perception_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_perception_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_perception_bonus" value="0">
<input type="number" name="attr_skill_perception" readonly>
<button type="roll" name="roll_skill_perception" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Perception&quot; &quot;Skill Check&quot; @{skill_perception} &quot;Wisdom skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Performance <small>CHA</small></span>
<label><input type="checkbox" name="attr_skill_performance_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_performance_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_performance_bonus" value="0">
<input type="number" name="attr_skill_performance" readonly>
<button type="roll" name="roll_skill_performance" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Performance&quot; &quot;Skill Check&quot; @{skill_performance} &quot;Charisma skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Persuasion <small>CHA</small></span>
<label><input type="checkbox" name="attr_skill_persuasion_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_persuasion_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_persuasion_bonus" value="0">
<input type="number" name="attr_skill_persuasion" readonly>
<button type="roll" name="roll_skill_persuasion" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Persuasion&quot; &quot;Skill Check&quot; @{skill_persuasion} &quot;Charisma skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Religion <small>INT</small></span>
<label><input type="checkbox" name="attr_skill_religion_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_religion_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_religion_bonus" value="0">
<input type="number" name="attr_skill_religion" readonly>
<button type="roll" name="roll_skill_religion" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Religion&quot; &quot;Skill Check&quot; @{skill_religion} &quot;Intelligence skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Sleight of Hand <small>DEX</small></span>
<label><input type="checkbox" name="attr_skill_sleight_of_hand_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_sleight_of_hand_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_sleight_of_hand_bonus" value="0">
<input type="number" name="attr_skill_sleight_of_hand" readonly>
<button type="roll" name="roll_skill_sleight_of_hand" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Sleight of Hand&quot; &quot;Skill Check&quot; @{skill_sleight_of_hand} &quot;Dexterity skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Stealth <small>DEX</small></span>
<label><input type="checkbox" name="attr_skill_stealth_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_stealth_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_stealth_bonus" value="0">
<input type="number" name="attr_skill_stealth" readonly>
<button type="roll" name="roll_skill_stealth" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Stealth&quot; &quot;Skill Check&quot; @{skill_stealth} &quot;Dexterity skill check.&quot;">Roll</button>
</div>
<div class="skill-auto-row">
<span>Survival <small>WIS</small></span>
<label><input type="checkbox" name="attr_skill_survival_prof" value="1"> Prof</label>
<label><input type="checkbox" name="attr_skill_survival_expert" value="1"> Expert</label>
<input type="number" name="attr_skill_survival_bonus" value="0">
<input type="number" name="attr_skill_survival" readonly>
<button type="roll" name="roll_skill_survival" value="!ff5e-card-d20 &quot;@{character_name}&quot; &quot;Survival&quot; &quot;Skill Check&quot; @{skill_survival} &quot;Wisdom skill check.&quot;">Roll</button>
</div>
</div>
</div>
</div>
</div>
<!-- =========================
CP ENGINE TAB
========================== -->
<div class="tab-panel tab-cp">
<div class="ff7-card">
<h2>Customization Points</h2>
<div class="cp-grid">
<div>
<label>Baseline CP</label>
<input type="number" name="attr_cp_baseline" readonly>
</div>
<div>
<label>Racial CP Bonus</label>
<input type="number" name="attr_racial_cp_bonus" value="0" readonly>
</div>
<div>
<label>Chassis CP Bonus</label>
<input type="number" name="attr_chassis_cp_bonus" value="0">
</div>
<div>
<label>Defect CP Bonus</label>
<input type="number" name="attr_defect_cp_bonus" value="0">
</div>
<div>
<label>Total CP</label>
<input type="number" name="attr_cp_total" readonly>
</div>
<div>
<label>Spent CP</label>
<input type="number" name="attr_cp_spent" readonly>
</div>
<div>
<label>Remaining CP</label>
<input type="number" name="attr_cp_remaining" readonly>
</div>
<div>
<label>CP Warning</label>
<input type="text" name="attr_cp_warning" readonly>
</div>
</div>
<h3>Purchased Attributes</h3>
<fieldset class="repeating_attributes">
<div class="repeat-row three">
<input type="text" name="attr_attribute_name" placeholder="Attribute Name">
<input type="number" name="attr_attribute_rank" placeholder="Rank">
<input type="number" name="attr_attribute_cost" placeholder="CP Cost">
<textarea name="attr_attribute_notes" placeholder="Attribute notes, upgrades, restrictions, or reminders."></textarea>
</div>
</fieldset>
<h3>Defects</h3>
<fieldset class="repeating_defects">
<div class="repeat-row three">
<input type="text" name="attr_defect_name" placeholder="Defect Name">
<input type="number" name="attr_defect_rank" placeholder="Rank">
<input type="number" name="attr_defect_cp_gain" placeholder="CP Gain">
<textarea name="attr_defect_notes" placeholder="Defect notes and roleplay reminders."></textarea>
</div>
</fieldset>
</div>
</div>
<!-- =========================
COMBAT TAB
========================== -->
<div class="tab-panel tab-combat">
<div class="ff7-card">
<h2>Weapon Attacks</h2>
<fieldset class="repeating_attacks">
<div class="repeat-row combat">
<input type="text" name="attr_attack_name" placeholder="Attack Name">
<select name="attr_attack_stat">
<option value="strength_mod">STR</option>
<option value="dexterity_mod">DEX</option>
<option value="intelligence_mod">INT</option>
<option value="wisdom_mod">WIS</option>
<option value="charisma_mod">CHA</option>
</select>
<select name="attr_attack_proficient">
<option value="1">Proficient</option>
<option value="0">Not Proficient</option>
</select>
<input type="number" name="attr_attack_weapon_bonus" placeholder="Weapon Bonus" value="0">
<input type="number" name="attr_attack_total_bonus" placeholder="Total Bonus" readonly>
<input type="text" name="attr_attack_damage" placeholder="Damage Dice">
<input type="text" name="attr_attack_damage_type" placeholder="Damage Type / Notes">
<input type="text" name="attr_attack_element" placeholder="Element / Tags">
<textarea name="attr_attack_notes" placeholder="Attack description, effects, properties, ammo, crit notes, or special rules."></textarea>
<button type="roll" name="roll_weapon_attack" value="!ff5e-card-attack &quot;@{character_name}&quot; &quot;@{attack_name}&quot; &quot;Weapon Attack&quot; @{attack_total_bonus} &quot;@{attack_damage}&quot; 0 &quot;@{attack_notes}&quot;">
Attack
</button>
</div>
</fieldset>
</div>
<div class="ff7-card">
<h2>Techniques</h2>
<fieldset class="repeating_techniques">
<div class="repeat-row technique">
<input type="text" name="attr_tech_name" placeholder="Technique Name">
<input type="text" name="attr_tech_job" placeholder="Job">
<input type="number" name="attr_tech_cp_rank" placeholder="Rank">
<input type="text" name="attr_tech_cost" placeholder="Cost">
<input type="text" name="attr_tech_roll" placeholder="Roll Formula">
<textarea name="attr_tech_description" placeholder="Technique description, timing, target rules, upgrades, and effects."></textarea>
<button type="roll" name="roll_technique" value="!ff5e-card-power &quot;@{character_name}&quot; &quot;@{tech_name}&quot; &quot;Technique&quot; &quot;@{tech_roll}&quot; &quot;@{tech_cost}&quot; &quot;Technique Effect&quot; &quot;@{tech_description}&quot;">
Use
</button>
</div>
</fieldset>
</div>
<div class="ff7-card">
<h2>Limit Breaks</h2>
<fieldset class="repeating_limits">
<div class="repeat-row technique">
<input type="text" name="attr_limit_name" placeholder="Limit Break Name">
<select name="attr_limit_type">
<option value="Offensive">Offensive</option>
<option value="Defensive">Defensive</option>
<option value="Healing">Healing</option>
<option value="Summon">Summon</option>
<option value="Transformation">Transformation</option>
</select>
<input type="number" name="attr_limit_cost" placeholder="Gauge Cost" value="100">
<input type="text" name="attr_limit_roll" placeholder="Roll Formula">
<textarea name="attr_limit_description" placeholder="Limit Break effects, targeting, duration, and cinematic description."></textarea>
<button type="roll" name="roll_limit_break" value="!ff5e-card-power &quot;@{character_name}&quot; &quot;@{limit_name}&quot; &quot;@{limit_type} Limit Break&quot; &quot;@{limit_roll}&quot; &quot;@{limit_cost} Limit&quot; &quot;Limit Effect&quot; &quot;@{limit_description}&quot;">
LIMIT
</button>
<button type="roll" name="roll_limit_api" value="!ff5e-limit-use @{selected|token_id} &quot;@{limit_name}&quot; @{limit_cost}">
Spend
</button>
</div>
</fieldset>
</div>
</div>
<!-- =========================
MAGIC / MATERIA / SUMMONS TAB
========================== -->
<div class="tab-panel tab-magic">
<div class="ff7-card">
<h2>Spellcasting</h2>
<div class="spellcasting-grid">
<div>
<label>Spellcasting Ability</label>
<select name="attr_spellcasting_ability">
<option value="intelligence_mod">Intelligence</option>
<option value="wisdom_mod">Wisdom</option>
<option value="charisma_mod">Charisma</option>
</select>
</div>
<div>
<label>Spellcasting Modifier</label>
<div class="display-stat-pair">
<input type="number" name="attr_spellcasting_mod" readonly>
<span name="attr_spellcasting_mod"></span>
</div>
</div>
<div>
<label>Spell Attack Bonus</label>
<div class="display-stat-pair">
<input type="number" name="attr_spell_attack_bonus" readonly>
<span name="attr_spell_attack_bonus"></span>
</div>
</div>
<div>
<label>Spell Save DC</label>
<div class="display-stat-pair">
<input type="number" name="attr_spell_save_dc" readonly>
<span name="attr_spell_save_dc"></span>
</div>
</div>
<div>
<label>Racial MP Bonus</label>
<input type="number" name="attr_racial_mp_bonus" readonly>
</div>
<div>
<label>Materia MP Bonus</label>
<input type="number" name="attr_materia_mp_bonus" readonly>
</div>
<div>
<label>Total MP Bonus</label>
<input type="number" name="attr_total_mp_bonus" readonly>
</div>
</div>
</div>
<div class="ff7-card">
<h2>Spells</h2>
<fieldset class="repeating_spells">
<div class="repeat-row spell">
<input type="text" name="attr_spell_name" placeholder="Spell Name">
<select name="attr_spell_source">
<option value="Job">Job</option>
<option value="Materia">Materia</option>
<option value="Race">Race</option>
<option value="Summon">Summon</option>
<option value="Item">Item</option>
<option value="Other">Other</option>
</select>
<input type="number" name="attr_spell_mp_cost" placeholder="MP Cost" value="0">
<input type="text" name="attr_spell_element" placeholder="Element / Detail">
<input type="text" name="attr_spell_range" placeholder="Range / Area">
<input type="text" name="attr_spell_roll" placeholder="Damage / Healing / Effect Roll">
<select name="attr_spell_roll_type">
<option value="Spell Effect">Spell Effect</option>
<option value="Spell Attack">Spell Attack</option>
<option value="Spell Save">Spell Save</option>
<option value="Healing">Healing</option>
<option value="Buff">Buff</option>
<option value="Debuff">Debuff</option>
</select>
<input type="text" name="attr_spell_save" placeholder="Save / DC">
<input type="text" name="attr_spell_linked_materia" placeholder="Linked Materia">
<input type="text" name="attr_spell_unlocked" placeholder="Unlocked?" readonly>
<textarea name="attr_spell_description" placeholder="Spell description, upcast effects, conditions, targeting, and special notes."></textarea>
<div class="button-strip">
<button type="roll" name="roll_spell" value="!ff5e-card-power &quot;@{character_name}&quot; &quot;@{spell_name}&quot; &quot;@{spell_roll_type}&quot; &quot;@{spell_roll}&quot; &quot;@{spell_mp_cost}&quot; &quot;@{spell_element} | @{spell_save} | @{spell_range}&quot; &quot;@{spell_description}&quot;">
Card
</button>
<button type="roll" name="roll_spell_attack_card" value="!ff5e-card-attack &quot;@{character_name}&quot; &quot;@{spell_name}&quot; &quot;Spell Attack&quot; @{spell_attack_bonus} &quot;@{spell_roll}&quot; @{spell_mp_cost} &quot;@{spell_description}&quot;">
Attack
</button>
<button type="roll" name="roll_spell_spend_mp" value="!ff5e-mp spend @{selected|token_id} @{spell_mp_cost}">
Spend MP
</button>
<button type="roll" name="roll_spell_full_api" value="!ff5e-cast @{selected|token_id} &quot;@{spell_name}&quot; @{spell_mp_cost} &quot;@{spell_element}&quot; &quot;@{spell_roll}&quot;">
Cast
</button>
</div>
</div>
</fieldset>
</div>
<div class="ff7-card">
<h2>Materia Slots</h2>
<p class="sheet-help">
Equipped Materia can grant spells, MP bonuses, stat bonuses, linked effects, and support effects.
</p>
<fieldset class="repeating_materia">
<div class="repeat-row materia-advanced">
<input type="text" name="attr_materia_name" placeholder="Materia Name">
<select name="attr_materia_type">
<option value="Magic">Magic</option>
<option value="Command">Command</option>
<option value="Support">Support</option>
<option value="Independent">Independent</option>
<option value="Summon">Summon</option>
</select>
<select name="attr_materia_equipped">
<option value="1">Equipped</option>
<option value="0">Not Equipped</option>
</select>
<input type="text" name="attr_materia_slot" placeholder="Slot ID">
<input type="text" name="attr_materia_linked_slot" placeholder="Linked Slot ID">
<input type="number" name="attr_materia_level" placeholder="Level" value="1">
<input type="number" name="attr_materia_ap" placeholder="Current AP" value="0">
<input type="number" name="attr_materia_next_ap" placeholder="Next Level AP" value="100">
<input type="text" name="attr_materia_grants_spell" placeholder="Granted Spell">
<input type="number" name="attr_materia_mp_bonus" placeholder="MP Bonus" value="0">
<input type="number" name="attr_materia_str_bonus" placeholder="STR Bonus" value="0">
<input type="number" name="attr_materia_dex_bonus" placeholder="DEX Bonus" value="0">
<input type="number" name="attr_materia_con_bonus" placeholder="CON Bonus" value="0">
<input type="number" name="attr_materia_int_bonus" placeholder="INT Bonus" value="0">
<input type="number" name="attr_materia_wis_bonus" placeholder="WIS Bonus" value="0">
<input type="number" name="attr_materia_cha_bonus" placeholder="CHA Bonus" value="0">
<input type="text" name="attr_materia_link_effect" placeholder="Linked Effect">
<textarea name="attr_materia_effect" placeholder="Materia effect, linked effect, AP notes, upgrades, and restrictions."></textarea>
<button type="roll" name="roll_materia_effect" value="!ff5e-card-power &quot;@{character_name}&quot; &quot;@{materia_name}&quot; &quot;Materia Effect&quot; &quot;0&quot; &quot;0&quot; &quot;@{materia_type} | Level @{materia_level}&quot; &quot;@{materia_effect}&quot;">
Card
</button>
</div>
</fieldset>
</div>
<div class="ff7-card">
<h2>Summons</h2>
<fieldset class="repeating_summons">
<div class="repeat-row summon">
<input type="text" name="attr_summon_name" placeholder="Summon Name">
<input type="number" name="attr_summon_mp_cost" placeholder="MP Cost" value="0">
<input type="text" name="attr_summon_element" placeholder="Element / Detail">
<input type="number" name="attr_summon_duration_rounds" placeholder="Duration Rounds" value="3">
<input type="text" name="attr_summon_roll" placeholder="Signature Roll / Damage">
<input type="text" name="attr_summon_range" placeholder="Range / Area">
<textarea name="attr_summon_description" placeholder="Summon description, signature attack, passive aura, duration rules, and exit effect."></textarea>
<div class="button-strip">
<button type="roll" name="roll_summon" value="!ff5e-card-power &quot;@{character_name}&quot; &quot;@{summon_name}&quot; &quot;Summon&quot; &quot;@{summon_roll}&quot; &quot;@{summon_mp_cost}&quot; &quot;@{summon_element} | Duration @{summon_duration_rounds} rounds | @{summon_range}&quot; &quot;@{summon_description}&quot;">
Card
</button>
<button type="roll" name="roll_summon_attack_card" value="!ff5e-card-attack &quot;@{character_name}&quot; &quot;@{summon_name}&quot; &quot;Summon Attack&quot; @{spell_attack_bonus} &quot;@{summon_roll}&quot; @{summon_mp_cost} &quot;@{summon_description}&quot;">
Attack
</button>
<button type="roll" name="roll_summon_api" value="!ff5e-summon-cast @{selected|token_id} &quot;@{summon_name}&quot; @{summon_mp_cost} @{summon_duration_rounds}">
Cast
</button>
</div>
</div>
</fieldset>
</div>
</div>
<!-- =========================
EQUIPMENT TAB
========================== -->
<div class="tab-panel tab-equipment">
<div class="ff7-card">
<h2>Armor</h2>
<div class="equipment-grid">
<div>
<label>Armor Type</label>
<select name="attr_armor_type">
<option value="unarmored">Unarmored</option>
<option value="light">Light</option>
<option value="medium">Medium</option>
<option value="heavy">Heavy</option>
<option value="natural">Natural Armor</option>
</select>
</div>
<div>
<label>Armor Base AC</label>
<input type="number" name="attr_armor_base_ac" value="10">
</div>
<div>
<label>Natural AC Base</label>
<input type="number" name="attr_natural_ac_base" readonly>
</div>
<div>
<label>Armor Bonus</label>
<input type="number" name="attr_armor_bonus" value="0">
</div>
<div>
<label>Shield Bonus</label>
<input type="number" name="attr_shield_bonus" value="0">
</div>
<div>
<label>Gear AC Bonus</label>
<input type="number" name="attr_gear_ac_bonus" value="0">
</div>
</div>
<label>Armor Notes</label>
<textarea name="attr_armor_notes" placeholder="Armor properties, shield rules, upgrades, resistance notes, or reminders."></textarea>
</div>
<div class="ff7-card">
<h2>Weapons</h2>
<fieldset class="repeating_weapons">
<div class="repeat-row weapon">
<input type="text" name="attr_weapon_name" placeholder="Weapon Name">
<input type="text" name="attr_weapon_type" placeholder="Weapon Type">
<input type="text" name="attr_weapon_damage" placeholder="Damage Dice">
<input type="text" name="attr_weapon_element" placeholder="Element / Notes">
<input type="number" name="attr_weapon_bonus" placeholder="Bonus" value="0">
<textarea name="attr_weapon_notes" placeholder="Weapon properties, ammunition, materia slots, upgrades, special rules, and notes."></textarea>
<button type="roll" name="roll_weapon_info_card" value="!ff5e-card-power &quot;@{character_name}&quot; &quot;@{weapon_name}&quot; &quot;Weapon Info&quot; &quot;0&quot; &quot;0&quot; &quot;@{weapon_type} | Bonus @{weapon_bonus} | Damage @{weapon_damage}&quot; &quot;@{weapon_notes}&quot;">
Card
</button>
</div>
</fieldset>
</div>
<div class="ff7-card">
<h2>Accessories</h2>
<fieldset class="repeating_accessories">
<div class="repeat-row accessory">
<input type="text" name="attr_accessory_name" placeholder="Accessory">
<input type="text" name="attr_accessory_slot" placeholder="Slot">
<input type="text" name="attr_accessory_effect" placeholder="Effect">
<textarea name="attr_accessory_notes" placeholder="Accessory rules, charges, passive effects, upgrades, and restrictions."></textarea>
<button type="roll" name="roll_accessory_card" value="!ff5e-card-power &quot;@{character_name}&quot; &quot;@{accessory_name}&quot; &quot;Accessory&quot; &quot;0&quot; &quot;0&quot; &quot;@{accessory_slot} | @{accessory_effect}&quot; &quot;@{accessory_notes}&quot;">
Card
</button>
</div>
</fieldset>
</div>
<div class="ff7-card">
<h2>Inventory</h2>
<fieldset class="repeating_inventory">
<div class="repeat-row inventory">
<input type="text" name="attr_item_name" placeholder="Item">
<input type="number" name="attr_item_qty" placeholder="Qty" value="1">
<input type="text" name="attr_item_type" placeholder="Type">
<textarea name="attr_item_notes" placeholder="Item effect, value, weight, crafting use, charges, or notes."></textarea>
<button type="roll" name="roll_item_card" value="!ff5e-card-power &quot;@{character_name}&quot; &quot;@{item_name}&quot; &quot;Item&quot; &quot;0&quot; &quot;0&quot; &quot;Qty @{item_qty} | @{item_type}&quot; &quot;@{item_notes}&quot;">
Card
</button>
</div>
</fieldset>
</div>
</div>
<!-- =========================
STATUS / ELEMENTS TAB
========================== -->
<div class="tab-panel tab-status">
<div class="ff7-card">
<h2>Elemental Affinities</h2>
<div class="element-grid">
<div class="element-row header">
<span>Element</span>
<span>Affinity</span>
</div>
<div class="element-row">
<label>Fire</label>
<select name="attr_affinity_fire">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Ice</label>
<select name="attr_affinity_ice">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Lightning</label>
<select name="attr_affinity_lightning">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Water</label>
<select name="attr_affinity_water">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Wind</label>
<select name="attr_affinity_wind">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Earth</label>
<select name="attr_affinity_earth">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Holy</label>
<select name="attr_affinity_holy">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Dark</label>
<select name="attr_affinity_dark">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Poison</label>
<select name="attr_affinity_poison">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
</div>
<label>Affinity Notes</label>
<textarea name="attr_affinity_notes" placeholder="Elemental rules, conditional weaknesses, resist changes, or campaign-specific notes."></textarea>
</div>
<div class="ff7-card">
<h2>Status Effects</h2>
<div class="status-grid">
<label><input type="checkbox" name="attr_status_poison"> Poison</label>
<label><input type="checkbox" name="attr_status_silence"> Silence</label>
<label><input type="checkbox" name="attr_status_blind"> Blind</label>
<label><input type="checkbox" name="attr_status_berserk"> Berserk</label>
<label><input type="checkbox" name="attr_status_doom"> Doom</label>
<label><input type="checkbox" name="attr_status_slow"> Slow</label>
<label><input type="checkbox" name="attr_status_stop"> Stop</label>
<label><input type="checkbox" name="attr_status_petrify"> Petrify</label>
<label><input type="checkbox" name="attr_status_sleep"> Sleep</label>
<label><input type="checkbox" name="attr_status_confuse"> Confuse</label>
<label><input type="checkbox" name="attr_status_protect"> Protect</label>
<label><input type="checkbox" name="attr_status_shell"> Shell</label>
<label><input type="checkbox" name="attr_status_haste"> Haste</label>
<label><input type="checkbox" name="attr_status_regen"> Regen</label>
<label><input type="checkbox" name="attr_status_reflect"> Reflect</label>
<label><input type="checkbox" name="attr_status_float"> Float</label>
<label><input type="checkbox" name="attr_status_brave"> Brave</label>
<label><input type="checkbox" name="attr_status_faith"> Faith</label>
</div>
<label>Status Notes</label>
<textarea name="attr_status_notes" placeholder="Current conditions, remaining duration, concentration notes, status immunity, or reminders."></textarea>
<h3>Timed Status Helper</h3>
<fieldset class="repeating_statustimers">
<div class="repeat-row status-timer">
<input type="text" name="attr_timer_status_name" placeholder="Status Name">
<input type="number" name="attr_timer_rounds" placeholder="Rounds" value="1">
<button type="roll" name="roll_status_timer_api" value="!ff5e-status add @{selected|token_id} @{timer_status_name} @{timer_rounds}">
Timer
</button>
</div>
</fieldset>
</div>
</div>
<!-- =========================
BIO TAB
========================== -->
<div class="tab-panel tab-bio">
<div class="ff7-card">
<h2>Biography</h2>
<div class="bio-grid">
<div>
<label>Origin</label>
<input type="text" name="attr_origin">
</div>
<div>
<label>Faction</label>
<input type="text" name="attr_faction">
</div>
<div>
<label>Renown</label>
<input type="number" name="attr_renown">
</div>
</div>
<label>Languages</label>
<textarea name="attr_languages" placeholder="Languages, dialects, secret codes, regional speech, and translation notes."></textarea>
<label>Character Notes</label>
<textarea name="attr_character_notes" placeholder="Backstory, personality, bonds, flaws, goals, reputation, allies, enemies, and story hooks."></textarea>
<button type="roll" name="roll_bio_card" value="!ff5e-card-power &quot;@{character_name}&quot; &quot;Character Bio&quot; &quot;Biography&quot; &quot;0&quot; &quot;0&quot; &quot;@{origin} | @{faction} | Renown @{renown}&quot; &quot;@{character_notes}&quot;">
Bio Card
</button>
</div>
<div class="ff7-card">
<h2>Holdings / Base</h2>
<div class="bio-grid">
<div>
<label>Holding Name</label>
<input type="text" name="attr_holding_name">
</div>
<div>
<label>Holding Size</label>
<select name="attr_holding_size">
<option value="Tiny">Tiny</option>
<option value="Small">Small</option>
<option value="Medium">Medium</option>
<option value="Large">Large</option>
<option value="Massive">Massive</option>
</select>
</div>
<div>
<label>Upgrade Slots</label>
<input type="number" name="attr_holding_slots">
</div>
</div>
<label>Holding Notes</label>
<textarea name="attr_holding_notes" placeholder="Base description, rooms, staff, services, income, defenses, downtime options, and upgrades."></textarea>
<button type="roll" name="roll_holding_card" value="!ff5e-card-power &quot;@{character_name}&quot; &quot;@{holding_name}&quot; &quot;Holding / Base&quot; &quot;0&quot; &quot;0&quot; &quot;@{holding_size} | Slots @{holding_slots}&quot; &quot;@{holding_notes}&quot;">
Holding Card
</button>
<fieldset class="repeating_holdings">
<div class="repeat-row holding">
<input type="text" name="attr_holding_upgrade_name" placeholder="Upgrade / Business">
<input type="number" name="attr_holding_rank" placeholder="Rank">
<input type="text" name="attr_holding_income" placeholder="Income Formula">
<textarea name="attr_holding_upgrade_notes" placeholder="Upgrade notes, benefits, staff, upkeep, and income details."></textarea>
<button type="roll" name="roll_holding_upgrade_card" value="!ff5e-card-power &quot;@{character_name}&quot; &quot;@{holding_upgrade_name}&quot; &quot;Holding Upgrade&quot; &quot;@{holding_income}&quot; &quot;0&quot; &quot;Rank @{holding_rank}&quot; &quot;@{holding_upgrade_notes}&quot;">
Card
</button>
</div>
</fieldset>
</div>
</div>
</div>
<!-- =========================
MONSTER MODE
========================== -->
<div class="mode-monster">
<div class="tab-buttons monster-tabs">
<button type="action" name="act_tab_monster_core">Core</button>
<button type="action" name="act_tab_monster_actions">Actions</button>
<button type="action" name="act_tab_monster_status">Weaknesses</button>
<button type="action" name="act_tab_monster_import">Import</button>
</div>
<!-- =========================
MONSTER CORE TAB
========================== -->
<div class="tab-panel tab-monster-core">
<div class="resource-bar">
<div class="resource hp">
<label>NPC HP</label>
<div class="resource-main">
<input type="number" name="attr_npc_hp_current" value="0">
<span>/</span>
<input type="number" name="attr_npc_hp_max" value="0">
</div>
<div class="resource-adjust">
<input type="number" name="attr_npc_hp_adjust" value="0" placeholder="Amount">
<button type="action" name="act_npc_hp_subtract">- HP</button>
<button type="action" name="act_npc_hp_add">+ HP</button>
</div>
</div>
<div class="resource mp">
<label>NPC MP</label>
<div class="resource-main">
<input type="number" name="attr_npc_mp_current" value="0">
<span>/</span>
<input type="number" name="attr_npc_mp_max" value="0">
</div>
<div class="resource-adjust">
<input type="number" name="attr_npc_mp_adjust" value="0" placeholder="Amount">
<button type="action" name="act_npc_mp_subtract">- MP</button>
<button type="action" name="act_npc_mp_add">+ MP</button>
</div>
</div>
<div class="resource limit">
<label>NPC Limit</label>
<div class="resource-main">
<input type="number" name="attr_npc_limit_current" value="0">
<span>/</span>
<input type="number" name="attr_npc_limit_max" value="100">
</div>
<div class="resource-adjust">
<input type="number" name="attr_npc_limit_adjust" value="0" placeholder="Amount">
<button type="action" name="act_npc_limit_subtract">- Limit</button>
<button type="action" name="act_npc_limit_add">+ Limit</button>
</div>
</div>
<div class="resource">
<label>Boss Phase</label>
<div class="resource-main single-resource">
<input type="number" name="attr_boss_phase" value="1">
</div>
<div class="resource-adjust">
<input type="number" name="attr_boss_phase_adjust" value="1" placeholder="Phase">
<button type="action" name="act_boss_phase_subtract">- Phase</button>
<button type="action" name="act_boss_phase_add">+ Phase</button>
</div>
</div>
<div class="resource">
<label>HP Percent</label>
<div class="resource-main single-resource">
<input type="number" name="attr_npc_hp_percent" readonly>
<span>%</span>
</div>
</div>
</div>
<div class="overview-grid">
<div class="ff7-card">
<h2>Enemy Profile</h2>
<div class="monster-profile-grid">
<div>
<label>Name</label>
<input type="text" name="attr_npc_name" placeholder="Monster Name">
</div>
<div>
<label>Enemy Type</label>
<select name="attr_npc_type">
<option value="Fiend">Fiend</option>
<option value="Machina">Machina</option>
<option value="Humanoid">Humanoid</option>
<option value="Beast">Beast</option>
<option value="Dragon">Dragon</option>
<option value="Undead">Undead</option>
<option value="Eidolon">Eidolon</option>
<option value="Primal">Primal</option>
<option value="Weapon">Weapon</option>
<option value="Construct">Construct</option>
<option value="Other">Other</option>
</select>
</div>
<div>
<label>Level / CR</label>
<input type="number" name="attr_npc_level" value="1">
</div>
<div>
<label>Proficiency</label>
<div class="display-stat-pair">
<input type="number" name="attr_npc_proficiency_bonus" readonly>
<span name="attr_npc_proficiency_bonus"></span>
</div>
</div>
<div>
<label>Scale</label>
<select name="attr_npc_scale">
<option value="personal">Personal</option>
<option value="armor">Armor</option>
<option value="ship">Ship</option>
</select>
</div>
<div>
<label>Armor Class</label>
<div class="display-stat-pair">
<input type="number" name="attr_npc_ac" value="10">
<span name="attr_npc_ac"></span>
</div>
</div>
</div>
<label>Initiative</label>
<div class="initiative-row">
<input type="number" name="attr_npc_initiative" value="0">
<button type="roll" name="roll_npc_initiative" value="!ff5e-card-init &quot;@{character_id}&quot; &quot;@{npc_name}&quot; &quot;Monster&quot; @{npc_initiative}">
Initiative
</button>
</div>
<div class="monster-profile-grid">
<div>
<label>Speed</label>
<input type="text" name="attr_npc_speed" placeholder="30 ft., fly 60 ft., etc.">
</div>
<div>
<label>Senses</label>
<input type="text" name="attr_npc_senses" placeholder="Darkvision, tremorsense, etc.">
</div>
</div>
</div>
<div class="ff7-card">
<h2>Monster Quick Rolls</h2>
<p class="sheet-help">
These use the same themed card as player checks and saves.
</p>
<div class="quick-roll-grid">
<div>
<label>STR Bonus</label>
<input type="number" name="attr_npc_str_bonus" value="0">
<button type="roll" name="roll_npc_str_check" value="!ff5e-card-d20 &quot;@{npc_name}&quot; &quot;Strength Roll&quot; &quot;Monster Check / Save&quot; @{npc_str_bonus} &quot;Monster Strength check or saving throw.&quot;">Roll</button>
</div>
<div>
<label>DEX Bonus</label>
<input type="number" name="attr_npc_dex_bonus" value="0">
<button type="roll" name="roll_npc_dex_check" value="!ff5e-card-d20 &quot;@{npc_name}&quot; &quot;Dexterity Roll&quot; &quot;Monster Check / Save&quot; @{npc_dex_bonus} &quot;Monster Dexterity check or saving throw.&quot;">Roll</button>
</div>
<div>
<label>CON Bonus</label>
<input type="number" name="attr_npc_con_bonus" value="0">
<button type="roll" name="roll_npc_con_check" value="!ff5e-card-d20 &quot;@{npc_name}&quot; &quot;Constitution Roll&quot; &quot;Monster Check / Save&quot; @{npc_con_bonus} &quot;Monster Constitution check or saving throw.&quot;">Roll</button>
</div>
<div>
<label>INT Bonus</label>
<input type="number" name="attr_npc_int_bonus" value="0">
<button type="roll" name="roll_npc_int_check" value="!ff5e-card-d20 &quot;@{npc_name}&quot; &quot;Intelligence Roll&quot; &quot;Monster Check / Save&quot; @{npc_int_bonus} &quot;Monster Intelligence check or saving throw.&quot;">Roll</button>
</div>
<div>
<label>WIS Bonus</label>
<input type="number" name="attr_npc_wis_bonus" value="0">
<button type="roll" name="roll_npc_wis_check" value="!ff5e-card-d20 &quot;@{npc_name}&quot; &quot;Wisdom Roll&quot; &quot;Monster Check / Save&quot; @{npc_wis_bonus} &quot;Monster Wisdom check or saving throw.&quot;">Roll</button>
</div>
<div>
<label>CHA Bonus</label>
<input type="number" name="attr_npc_cha_bonus" value="0">
<button type="roll" name="roll_npc_cha_check" value="!ff5e-card-d20 &quot;@{npc_name}&quot; &quot;Charisma Roll&quot; &quot;Monster Check / Save&quot; @{npc_cha_bonus} &quot;Monster Charisma check or saving throw.&quot;">Roll</button>
</div>
</div>
<label>Custom Roll Name</label>
<input type="text" name="attr_npc_custom_roll_name" placeholder="Example: Perception">
<label>Custom Roll Bonus</label>
<input type="number" name="attr_npc_custom_roll_bonus" value="0">
<button type="roll" name="roll_npc_custom_check" value="!ff5e-card-d20 &quot;@{npc_name}&quot; &quot;@{npc_custom_roll_name}&quot; &quot;Monster Custom Roll&quot; @{npc_custom_roll_bonus} &quot;Custom monster roll.&quot;">
Custom Roll
</button>
</div>
<div class="ff7-card">
<h2>Boss Phase Engine</h2>
<div class="boss-grid">
<div>
<label>Suggested Phase</label>
<input type="number" name="attr_boss_phase_suggested" readonly>
</div>
<div>
<label>Current AI State</label>
<select name="attr_npc_ai_state">
<option value="Normal">Normal</option>
<option value="Aggressive">Aggressive</option>
<option value="Defensive">Defensive</option>
<option value="Charging">Charging</option>
<option value="Enraged">Enraged</option>
<option value="Staggered">Staggered</option>
<option value="Scripted">Scripted</option>
</select>
</div>
</div>
<label>Phase 2 Trigger</label>
<input type="text" name="attr_phase_2_trigger" value="50% HP">
<label>Phase 3 Trigger</label>
<input type="text" name="attr_phase_3_trigger" value="25% HP">
<label>Phase 4 / Enrage Trigger</label>
<input type="text" name="attr_enrage_trigger" value="10% HP">
<label>Boss Notes</label>
<textarea name="attr_boss_notes" placeholder="Boss behavior, phase scripts, legendary actions, reactions, lair effects, and encounter notes."></textarea>
<button type="roll" name="roll_boss_phase_card" value="!ff5e-card-power &quot;@{npc_name}&quot; &quot;Boss Phase&quot; &quot;Boss State&quot; &quot;0&quot; &quot;0&quot; &quot;Current Phase @{boss_phase} | Suggested @{boss_phase_suggested} | HP @{npc_hp_percent}%&quot; &quot;@{boss_notes}&quot;">
Phase Card
</button>
</div>
<div class="ff7-card">
<h2>Defenses</h2>
<label>Saving Throws</label>
<textarea name="attr_npc_saves" placeholder="Example: STR +6, CON +5, WIS +3"></textarea>
<label>Skills</label>
<textarea name="attr_npc_skills" placeholder="Example: Perception +6, Athletics +8"></textarea>
<label>Resistances</label>
<textarea name="attr_npc_resistances" placeholder="Damage resistances and conditional resistance notes."></textarea>
<label>Immunities</label>
<textarea name="attr_npc_immunities" placeholder="Damage immunities."></textarea>
<label>Condition Immunities</label>
<textarea name="attr_npc_condition_immunities" placeholder="Poisoned, charmed, frightened, etc."></textarea>
<button type="roll" name="roll_npc_defense_card" value="!ff5e-card-power &quot;@{npc_name}&quot; &quot;Defenses&quot; &quot;Monster Defense Profile&quot; &quot;0&quot; &quot;0&quot; &quot;AC @{npc_ac} | Saves @{npc_saves} | Skills @{npc_skills}&quot; &quot;Resistances: @{npc_resistances} | Immunities: @{npc_immunities} | Condition Immunities: @{npc_condition_immunities}&quot;">
Defense Card
</button>
</div>
</div>
</div>
<!-- =========================
MONSTER ACTIONS TAB
========================== -->
<div class="tab-panel tab-monster-actions">
<div class="ff7-card">
<h2>Enemy Actions</h2>
<fieldset class="repeating_npcactions">
<div class="repeat-row npc-action">
<input type="text" name="attr_npc_action_name" placeholder="Action Name">
<select name="attr_npc_action_category">
<option>Action</option>
<option>Bonus Action</option>
<option>Reaction</option>
<option>Legendary Action</option>
<option>Lair Action</option>
<option>Phase Action</option>
<option>Enrage Action</option>
<option>Counter</option>
</select>
<input type="text" name="attr_npc_action_type" placeholder="Attack Type / Save Type">
<input type="text" name="attr_npc_action_recharge" placeholder="Recharge, e.g. 5-6">
<input type="number" name="attr_npc_action_mp_cost" placeholder="MP Cost" value="0">
<input type="text" name="attr_npc_action_attack" placeholder="Attack Roll, e.g. 1d20+6">
<input type="text" name="attr_npc_action_roll" placeholder="Damage / Effect Roll">
<input type="text" name="attr_npc_action_damage_type" placeholder="Damage Type / Notes">
<input type="text" name="attr_npc_action_element" placeholder="Element / Detail">
<input type="text" name="attr_npc_action_range" placeholder="Range / Area">
<input type="text" name="attr_npc_action_save" placeholder="Save / DC">
<select name="attr_npc_action_scale">
<option value="personal">Personal</option>
<option value="armor">Armor</option>
<option value="ship">Ship</option>
</select>
<input type="text" name="attr_npc_action_status" placeholder="Status Inflicted">
<input type="number" name="attr_npc_action_status_rounds" placeholder="Status Rounds" value="1">
<textarea name="attr_npc_action_desc" placeholder="Action description, targeting, recharge rules, rider effects, status effects, and phase notes."></textarea>
<div class="button-strip">
<button type="roll" name="roll_npc_action_attack" value="!ff5e-card-attack-formula &quot;@{npc_name}&quot; &quot;@{npc_action_name}&quot; &quot;@{npc_action_category}: @{npc_action_type}&quot; &quot;@{npc_action_attack}&quot; &quot;@{npc_action_roll}&quot; @{npc_action_mp_cost} &quot;@{npc_action_desc}&quot;">
Attack
</button>
<button type="roll" name="roll_npc_power" value="!ff5e-card-power &quot;@{npc_name}&quot; &quot;@{npc_action_name}&quot; &quot;@{npc_action_category}: @{npc_action_type}&quot; &quot;@{npc_action_roll}&quot; &quot;@{npc_action_mp_cost}&quot; &quot;@{npc_action_element} | @{npc_action_save} | @{npc_action_range} | Recharge @{npc_action_recharge}&quot; &quot;@{npc_action_desc}&quot;">
Power
</button>
<button type="roll" name="roll_npc_status_api" value="!ff5e-status add @{target|Status Target|token_id} @{npc_action_status} @{npc_action_status_rounds}">
Status
</button>
<button type="roll" name="roll_npc_recharge_api" value="!ff5e-recharge @{npc_action_recharge}">
Recharge
</button>
</div>
</div>
</fieldset>
</div>
<div class="ff7-card">
<h2>Legendary / Lair Actions</h2>
<fieldset class="repeating_legendaryactions">
<div class="repeat-row npc-action">
<input type="text" name="attr_legendary_name" placeholder="Legendary Action">
<input type="number" name="attr_legendary_cost" placeholder="Cost">
<input type="text" name="attr_legendary_roll" placeholder="Roll Formula">
<input type="text" name="attr_legendary_element" placeholder="Element / Detail">
<input type="text" name="attr_legendary_range" placeholder="Range / Area">
<input type="text" name="attr_legendary_save" placeholder="Save / DC">
<textarea name="attr_legendary_desc" placeholder="Legendary action description, timing, triggers, and effects."></textarea>
<button type="roll" name="roll_legendary_action" value="!ff5e-card-power &quot;@{npc_name}&quot; &quot;@{legendary_name}&quot; &quot;Legendary / Lair Action&quot; &quot;@{legendary_roll}&quot; &quot;@{legendary_cost} Action Cost&quot; &quot;@{legendary_element} | @{legendary_save} | @{legendary_range}&quot; &quot;@{legendary_desc}&quot;">
Card
</button>
</div>
</fieldset>
</div>
<div class="ff7-card">
<h2>AI Pattern</h2>
<fieldset class="repeating_aipattern">
<div class="repeat-row npc-action">
<input type="number" name="attr_ai_round" placeholder="Round">
<input type="text" name="attr_ai_phase" placeholder="Phase">
<input type="text" name="attr_ai_action" placeholder="Preferred Action">
<textarea name="attr_ai_notes" placeholder="AI behavior, priorities, conditions, reactions, and tactical notes."></textarea>
<button type="roll" name="roll_ai_pattern_card" value="!ff5e-card-power &quot;@{npc_name}&quot; &quot;AI Round @{ai_round}&quot; &quot;AI Pattern&quot; &quot;0&quot; &quot;0&quot; &quot;Phase @{ai_phase} | Action @{ai_action}&quot; &quot;@{ai_notes}&quot;">
AI Card
</button>
</div>
</fieldset>
</div>
</div>
<!-- =========================
MONSTER WEAKNESSES TAB
========================== -->
<div class="tab-panel tab-monster-status">
<div class="ff7-card">
<h2>Elemental Profile</h2>
<div class="element-grid">
<div class="element-row header">
<span>Element</span>
<span>Affinity</span>
</div>
<div class="element-row">
<label>Fire</label>
<select name="attr_npc_affinity_fire">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Ice</label>
<select name="attr_npc_affinity_ice">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Lightning</label>
<select name="attr_npc_affinity_lightning">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Water</label>
<select name="attr_npc_affinity_water">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Wind</label>
<select name="attr_npc_affinity_wind">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Earth</label>
<select name="attr_npc_affinity_earth">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Holy</label>
<select name="attr_npc_affinity_holy">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Dark</label>
<select name="attr_npc_affinity_dark">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
<div class="element-row">
<label>Poison</label>
<select name="attr_npc_affinity_poison">
<option>Normal</option>
<option>Weak</option>
<option>Resist</option>
<option>Null</option>
<option>Absorb</option>
</select>
</div>
</div>
<label>Weakness / Resistance Notes</label>
<textarea name="attr_npc_affinity_notes" placeholder="Conditional weaknesses, phase changes, stagger rules, exposed cores, shield effects, and special damage rules."></textarea>
<h3>Damage Calculator Helper</h3>
<div class="damage-helper-grid">
<div>
<label>Incoming Damage</label>
<input type="number" name="attr_npc_incoming_damage" value="0">
</div>
<div>
<label>Incoming Element</label>
<select name="attr_npc_incoming_element">
<option value="fire">Fire</option>
<option value="ice">Ice</option>
<option value="lightning">Lightning</option>
<option value="water">Water</option>
<option value="wind">Wind</option>
<option value="earth">Earth</option>
<option value="holy">Holy</option>
<option value="dark">Dark</option>
<option value="poison">Poison</option>
<option value="none">None</option>
</select>
</div>
<div>
<label>Adjusted Damage</label>
<div class="display-stat-pair">
<input type="number" name="attr_npc_adjusted_damage" readonly>
<span name="attr_npc_adjusted_damage"></span>
</div>
</div>
<div>
<label>Affinity Result</label>
<input type="text" name="attr_npc_damage_affinity_result" readonly>
</div>
</div>
<button type="roll" name="roll_npc_affinity_card" value="!ff5e-card-power &quot;@{npc_name}&quot; &quot;Affinity Damage&quot; &quot;Damage Helper&quot; &quot;@{npc_adjusted_damage}&quot; &quot;0&quot; &quot;Incoming @{npc_incoming_damage} | @{npc_incoming_element}&quot; &quot;@{npc_damage_affinity_result}&quot;">
Affinity Card
</button>
</div>
</div>
<!-- =========================
MONSTER IMPORT TAB
========================== -->
<div class="tab-panel tab-monster-import">
<div class="ff7-card">
<h2>Monster Database Import</h2>
<p class="sheet-help">
Use this with the monster database API script. Enter a monster key such as guard_scorpion,
bomb, behemoth, ifrit, or tonberry.
</p>
<label>Monster Import Key</label>
<input type="text" name="attr_npc_import_key" placeholder="Example: guard_scorpion">
<button type="roll" name="roll_import_monster" value="!ff5e-import-monster @{selected|token_id} @{npc_import_key}">
Import Selected
</button>
<label>Manual JSON Import</label>
<textarea name="attr_npc_import_json" placeholder='Paste monster JSON here for API/manual reference.'></textarea>
<button type="roll" name="roll_import_monster_json" value="!ff5e-import-json @{selected|token_id}">
Import JSON
</button>
</div>
<div class="ff7-card compendium-drop-target" accept="Monster,NPC">
<h2>Compendium / Drop Target</h2>
<p class="sheet-help">
This panel is prepared as a compendium drop target. Full private compendium support depends on your Roll20 compendium setup.
</p>
<div class="monster-profile-grid">
<div>
<label>Dropped Name</label>
<input type="text" name="attr_drop_name" accept="Name">
</div>
<div>
<label>Dropped Type</label>
<input type="text" name="attr_drop_type" accept="Type">
</div>
<div>
<label>Dropped HP</label>
<input type="text" name="attr_drop_hp" accept="Hit Points">
</div>
<div>
<label>Dropped AC</label>
<input type="text" name="attr_drop_ac" accept="Armor Class">
</div>
</div>
<label>Dropped Notes</label>
<textarea name="attr_drop_notes" placeholder="Dropped compendium notes or manual import notes."></textarea>
</div>
</div>
</div>
<!-- =========================
VEHICLE MODE
========================== -->
<div class="mode-vehicle">
<div class="tab-buttons vehicle-tabs">
<button type="action" name="act_tab_vehicle_core">Core</button>
<button type="action" name="act_tab_vehicle_weapons">Weapons</button>
<button type="action" name="act_tab_vehicle_systems">Systems</button>
<button type="action" name="act_tab_vehicle_scale">Scale</button>
</div>
<!-- =========================
VEHICLE CORE TAB
========================== -->
<div class="tab-panel tab-vehicle-core">
<div class="resource-bar">
<div class="resource hp">
<label>Hull HP</label>
<div class="resource-main">
<input type="number" name="attr_vehicle_hp_current" value="0">
<span>/</span>
<input type="number" name="attr_vehicle_hp_max" value="0">
</div>
<div class="resource-adjust">
<input type="number" name="attr_vehicle_hp_adjust" value="0" placeholder="Amount">
<button type="action" name="act_vehicle_hp_subtract">- HP</button>
<button type="action" name="act_vehicle_hp_add">+ HP</button>
</div>
</div>
<div class="resource mp">
<label>Vehicle MP / Energy</label>
<div class="resource-main">
<input type="number" name="attr_vehicle_mp_current" value="0">
<span>/</span>
<input type="number" name="attr_vehicle_mp_max" value="0">
</div>
<div class="resource-adjust">
<input type="number" name="attr_vehicle_mp_adjust" value="0" placeholder="Amount">
<button type="action" name="act_vehicle_mp_subtract">- MP</button>
<button type="action" name="act_vehicle_mp_add">+ MP</button>
</div>
</div>
<div class="resource limit">
<label>Vehicle Limit</label>
<div class="resource-main">
<input type="number" name="attr_vehicle_limit_current" value="0">
<span>/</span>
<input type="number" name="attr_vehicle_limit_max" value="100">
</div>
<div class="resource-adjust">
<input type="number" name="attr_vehicle_limit_adjust" value="0" placeholder="Amount">
<button type="action" name="act_vehicle_limit_subtract">- Limit</button>
<button type="action" name="act_vehicle_limit_add">+ Limit</button>
</div>
</div>
<div class="resource mp">
<label>Shield</label>
<div class="resource-main">
<input type="number" name="attr_vehicle_shield_current" value="0">
<span>/</span>
<input type="number" name="attr_vehicle_shield_max" value="0">
</div>
<div class="resource-adjust">
<input type="number" name="attr_vehicle_shield_adjust" value="0" placeholder="Amount">
<button type="action" name="act_vehicle_shield_subtract">- Shield</button>
<button type="action" name="act_vehicle_shield_add">+ Shield</button>
</div>
</div>
<div class="resource">
<label>Condition</label>
<div class="resource-main single-resource">
<input type="text" name="attr_vehicle_condition" readonly>
</div>
</div>
</div>
<div class="overview-grid">
<div class="ff7-card">
<h2>Vehicle Profile</h2>
<div class="vehicle-profile-grid">
<div>
<label>Name</label>
<input type="text" name="attr_vehicle_name" placeholder="Vehicle Name">
</div>
<div>
<label>Vehicle Type</label>
<select name="attr_vehicle_type">
<option value="mount">Mount</option>
<option value="warmachina">Warmachina</option>
<option value="land_vehicle">Land Vehicle</option>
<option value="airship">Airship</option>
<option value="dreadnought">Dreadnought</option>
</select>
</div>
<div>
<label>Scale</label>
<select name="attr_vehicle_scale">
<option value="personal">Personal</option>
<option value="armor">Armor</option>
<option value="ship">Ship</option>
</select>
</div>
<div>
<label>Armor Class</label>
<div class="display-stat-pair">
<input type="number" name="attr_vehicle_ac" value="10">
<span name="attr_vehicle_ac"></span>
</div>
</div>
</div>
<label>Initiative</label>
<div class="initiative-row">
<input type="number" name="attr_vehicle_initiative" value="0">
<button type="roll" name="roll_vehicle_initiative" value="!ff5e-card-init &quot;@{character_id}&quot; &quot;@{vehicle_name}&quot; &quot;Vehicle&quot; @{vehicle_initiative}">
Initiative
</button>
</div>
<div class="vehicle-profile-grid">
<div>
<label>Speed</label>
<input type="text" name="attr_vehicle_speed" placeholder="Speed / travel pace">
</div>
<div>
<label>Capacity</label>
<input type="number" name="attr_vehicle_capacity" value="0">
</div>
<div>
<label>Crew Required</label>
<input type="number" name="attr_vehicle_crew_required" value="0">
</div>
</div>
</div>
<div class="ff7-card">
<h2>Crew Stations</h2>
<div class="crew-grid">
<div>
<label>Captain</label>
<input type="text" name="attr_crew_captain">
<label>Captain Bonus</label>
<input type="number" name="attr_captain_bonus" value="0">
<button type="roll" name="roll_captain_action" value="!ff5e-card-d20 &quot;@{vehicle_name}&quot; &quot;Captain Command&quot; &quot;Vehicle Station Check&quot; @{captain_bonus} &quot;Captain: @{crew_captain}. Grant advantage or command a station.&quot;">Roll</button>
</div>
<div>
<label>Pilot</label>
<input type="text" name="attr_crew_pilot">
<label>Pilot Bonus</label>
<input type="number" name="attr_pilot_bonus" value="0">
<button type="roll" name="roll_pilot_action" value="!ff5e-card-d20 &quot;@{vehicle_name}&quot; &quot;Evasive Maneuver&quot; &quot;Vehicle Station Check&quot; @{pilot_bonus} &quot;Pilot: @{crew_pilot}. Reposition or increase defense.&quot;">Roll</button>
</div>
<div>
<label>Gunner</label>
<input type="text" name="attr_crew_gunner">
<label>Gunner Bonus</label>
<input type="number" name="attr_gunner_bonus" value="0">
<button type="roll" name="roll_gunner_action" value="!ff5e-card-d20 &quot;@{vehicle_name}&quot; &quot;Fire Weapon Systems&quot; &quot;Vehicle Station Check&quot; @{gunner_bonus} &quot;Gunner: @{crew_gunner}. Fire one vehicle weapon.&quot;">Roll</button>
</div>
<div>
<label>Engineer</label>
<input type="text" name="attr_crew_engineer">
<label>Engineer Bonus</label>
<input type="number" name="attr_engineer_bonus" value="0">
<button type="roll" name="roll_engineer_action" value="!ff5e-card-d20 &quot;@{vehicle_name}&quot; &quot;Emergency Repairs&quot; &quot;Vehicle Station Check&quot; @{engineer_bonus} &quot;Engineer: @{crew_engineer}. Repair hull or stabilize systems.&quot;">Roll</button>
</div>
</div>
</div>
<div class="ff7-card">
<h2>Vehicle Notes</h2>
<label>Features</label>
<textarea name="attr_vehicle_features" placeholder="Vehicle traits, systems, movement rules, special actions, and upgrades."></textarea>
<label>Damage Notes</label>
<textarea name="attr_vehicle_damage_notes" placeholder="Critical damage, disabled systems, hull breaches, repairs, and shield rules."></textarea>
<label>Cargo</label>
<textarea name="attr_vehicle_cargo" placeholder="Cargo, passengers, supplies, fuel, trade goods, and stored gear."></textarea>
<button type="roll" name="roll_vehicle_profile_card" value="!ff5e-card-power &quot;@{vehicle_name}&quot; &quot;Vehicle Profile&quot; &quot;Vehicle Info&quot; &quot;0&quot; &quot;0&quot; &quot;@{vehicle_type} | @{vehicle_scale} | AC @{vehicle_ac} | Speed @{vehicle_speed}&quot; &quot;@{vehicle_features}&quot;">
Info Card
</button>
</div>
</div>
</div>
<!-- =========================
VEHICLE WEAPONS TAB
========================== -->
<div class="tab-panel tab-vehicle-weapons">
<div class="ff7-card">
<h2>Vehicle Weapons</h2>
<fieldset class="repeating_vehicleweapons">
<div class="repeat-row vehicle-weapon">
<input type="text" name="attr_vehicle_weapon_name" placeholder="Weapon Name">
<input type="text" name="attr_vehicle_weapon_range" placeholder="Range / Area">
<input type="text" name="attr_vehicle_weapon_damage" placeholder="Damage Dice">
<input type="text" name="attr_vehicle_weapon_type" placeholder="Damage Type / Notes">
<input type="text" name="attr_vehicle_weapon_element" placeholder="Element / Detail">
<input type="number" name="attr_vehicle_weapon_bonus" placeholder="Attack Bonus" value="0">
<input type="number" name="attr_vehicle_weapon_mp_cost" placeholder="MP / Energy Cost" value="0">
<select name="attr_vehicle_weapon_scale">
<option value="personal">Personal</option>
<option value="armor">Armor</option>
<option value="ship">Ship</option>
</select>
<textarea name="attr_vehicle_weapon_notes" placeholder="Weapon notes, firing arc, reload rules, ammo, charges, misfire, and special effects."></textarea>
<button type="roll" name="roll_vehicle_weapon" value="!ff5e-card-attack &quot;@{vehicle_name}&quot; &quot;@{vehicle_weapon_name}&quot; &quot;Vehicle Weapon&quot; @{vehicle_weapon_bonus} &quot;@{vehicle_weapon_damage}&quot; @{vehicle_weapon_mp_cost} &quot;@{vehicle_weapon_notes}&quot;">
Fire
</button>
</div>
</fieldset>
</div>
</div>
<!-- =========================
VEHICLE SYSTEMS TAB
========================== -->
<div class="tab-panel tab-vehicle-systems">
<div class="ff7-card">
<h2>Systems & Cargo</h2>
<fieldset class="repeating_vehiclesystems">
<div class="repeat-row vehicle-system">
<input type="text" name="attr_vehicle_system_name" placeholder="System / Upgrade">
<input type="text" name="attr_vehicle_system_status" placeholder="Status">
<textarea name="attr_vehicle_system_notes" placeholder="System notes, upgrade effects, broken state, repair DC, power cost, and crew actions."></textarea>
<button type="roll" name="roll_vehicle_system_card" value="!ff5e-card-power &quot;@{vehicle_name}&quot; &quot;@{vehicle_system_name}&quot; &quot;Vehicle System&quot; &quot;0&quot; &quot;0&quot; &quot;Status: @{vehicle_system_status}&quot; &quot;@{vehicle_system_notes}&quot;">
Card
</button>
</div>
</fieldset>
</div>
</div>
<!-- =========================
VEHICLE SCALE COMBAT TAB
========================== -->
<div class="tab-panel tab-vehicle-scale">
<div class="ff7-card">
<h2>Scale Damage Calculator</h2>
<div class="scale-grid">
<div>
<label>Base Damage</label>
<input type="number" name="attr_scale_base_damage" value="0">
</div>
<div>
<label>Attacker Scale</label>
<select name="attr_scale_attacker">
<option value="personal">Personal</option>
<option value="armor">Armor</option>
<option value="ship">Ship</option>
</select>
</div>
<div>
<label>Target Scale</label>
<select name="attr_scale_target">
<option value="personal">Personal</option>
<option value="armor">Armor</option>
<option value="ship">Ship</option>
</select>
</div>
<div>
<label>Final Scaled Damage</label>
<div class="display-stat-pair">
<input type="number" name="attr_scale_final_damage" readonly>
<span name="attr_scale_final_damage"></span>
</div>
</div>
</div>
<label>Scale Result</label>
<input type="text" name="attr_scale_result_text" readonly>
<div class="button-strip">
<button type="roll" name="roll_scale_damage_card" value="!ff5e-card-power &quot;@{vehicle_name}&quot; &quot;Scale Damage&quot; &quot;Scale Combat&quot; &quot;@{scale_final_damage}&quot; &quot;0&quot; &quot;Base @{scale_base_damage} | @{scale_attacker} to @{scale_target}&quot; &quot;@{scale_result_text}&quot;">
Card
</button>
<button type="roll" name="roll_scale_damage_api" value="!ff5e-scale-damage @{scale_base_damage} @{scale_attacker} @{scale_target}">
API
</button>
</div>
</div>
</div>
</div>
</div>
<!-- =========================
THEMED ROLL TEMPLATES
API-BACKED CARD SYSTEM
Roll20-compliant custom templates
========================== -->
<rolltemplate class="sheet-rolltemplate-ff5e_card_d20">
<div class="sheet-ff5e-chat-card sheet-ff5e-chat-d20">
<div class="sheet-ff5e-card-title sheet-ff5e-title-d20">
<div class="sheet-ff5e-card-name">{{name}}</div>
<div class="sheet-ff5e-card-subtitle">{{actor}} • {{type}}</div>
</div>
{{#description}}
<div class="sheet-ff5e-card-description">
{{description}}
</div>
{{/description}}
<div class="sheet-ff5e-card-body">
<div class="sheet-ff5e-card-row">
<span>D20 Roll</span>
{{#crit}}
<strong class="sheet-ff5e-roll-box sheet-ff5e-nat20">{{d20}}</strong>
{{/crit}}
{{#fail}}
<strong class="sheet-ff5e-roll-box sheet-ff5e-nat1">{{d20}}</strong>
{{/fail}}
{{#normal}}
<strong class="sheet-ff5e-roll-box">{{d20}}</strong>
{{/normal}}
</div>
<div class="sheet-ff5e-card-row">
<span>Modifier</span>
<strong>{{modifier}}</strong>
</div>
<div class="sheet-ff5e-card-row sheet-ff5e-total-row">
<span>Total Result</span>
{{#crit}}
<strong class="sheet-ff5e-roll-box sheet-ff5e-nat20">{{total}}</strong>
{{/crit}}
{{#fail}}
<strong class="sheet-ff5e-roll-box sheet-ff5e-nat1">{{total}}</strong>
{{/fail}}
{{#normal}}
<strong class="sheet-ff5e-roll-box">{{total}}</strong>
{{/normal}}
</div>
<div class="sheet-ff5e-card-row">
<span>Rolled</span>
<strong>{{formula}}</strong>
</div>
</div>
</div>
</rolltemplate>
<rolltemplate class="sheet-rolltemplate-ff5e_card_attack">
<div class="sheet-ff5e-chat-card sheet-ff5e-chat-attack">
<div class="sheet-ff5e-card-title sheet-ff5e-title-attack">
<div class="sheet-ff5e-card-name">{{name}}</div>
<div class="sheet-ff5e-card-subtitle">{{actor}} • {{type}}</div>
</div>
{{#description}}
<div class="sheet-ff5e-card-description">
{{description}}
</div>
{{/description}}
<div class="sheet-ff5e-card-body">
<div class="sheet-ff5e-card-row">
<span>MP Cost</span>
<strong>{{mpcost}}</strong>
</div>
<div class="sheet-ff5e-card-row sheet-ff5e-total-row">
<span>Attack Roll</span>
{{#crit}}
<strong class="sheet-ff5e-roll-box sheet-ff5e-nat20">{{attacktotal}}</strong>
{{/crit}}
{{#fail}}
<strong class="sheet-ff5e-roll-box sheet-ff5e-nat1">{{attacktotal}}</strong>
{{/fail}}
{{#normal}}
<strong class="sheet-ff5e-roll-box">{{attacktotal}}</strong>
{{/normal}}
</div>
<div class="sheet-ff5e-card-row">
<span>D20 Roll</span>
{{#crit}}
<strong class="sheet-ff5e-roll-box sheet-ff5e-nat20">{{attackd20}}</strong>
{{/crit}}
{{#fail}}
<strong class="sheet-ff5e-roll-box sheet-ff5e-nat1">{{attackd20}}</strong>
{{/fail}}
{{#normal}}
<strong class="sheet-ff5e-roll-box">{{attackd20}}</strong>
{{/normal}}
</div>
<div class="sheet-ff5e-card-row">
<span>Modifier</span>
<strong>{{attackmodifier}}</strong>
</div>
<div class="sheet-ff5e-card-row">
<span>Rolled</span>
<strong>{{attackformula}}</strong>
</div>
<div class="sheet-ff5e-card-row sheet-ff5e-total-row">
<span>Damage</span>
<strong class="sheet-ff5e-roll-box sheet-ff5e-damage-box">{{damage}}</strong>
</div>
<div class="sheet-ff5e-card-row">
<span>Damage Roll</span>
<strong>{{damageformula}}</strong>
</div>
</div>
</div>
</rolltemplate>
<rolltemplate class="sheet-rolltemplate-ff5e_card_power">
<div class="sheet-ff5e-chat-card sheet-ff5e-chat-power">
<div class="sheet-ff5e-card-title sheet-ff5e-title-power">
<div class="sheet-ff5e-card-name">{{name}}</div>
<div class="sheet-ff5e-card-subtitle">{{actor}} • {{type}}</div>
</div>
{{#description}}
<div class="sheet-ff5e-card-description">
{{description}}
</div>
{{/description}}
<div class="sheet-ff5e-card-body">
<div class="sheet-ff5e-card-row">
<span>MP / Cost</span>
<strong>{{mpcost}}</strong>
</div>
{{#detail}}
<div class="sheet-ff5e-card-row sheet-ff5e-detail-row">
<span>Details</span>
<strong>{{detail}}</strong>
</div>
{{/detail}}
<div class="sheet-ff5e-card-row sheet-ff5e-total-row">
<span>Result</span>
<strong class="sheet-ff5e-roll-box sheet-ff5e-power-box">{{result}}</strong>
</div>
<div class="sheet-ff5e-card-row">
<span>Rolled</span>
<strong>{{formula}}</strong>
</div>
</div>
</div>
</rolltemplate>
<rolltemplate class="sheet-rolltemplate-ff5e_card_resource">
<div class="sheet-ff5e-chat-card sheet-ff5e-chat-resource">
<div class="sheet-ff5e-card-title sheet-ff5e-title-resource">
<div class="sheet-ff5e-card-name">{{name}}</div>
<div class="sheet-ff5e-card-subtitle">{{actor}} • {{type}}</div>
</div>
<div class="sheet-ff5e-card-body">
<div class="sheet-ff5e-resource-change">
<span>{{before}}</span>
<strong></strong>
<span>{{after}}</span>
</div>
</div>
{{#description}}
<div class="sheet-ff5e-card-description">
{{description}}
</div>
{{/description}}
</div>
</rolltemplate>
<!-- =========================
SHEET WORKERS
========================== -->
<script type="text/worker">
/* =========================
CORE HELPERS
========================= */
var FF5E = {
mod: function(score) {
return Math.floor((parseInt(score || 10, 10) - 10) / 2);
},
prof: function(level) {
level = parseInt(level || 1, 10);
if (level >= 17) return 6;
if (level >= 13) return 5;
if (level >= 9) return 4;
if (level >= 5) return 3;
return 2;
},
baselineCP: function(level) {
level = parseInt(level || 1, 10);
return 10 + ((level - 1) * 2);
},
bool: function(value) {
value = String(value || "0").toLowerCase();
return value === "1" || value === "on" || value === "true" || value === "yes";
},
number: function(value, fallback) {
var parsed = parseInt(value, 10);
return isNaN(parsed) ? (fallback || 0) : parsed;
},
blankBonuses: function() {
return {
strength: 0,
dexterity: 0,
constitution: 0,
intelligence: 0,
wisdom: 0,
charisma: 0
};
},
addBonus: function(bonuses, ability, amount) {
if (ability && Object.prototype.hasOwnProperty.call(bonuses, ability)) {
bonuses[ability] += parseInt(amount || 0, 10);
}
},
clampResource: function(current, max, amount, mode) {
current = FF5E.number(current, 0);
max = FF5E.number(max, 0);
amount = FF5E.number(amount, 0);
var next = current;
if (mode === "add") {
next = current + amount;
}
if (mode === "subtract") {
next = current - amount;
}
if (max > 0) {
next = Math.min(next, max);
}
return Math.max(0, next);
},
proficiencyPart: function(profBonus, proficient, expert) {
profBonus = FF5E.number(profBonus, 2);
if (FF5E.bool(expert)) {
return profBonus * 2;
}
if (FF5E.bool(proficient)) {
return profBonus;
}
return 0;
},
saveTotal: function(abilityMod, profBonus, proficient, miscBonus) {
abilityMod = FF5E.number(abilityMod, 0);
profBonus = FF5E.number(profBonus, 2);
miscBonus = FF5E.number(miscBonus, 0);
return abilityMod + miscBonus + (FF5E.bool(proficient) ? profBonus : 0);
},
skillTotal: function(abilityMod, profBonus, proficient, expert, miscBonus) {
abilityMod = FF5E.number(abilityMod, 0);
profBonus = FF5E.number(profBonus, 2);
miscBonus = FF5E.number(miscBonus, 0);
return abilityMod + miscBonus + FF5E.proficiencyPart(profBonus, proficient, expert);
},
expNextByLevel: function(level) {
level = FF5E.number(level, 1);
var table = {
1: 300,
2: 900,
3: 2700,
4: 6500,
5: 14000,
6: 23000,
7: 34000,
8: 48000,
9: 64000,
10: 85000,
11: 100000,
12: 120000,
13: 140000,
14: 165000,
15: 195000,
16: 225000,
17: 265000,
18: 305000,
19: 355000,
20: 0
};
return table[level] || 0;
},
scaleRank: {
personal: 1,
armor: 2,
ship: 3
},
scaleDamage: function(baseDamage, attackerScale, targetScale) {
var attacker = FF5E.scaleRank[attackerScale] || 1;
var target = FF5E.scaleRank[targetScale] || 1;
var multiplier = 1;
if (attacker < target) multiplier = 0.1;
if (attacker > target) multiplier = 10;
return Math.max(0, Math.floor(FF5E.number(baseDamage, 0) * multiplier));
},
affinityDamage: function(baseDamage, affinity) {
var dmg = FF5E.number(baseDamage, 0);
var result = "Normal";
if (affinity === "Weak") {
dmg = Math.floor(dmg * 1.5);
result = "Weak: x1.5 damage";
}
if (affinity === "Resist") {
dmg = Math.floor(dmg / 2);
result = "Resist: half damage";
}
if (affinity === "Null") {
dmg = 0;
result = "Null: no damage";
}
if (affinity === "Absorb") {
dmg = dmg * -1;
result = "Absorb: healing instead of damage";
}
return {
damage: dmg,
result: result
};
}
};
/* =========================
FULL RACE DATA
========================= */
var FF5E_FULL_RACES = {
"Hume": {
speed: 30,
cp_bonus: 2,
features: "Ability Score Increase: use Bonus Choice 1 and Bonus Choice 2. Endless Potential: +2 starting CP. Skill Proficiency: choice of any one skill."
},
"Miqo'te": {
speed: 35,
bonuses: { dexterity: 2 },
variants: {
"Seeker": { charisma: 1 },
"Keeper": { wisdom: 1 }
},
features: "Heightened Senses: Hearing and Smell. Skill Proficiency: Acrobatics. Feline Grace: no damage from falls of 30 feet or less."
},
"Elezen": {
speed: 30,
bonuses: { intelligence: 2 },
variants: {
"Wildwood": { dexterity: 1 },
"Duskwight": { constitution: 1 }
},
features: "Long-Limbed: melee reach increased by 5 feet. Skill Proficiency: History. Keen Mind: recall anything seen or heard within the past month."
},
"Lalafell": {
speed: 25,
bonuses: { charisma: 2, intelligence: 1 },
features: "Resilient: advantage on INT/WIS/CHA saves against magic. Skill Proficiency: Deception. Nimble Escape: move through spaces of larger creatures."
},
"Roegadyn": {
speed: 30,
bonuses: { constitution: 2, strength: 1 },
hp_per_level_bonus: 1,
features: "Toughness: maximum HP increases by +1 per character level. Skill Proficiency: Intimidation. Immovable: advantage against prone/forced movement."
},
"Viera": {
speed: 35,
bonuses: { dexterity: 2 },
variants: {
"Rava": { wisdom: 1 },
"Veena": { intelligence: 1 }
},
features: "Heightened Senses: Hearing. Jumping: jump distance doubled and ignore falling damage under 30 feet. Spellcasting: Druidcraft cantrip."
},
"Au Ra": {
speed: 30,
bonuses: { constitution: 2 },
variants: {
"Raen": { wisdom: 1 },
"Xaela": { strength: 1 }
},
natural_ac_base: 12,
features: "Raen: resistance to Radiant damage. Xaela: resistance to Cold damage. Ancestral Scales: unarmored AC is 12 + DEX modifier. Skill Proficiency: Insight."
},
"Hrothgar": {
speed: 30,
bonuses: { strength: 2, constitution: 1 },
features: "Natural Weapons: claws/fangs deal 1d6 + STR. Lancet: once per short rest gain temporary HP after hitting with melee attack. Skill Proficiency: Survival."
},
"Moogle": {
speed: 25,
bonuses: { intelligence: 2, charisma: 1 },
fly_speed: 30,
features: "Flight: 30 ft fly speed, cannot wear medium or heavy armor. Tool Proficiency: Tinker's Tools and Vehicles Airships. Inconspicuous."
},
"Bangaa": {
speed: 30,
bonuses: { strength: 2, constitution: 1 },
natural_ac_base: 13,
features: "Reptilian Hide: unarmored AC is 13 + DEX modifier. Edge: advantage on STR Athletics checks for grappling or shoving."
},
"Al Bhed": {
speed: 30,
bonuses: { intelligence: 2, dexterity: 1 },
features: "Salvager: advantage on Investigation checks to understand or repair machinery. Tool Proficiency: Thieves' Tools and Tinker's Tools. Cipher Tongue."
},
"Cetra": {
speed: 30,
bonuses: { wisdom: 2, charisma: 1 },
mp_bonus: 10,
features: "Energy Bonus: +10 maximum MP. Planet's Pulse: cast Detect Magic at will without MP. Skill Proficiency: Nature."
},
"Burmecian": {
speed: 35,
bonuses: { dexterity: 2, constitution: 1 },
features: "Jumping: jump distance tripled and ignore first 50 feet of falling damage. Weapon Proficiency: Polearms/Spears. Rain Dancer."
},
"Guado": {
speed: 30,
bonuses: { charisma: 2, wisdom: 1 },
features: "Spellcasting: Minor Illusion cantrip. Macalania's Step: ignore difficult terrain from roots, vines, and natural forest growth. Skill Proficiency: Religion."
},
"Nu Mou": {
speed: 25,
bonuses: { wisdom: 2, intelligence: 1 },
mp_bonus: 5,
features: "Beast Speaker: communicate simple ideas to beasts and monstrosities. Skill Proficiency: Animal Handling. Energy Bonus: +5 maximum MP."
},
"Dwarf": {
speed: 25,
bonuses: { constitution: 2 },
variants: {
"Tholl": { intelligence: 1 },
"Gogg": { strength: 1 }
},
features: "Resistance: Poison damage and advantage against poison. Tool Proficiency: Smith's Tools. Darkvision: 60 feet."
},
"Garlean": {
speed: 30,
bonuses: { strength: 2, intelligence: 2 },
mp_override: 0,
chassis_cp_bonus: 3,
features: "Aetherial Ineptitude: 0 MP, cannot purchase Spellcasting Attributes, use Materia, or cast magic natively. Magitek Mastery: +3 CP for Combat Techniques, Armour, or Tech/Gadget Attributes. Spatial Awareness: advantage on Initiative."
},
"Hybrid": {
speed: 30,
features: "Custom Lineage: use Bonus Choice 1 and Bonus Choice 2, then manually add remaining lineage traits as needed."
}
};
/* =========================
FULL JOB DATA
========================= */
var FF5E_FULL_JOBS = {
"Freelancer": { chassis: "Custom", hit_die: 8, role: "Flexible / Custom", spellcasting: "Optional" },
"Custom": { chassis: "Custom", hit_die: 8, role: "Custom Class / Job", spellcasting: "Optional" },
"Warrior": { chassis: "Warrior", hit_die: 10, role: "Vanguard Frontliner", spellcasting: "No" },
"Fighter": { chassis: "Warrior", hit_die: 10, role: "Weapon Specialist", spellcasting: "No" },
"Barbarian": { chassis: "Warrior", hit_die: 12, role: "Rage / Heavy Frontliner", spellcasting: "No" },
"Paladin": { chassis: "Warrior", hit_die: 10, role: "Tank / Holy Defender", spellcasting: "Optional" },
"Dark Knight": { chassis: "Warrior", hit_die: 10, role: "Drain Tank / Dark Striker", spellcasting: "Optional" },
"Gunbreaker": { chassis: "Warrior", hit_die: 10, role: "Tank / Magitek Weapon Specialist", spellcasting: "No" },
"Samurai": { chassis: "Warrior", hit_die: 10, role: "Burst Melee Striker", spellcasting: "No" },
"Dragoon": { chassis: "Warrior", hit_die: 10, role: "Jumping Vanguard / Anti-Flying Striker", spellcasting: "No" },
"Reaper": { chassis: "Warrior", hit_die: 10, role: "Dark Melee Striker / Avatar", spellcasting: "Optional" },
"Viper": { chassis: "Adept", hit_die: 8, role: "Dual-Blade Skirmisher", spellcasting: "No" },
"Monk": { chassis: "Adept", hit_die: 8, role: "Unarmed Striker", spellcasting: "No" },
"Mystic Knight": { chassis: "Adept", hit_die: 8, role: "Spellblade / Enchanted Weapon", spellcasting: "Intelligence" },
"Rune Knight": { chassis: "Adept", hit_die: 8, role: "Runic Defender / Spellblade", spellcasting: "Wisdom" },
"Berserker": { chassis: "Warrior", hit_die: 12, role: "High-Risk Melee Damage", spellcasting: "No" },
"Onion Knight": { chassis: "Custom", hit_die: 8, role: "Scaling Generalist", spellcasting: "Optional" },
"Rogue": { chassis: "Expert", hit_die: 8, role: "Precision / Skills", spellcasting: "No" },
"Thief": { chassis: "Expert", hit_die: 8, role: "Utility / Steal / Scout", spellcasting: "No" },
"Ninja": { chassis: "Expert", hit_die: 8, role: "Skirmisher / Stealth Striker", spellcasting: "Optional" },
"Ranger": { chassis: "Expert", hit_die: 8, role: "Ranged Scout", spellcasting: "Optional" },
"Archer": { chassis: "Expert", hit_die: 8, role: "Ranged Attacker", spellcasting: "No" },
"Sniper": { chassis: "Expert", hit_die: 8, role: "Precision Ranged Striker", spellcasting: "No" },
"Machinist": { chassis: "Expert", hit_die: 8, role: "Firearms / Gadgets / Magitek", spellcasting: "No" },
"Engineer": { chassis: "Expert", hit_die: 8, role: "Machines / Gadgets / Repair", spellcasting: "No" },
"Artificer": { chassis: "Expert", hit_die: 8, role: "Infusions / Crafting / Tech Magic", spellcasting: "Intelligence" },
"Bard": { chassis: "Expert", hit_die: 8, role: "Support / Songs", spellcasting: "Charisma" },
"Dancer": { chassis: "Expert", hit_die: 8, role: "Support / Mobility / Charm", spellcasting: "Charisma" },
"Alchemist": { chassis: "Expert", hit_die: 8, role: "Items / Crafting / Potion Support", spellcasting: "Optional" },
"Chemist": { chassis: "Expert", hit_die: 8, role: "Items / Mix / Recovery", spellcasting: "No" },
"Beastmaster": { chassis: "Expert", hit_die: 8, role: "Creature Control / Monster Tactics", spellcasting: "Optional" },
"Puppetmaster": { chassis: "Expert", hit_die: 8, role: "Automaton Controller", spellcasting: "No" },
"Corsair": { chassis: "Expert", hit_die: 8, role: "Guns / Luck / Party Support", spellcasting: "Optional" },
"Gambler": { chassis: "Expert", hit_die: 8, role: "Luck / Risk Effects", spellcasting: "Optional" },
"Mime": { chassis: "Expert", hit_die: 8, role: "Copycat / Reactive Utility", spellcasting: "Optional" },
"Black Mage": { chassis: "Mage", hit_die: 6, role: "Elemental Damage Caster", spellcasting: "Intelligence" },
"White Mage": { chassis: "Mage", hit_die: 6, role: "Healing / Holy Support", spellcasting: "Wisdom" },
"Red Mage": { chassis: "Adept", hit_die: 8, role: "Hybrid Spellblade", spellcasting: "Charisma" },
"Blue Mage": { chassis: "Adept", hit_die: 8, role: "Monster Magic / Adaptive Caster", spellcasting: "Charisma" },
"Time Mage": { chassis: "Mage", hit_die: 6, role: "Haste / Slow / Time Control", spellcasting: "Intelligence" },
"Green Mage": { chassis: "Mage", hit_die: 6, role: "Buffs / Debuffs / Status Magic", spellcasting: "Wisdom" },
"Geomancer": { chassis: "Mage", hit_die: 8, role: "Terrain / Nature Magic", spellcasting: "Wisdom" },
"Summoner": { chassis: "Mage", hit_die: 6, role: "Eidolons / Primal Magic", spellcasting: "Charisma" },
"Scholar": { chassis: "Mage", hit_die: 6, role: "Tactical Healing / Barrier Support", spellcasting: "Intelligence" },
"Sage": { chassis: "Mage", hit_die: 6, role: "Barrier Healing / Arcane Medicine", spellcasting: "Intelligence" },
"Astrologian": { chassis: "Mage", hit_die: 6, role: "Divination / Cards / Healing", spellcasting: "Wisdom" },
"Wizard": { chassis: "Mage", hit_die: 6, role: "Prepared Arcane Caster", spellcasting: "Intelligence" },
"Sorcerer": { chassis: "Mage", hit_die: 6, role: "Innate Arcane Caster", spellcasting: "Charisma" },
"Warlock": { chassis: "Mage", hit_die: 8, role: "Pact Magic / Dark Patron", spellcasting: "Charisma" },
"Cleric": { chassis: "Mage", hit_die: 8, role: "Divine Caster / Support", spellcasting: "Wisdom" },
"Druid": { chassis: "Mage", hit_die: 8, role: "Nature Magic / Forms", spellcasting: "Wisdom" },
"Oracle": { chassis: "Mage", hit_die: 6, role: "Prophecy / Curse / Support", spellcasting: "Wisdom" },
"Necromancer": { chassis: "Mage", hit_die: 6, role: "Undead / Dark Magic", spellcasting: "Intelligence" },
"Pictomancer": { chassis: "Mage", hit_die: 6, role: "Painted Constructs / Arcane Art", spellcasting: "Intelligence" }
};
/* =========================
VEHICLE DATA
========================= */
var FF5E_VEHICLE = {
scaleHPBase: function(type) {
var table = {
mount: 20,
warmachina: 100,
land_vehicle: 50,
airship: 150,
dreadnought: 300
};
return table[type] || 50;
},
defaultScale: function(type) {
var table = {
mount: "personal",
warmachina: "armor",
land_vehicle: "armor",
airship: "ship",
dreadnought: "ship"
};
return table[type] || "armor";
}
};
/* =========================
RESOURCE BUTTON HELPERS
========================= */
function adjustResource(currentAttr, maxAttr, adjustAttr, mode) {
getAttrs([currentAttr, maxAttr, adjustAttr], function(values) {
var current = FF5E.number(values[currentAttr], 0);
var max = FF5E.number(values[maxAttr], 0);
var amount = FF5E.number(values[adjustAttr], 0);
var next = FF5E.clampResource(current, max, amount, mode);
var update = {};
update[currentAttr] = next;
setAttrs(update);
});
}
function adjustUnboundedNumber(currentAttr, adjustAttr, mode, minimum) {
getAttrs([currentAttr, adjustAttr], function(values) {
var current = FF5E.number(values[currentAttr], 0);
var amount = FF5E.number(values[adjustAttr], 0);
var next = mode === "add" ? current + amount : current - amount;
if (minimum !== undefined) {
next = Math.max(minimum, next);
}
var update = {};
update[currentAttr] = next;
setAttrs(update);
});
}
/* Character resource buttons */
on("clicked:hp_add", function() {
adjustResource("hp_current", "hp_max", "hp_adjust", "add");
});
on("clicked:hp_subtract", function() {
adjustResource("hp_current", "hp_max", "hp_adjust", "subtract");
});
on("clicked:mp_add", function() {
adjustResource("mp_current", "mp_max", "mp_adjust", "add");
});
on("clicked:mp_subtract", function() {
adjustResource("mp_current", "mp_max", "mp_adjust", "subtract");
});
on("clicked:limit_add", function() {
adjustResource("limit_current", "limit_max", "limit_adjust", "add");
});
on("clicked:limit_subtract", function() {
adjustResource("limit_current", "limit_max", "limit_adjust", "subtract");
});
on("clicked:exp_add", function() {
adjustUnboundedNumber("exp_current", "exp_adjust", "add", 0);
});
on("clicked:exp_subtract", function() {
adjustUnboundedNumber("exp_current", "exp_adjust", "subtract", 0);
});
/* Monster resource buttons */
on("clicked:npc_hp_add", function() {
adjustResource("npc_hp_current", "npc_hp_max", "npc_hp_adjust", "add");
});
on("clicked:npc_hp_subtract", function() {
adjustResource("npc_hp_current", "npc_hp_max", "npc_hp_adjust", "subtract");
});
on("clicked:npc_mp_add", function() {
adjustResource("npc_mp_current", "npc_mp_max", "npc_mp_adjust", "add");
});
on("clicked:npc_mp_subtract", function() {
adjustResource("npc_mp_current", "npc_mp_max", "npc_mp_adjust", "subtract");
});
on("clicked:npc_limit_add", function() {
adjustResource("npc_limit_current", "npc_limit_max", "npc_limit_adjust", "add");
});
on("clicked:npc_limit_subtract", function() {
adjustResource("npc_limit_current", "npc_limit_max", "npc_limit_adjust", "subtract");
});
on("clicked:boss_phase_add", function() {
adjustUnboundedNumber("boss_phase", "boss_phase_adjust", "add", 1);
});
on("clicked:boss_phase_subtract", function() {
adjustUnboundedNumber("boss_phase", "boss_phase_adjust", "subtract", 1);
});
/* Vehicle resource buttons */
on("clicked:vehicle_hp_add", function() {
adjustResource("vehicle_hp_current", "vehicle_hp_max", "vehicle_hp_adjust", "add");
});
on("clicked:vehicle_hp_subtract", function() {
adjustResource("vehicle_hp_current", "vehicle_hp_max", "vehicle_hp_adjust", "subtract");
});
on("clicked:vehicle_mp_add", function() {
adjustResource("vehicle_mp_current", "vehicle_mp_max", "vehicle_mp_adjust", "add");
});
on("clicked:vehicle_mp_subtract", function() {
adjustResource("vehicle_mp_current", "vehicle_mp_max", "vehicle_mp_adjust", "subtract");
});
on("clicked:vehicle_limit_add", function() {
adjustResource("vehicle_limit_current", "vehicle_limit_max", "vehicle_limit_adjust", "add");
});
on("clicked:vehicle_limit_subtract", function() {
adjustResource("vehicle_limit_current", "vehicle_limit_max", "vehicle_limit_adjust", "subtract");
});
on("clicked:vehicle_shield_add", function() {
adjustResource("vehicle_shield_current", "vehicle_shield_max", "vehicle_shield_adjust", "add");
});
on("clicked:vehicle_shield_subtract", function() {
adjustResource("vehicle_shield_current", "vehicle_shield_max", "vehicle_shield_adjust", "subtract");
});
/* =========================
MODE / TAB BUTTONS
========================= */
on("clicked:mode_character", function() {
setAttrs({ sheet_mode: "character", sheet_tab: "overview" });
});
on("clicked:mode_monster", function() {
setAttrs({ sheet_mode: "monster", sheet_tab: "monster-core" });
});
on("clicked:mode_vehicle", function() {
setAttrs({ sheet_mode: "vehicle", sheet_tab: "vehicle-core" });
});
on("clicked:tab_overview", function() { setAttrs({ sheet_tab: "overview" }); });
on("clicked:tab_cp", function() { setAttrs({ sheet_tab: "cp" }); });
on("clicked:tab_combat", function() { setAttrs({ sheet_tab: "combat" }); });
on("clicked:tab_magic", function() { setAttrs({ sheet_tab: "magic" }); });
on("clicked:tab_equipment", function() { setAttrs({ sheet_tab: "equipment" }); });
on("clicked:tab_status", function() { setAttrs({ sheet_tab: "status" }); });
on("clicked:tab_bio", function() { setAttrs({ sheet_tab: "bio" }); });
on("clicked:tab_monster_core", function() { setAttrs({ sheet_tab: "monster-core" }); });
on("clicked:tab_monster_actions", function() { setAttrs({ sheet_tab: "monster-actions" }); });
on("clicked:tab_monster_status", function() { setAttrs({ sheet_tab: "monster-status" }); });
on("clicked:tab_monster_import", function() { setAttrs({ sheet_tab: "monster-import" }); });
on("clicked:tab_vehicle_core", function() { setAttrs({ sheet_tab: "vehicle-core" }); });
on("clicked:tab_vehicle_weapons", function() { setAttrs({ sheet_tab: "vehicle-weapons" }); });
on("clicked:tab_vehicle_systems", function() { setAttrs({ sheet_tab: "vehicle-systems" }); });
on("clicked:tab_vehicle_scale", function() { setAttrs({ sheet_tab: "vehicle-scale" }); });
/* =========================
JOB LEVELS / TOTAL LEVEL / EXP
Proficiency is now editable/manual.
========================= */
function updateTotalLevel() {
getAttrs(["primary_job_level", "secondary_job_level", "exp_next", "level"], function(values) {
var primary = Math.max(0, FF5E.number(values.primary_job_level, 1));
var secondary = Math.max(0, FF5E.number(values.secondary_job_level, 0));
var total = Math.max(1, primary + secondary);
var updates = {
level: total,
cp_baseline: FF5E.baselineCP(total)
};
if (!values.exp_next || FF5E.number(values.exp_next, 0) === 0) {
updates.exp_next = FF5E.expNextByLevel(total);
}
setAttrs(updates);
});
}
function updateExpTracker() {
getAttrs(["exp_current", "exp_next", "level"], function(values) {
var current = Math.max(0, FF5E.number(values.exp_current, 0));
var next = Math.max(0, FF5E.number(values.exp_next, FF5E.expNextByLevel(values.level)));
var remaining = Math.max(0, next - current);
var status = "Tracking";
if (next <= 0) {
status = "Max Level / Manual";
remaining = 0;
} else if (current >= next) {
status = "Ready to Level";
remaining = 0;
} else {
status = remaining + " EXP needed";
}
setAttrs({
exp_current: current,
exp_remaining: remaining,
exp_status: status
});
});
}
on("change:primary_job_level change:secondary_job_level sheet:opened", updateTotalLevel);
on("change:exp_current change:exp_next change:level sheet:opened", updateExpTracker);
/* =========================
RACE + EFFECTIVE STATS
Race features stay editable.
========================= */
function recalculateEffectiveStats() {
getAttrs([
"strength",
"dexterity",
"constitution",
"intelligence",
"wisdom",
"charisma",
"race",
"race_variant",
"race_choice_1",
"race_choice_2",
"race_features"
], function(values) {
var race = FF5E_FULL_RACES[values.race] || FF5E_FULL_RACES.Hume;
var bonuses = FF5E.blankBonuses();
if (race.bonuses) {
Object.keys(race.bonuses).forEach(function(ability) {
FF5E.addBonus(bonuses, ability, race.bonuses[ability]);
});
}
if (race.variants && values.race_variant && race.variants[values.race_variant]) {
var variant = race.variants[values.race_variant];
Object.keys(variant).forEach(function(ability) {
FF5E.addBonus(bonuses, ability, variant[ability]);
});
}
FF5E.addBonus(bonuses, values.race_choice_1, 1);
FF5E.addBonus(bonuses, values.race_choice_2, 1);
var totals = {};
var mods = {};
["strength", "dexterity", "constitution", "intelligence", "wisdom", "charisma"].forEach(function(ability) {
totals[ability] = FF5E.number(values[ability], 10) + bonuses[ability];
mods[ability] = FF5E.mod(totals[ability]);
});
var updates = {
strength_total: totals.strength,
dexterity_total: totals.dexterity,
constitution_total: totals.constitution,
intelligence_total: totals.intelligence,
wisdom_total: totals.wisdom,
charisma_total: totals.charisma,
strength_mod: mods.strength,
dexterity_mod: mods.dexterity,
constitution_mod: mods.constitution,
intelligence_mod: mods.intelligence,
wisdom_mod: mods.wisdom,
charisma_mod: mods.charisma,
initiative: mods.dexterity,
speed: race.speed || 30,
racial_cp_bonus: race.cp_bonus || 0,
fly_speed: race.fly_speed || 0,
racial_mp_bonus: race.mp_bonus || 0,
natural_ac_base: race.natural_ac_base || 0,
hp_per_level_bonus: race.hp_per_level_bonus || 0
};
if (!values.race_features) {
updates.race_features = race.features || "";
}
if (race.chassis_cp_bonus) {
updates.chassis_cp_bonus = race.chassis_cp_bonus;
}
if (race.mp_override === 0) {
updates.mp_max = 0;
updates.mp_current = 0;
updates.aetherial_ineptitude = "Yes";
} else {
updates.aetherial_ineptitude = "No";
}
setAttrs(updates);
});
}
on(
"change:race change:race_variant change:race_choice_1 change:race_choice_2 change:strength change:dexterity change:constitution change:intelligence change:wisdom change:charisma sheet:opened",
recalculateEffectiveStats
);
/* =========================
JOB PRESETS
========================= */
function applyJobPreset(jobName, prefix) {
var job = FF5E_FULL_JOBS[jobName] || FF5E_FULL_JOBS.Custom;
var updates = {};
if (prefix === "primary") {
updates.chassis = job.chassis;
updates.hit_die = job.hit_die;
updates.primary_role = job.role;
updates.job_spellcasting = job.spellcasting;
if (job.spellcasting === "Intelligence") {
updates.spellcasting_ability = "intelligence_mod";
}
if (job.spellcasting === "Wisdom") {
updates.spellcasting_ability = "wisdom_mod";
}
if (job.spellcasting === "Charisma") {
updates.spellcasting_ability = "charisma_mod";
}
}
if (prefix === "secondary") {
updates.secondary_role = jobName ? job.role : "";
updates.secondary_spellcasting = jobName ? job.spellcasting : "";
}
setAttrs(updates);
}
on("change:primary_job sheet:opened", function() {
getAttrs(["primary_job"], function(values) {
applyJobPreset(values.primary_job || "Freelancer", "primary");
});
});
on("change:secondary_job sheet:opened", function() {
getAttrs(["secondary_job"], function(values) {
applyJobPreset(values.secondary_job || "", "secondary");
});
});
/* =========================
CP ENGINE
========================= */
function updateCPTotalFromRepeating() {
getSectionIDs("attributes", function(ids) {
var fields = [];
ids.forEach(function(id) {
fields.push("repeating_attributes_" + id + "_attribute_cost");
});
fields.push("cp_baseline", "racial_cp_bonus", "defect_cp_bonus", "chassis_cp_bonus");
getAttrs(fields, function(values) {
var spent = 0;
ids.forEach(function(id) {
spent += FF5E.number(values["repeating_attributes_" + id + "_attribute_cost"], 0);
});
var baseline = FF5E.number(values.cp_baseline, 10);
var racial = FF5E.number(values.racial_cp_bonus, 0);
var defect = FF5E.number(values.defect_cp_bonus, 0);
var chassis = FF5E.number(values.chassis_cp_bonus, 0);
var total = baseline + racial + defect + chassis;
setAttrs({
cp_total: total,
cp_spent: spent,
cp_remaining: total - spent,
cp_warning: spent > total ? "Overspent" : "OK"
});
});
});
}
on(
"change:repeating_attributes:attribute_cost remove:repeating_attributes change:cp_baseline change:racial_cp_bonus change:defect_cp_bonus change:chassis_cp_bonus sheet:opened",
updateCPTotalFromRepeating
);
/* =========================
ABILITY CHECK AUTOMATION
========================= */
function updateAbilityChecks() {
getAttrs([
"strength_mod",
"dexterity_mod",
"constitution_mod",
"intelligence_mod",
"wisdom_mod",
"charisma_mod",
"proficiency_bonus",
"check_strength_prof",
"check_strength_expert",
"check_strength_bonus",
"check_dexterity_prof",
"check_dexterity_expert",
"check_dexterity_bonus",
"check_constitution_prof",
"check_constitution_expert",
"check_constitution_bonus",
"check_intelligence_prof",
"check_intelligence_expert",
"check_intelligence_bonus",
"check_wisdom_prof",
"check_wisdom_expert",
"check_wisdom_bonus",
"check_charisma_prof",
"check_charisma_expert",
"check_charisma_bonus"
], function(values) {
var prof = FF5E.number(values.proficiency_bonus, 2);
setAttrs({
check_strength_total: FF5E.skillTotal(values.strength_mod, prof, values.check_strength_prof, values.check_strength_expert, values.check_strength_bonus),
check_dexterity_total: FF5E.skillTotal(values.dexterity_mod, prof, values.check_dexterity_prof, values.check_dexterity_expert, values.check_dexterity_bonus),
check_constitution_total: FF5E.skillTotal(values.constitution_mod, prof, values.check_constitution_prof, values.check_constitution_expert, values.check_constitution_bonus),
check_intelligence_total: FF5E.skillTotal(values.intelligence_mod, prof, values.check_intelligence_prof, values.check_intelligence_expert, values.check_intelligence_bonus),
check_wisdom_total: FF5E.skillTotal(values.wisdom_mod, prof, values.check_wisdom_prof, values.check_wisdom_expert, values.check_wisdom_bonus),
check_charisma_total: FF5E.skillTotal(values.charisma_mod, prof, values.check_charisma_prof, values.check_charisma_expert, values.check_charisma_bonus)
});
});
}
on("change:strength_mod change:dexterity_mod change:constitution_mod change:intelligence_mod change:wisdom_mod change:charisma_mod change:proficiency_bonus sheet:opened", updateAbilityChecks);
on("change:check_strength_prof change:check_strength_expert change:check_strength_bonus", updateAbilityChecks);
on("change:check_dexterity_prof change:check_dexterity_expert change:check_dexterity_bonus", updateAbilityChecks);
on("change:check_constitution_prof change:check_constitution_expert change:check_constitution_bonus", updateAbilityChecks);
on("change:check_intelligence_prof change:check_intelligence_expert change:check_intelligence_bonus", updateAbilityChecks);
on("change:check_wisdom_prof change:check_wisdom_expert change:check_wisdom_bonus", updateAbilityChecks);
on("change:check_charisma_prof change:check_charisma_expert change:check_charisma_bonus", updateAbilityChecks);
/* =========================
SAVING THROW AUTOMATION
========================= */
function updateSavingThrows() {
getAttrs([
"strength_mod",
"dexterity_mod",
"constitution_mod",
"intelligence_mod",
"wisdom_mod",
"charisma_mod",
"proficiency_bonus",
"save_strength_prof",
"save_dexterity_prof",
"save_constitution_prof",
"save_intelligence_prof",
"save_wisdom_prof",
"save_charisma_prof",
"save_strength_bonus",
"save_dexterity_bonus",
"save_constitution_bonus",
"save_intelligence_bonus",
"save_wisdom_bonus",
"save_charisma_bonus"
], function(values) {
var prof = FF5E.number(values.proficiency_bonus, 2);
setAttrs({
save_strength_total: FF5E.saveTotal(values.strength_mod, prof, values.save_strength_prof, values.save_strength_bonus),
save_dexterity_total: FF5E.saveTotal(values.dexterity_mod, prof, values.save_dexterity_prof, values.save_dexterity_bonus),
save_constitution_total: FF5E.saveTotal(values.constitution_mod, prof, values.save_constitution_prof, values.save_constitution_bonus),
save_intelligence_total: FF5E.saveTotal(values.intelligence_mod, prof, values.save_intelligence_prof, values.save_intelligence_bonus),
save_wisdom_total: FF5E.saveTotal(values.wisdom_mod, prof, values.save_wisdom_prof, values.save_wisdom_bonus),
save_charisma_total: FF5E.saveTotal(values.charisma_mod, prof, values.save_charisma_prof, values.save_charisma_bonus)
});
});
}
on("change:strength_mod change:dexterity_mod change:constitution_mod change:intelligence_mod change:wisdom_mod change:charisma_mod change:proficiency_bonus sheet:opened", updateSavingThrows);
on("change:save_strength_prof change:save_dexterity_prof change:save_constitution_prof change:save_intelligence_prof change:save_wisdom_prof change:save_charisma_prof", updateSavingThrows);
on("change:save_strength_bonus change:save_dexterity_bonus change:save_constitution_bonus change:save_intelligence_bonus change:save_wisdom_bonus change:save_charisma_bonus", updateSavingThrows);
/* =========================
SKILL AUTOMATION
========================= */
function updateSkills() {
getAttrs([
"strength_mod",
"dexterity_mod",
"constitution_mod",
"intelligence_mod",
"wisdom_mod",
"charisma_mod",
"proficiency_bonus",
"skill_acrobatics_prof", "skill_acrobatics_expert", "skill_acrobatics_bonus",
"skill_animal_handling_prof", "skill_animal_handling_expert", "skill_animal_handling_bonus",
"skill_arcana_prof", "skill_arcana_expert", "skill_arcana_bonus",
"skill_athletics_prof", "skill_athletics_expert", "skill_athletics_bonus",
"skill_deception_prof", "skill_deception_expert", "skill_deception_bonus",
"skill_history_prof", "skill_history_expert", "skill_history_bonus",
"skill_insight_prof", "skill_insight_expert", "skill_insight_bonus",
"skill_intimidation_prof", "skill_intimidation_expert", "skill_intimidation_bonus",
"skill_investigation_prof", "skill_investigation_expert", "skill_investigation_bonus",
"skill_medicine_prof", "skill_medicine_expert", "skill_medicine_bonus",
"skill_nature_prof", "skill_nature_expert", "skill_nature_bonus",
"skill_perception_prof", "skill_perception_expert", "skill_perception_bonus",
"skill_performance_prof", "skill_performance_expert", "skill_performance_bonus",
"skill_persuasion_prof", "skill_persuasion_expert", "skill_persuasion_bonus",
"skill_religion_prof", "skill_religion_expert", "skill_religion_bonus",
"skill_sleight_of_hand_prof", "skill_sleight_of_hand_expert", "skill_sleight_of_hand_bonus",
"skill_stealth_prof", "skill_stealth_expert", "skill_stealth_bonus",
"skill_survival_prof", "skill_survival_expert", "skill_survival_bonus"
], function(values) {
var prof = FF5E.number(values.proficiency_bonus, 2);
setAttrs({
skill_acrobatics: FF5E.skillTotal(values.dexterity_mod, prof, values.skill_acrobatics_prof, values.skill_acrobatics_expert, values.skill_acrobatics_bonus),
skill_animal_handling: FF5E.skillTotal(values.wisdom_mod, prof, values.skill_animal_handling_prof, values.skill_animal_handling_expert, values.skill_animal_handling_bonus),
skill_arcana: FF5E.skillTotal(values.intelligence_mod, prof, values.skill_arcana_prof, values.skill_arcana_expert, values.skill_arcana_bonus),
skill_athletics: FF5E.skillTotal(values.strength_mod, prof, values.skill_athletics_prof, values.skill_athletics_expert, values.skill_athletics_bonus),
skill_deception: FF5E.skillTotal(values.charisma_mod, prof, values.skill_deception_prof, values.skill_deception_expert, values.skill_deception_bonus),
skill_history: FF5E.skillTotal(values.intelligence_mod, prof, values.skill_history_prof, values.skill_history_expert, values.skill_history_bonus),
skill_insight: FF5E.skillTotal(values.wisdom_mod, prof, values.skill_insight_prof, values.skill_insight_expert, values.skill_insight_bonus),
skill_intimidation: FF5E.skillTotal(values.charisma_mod, prof, values.skill_intimidation_prof, values.skill_intimidation_expert, values.skill_intimidation_bonus),
skill_investigation: FF5E.skillTotal(values.intelligence_mod, prof, values.skill_investigation_prof, values.skill_investigation_expert, values.skill_investigation_bonus),
skill_medicine: FF5E.skillTotal(values.wisdom_mod, prof, values.skill_medicine_prof, values.skill_medicine_expert, values.skill_medicine_bonus),
skill_nature: FF5E.skillTotal(values.intelligence_mod, prof, values.skill_nature_prof, values.skill_nature_expert, values.skill_nature_bonus),
skill_perception: FF5E.skillTotal(values.wisdom_mod, prof, values.skill_perception_prof, values.skill_perception_expert, values.skill_perception_bonus),
skill_performance: FF5E.skillTotal(values.charisma_mod, prof, values.skill_performance_prof, values.skill_performance_expert, values.skill_performance_bonus),
skill_persuasion: FF5E.skillTotal(values.charisma_mod, prof, values.skill_persuasion_prof, values.skill_persuasion_expert, values.skill_persuasion_bonus),
skill_religion: FF5E.skillTotal(values.intelligence_mod, prof, values.skill_religion_prof, values.skill_religion_expert, values.skill_religion_bonus),
skill_sleight_of_hand: FF5E.skillTotal(values.dexterity_mod, prof, values.skill_sleight_of_hand_prof, values.skill_sleight_of_hand_expert, values.skill_sleight_of_hand_bonus),
skill_stealth: FF5E.skillTotal(values.dexterity_mod, prof, values.skill_stealth_prof, values.skill_stealth_expert, values.skill_stealth_bonus),
skill_survival: FF5E.skillTotal(values.wisdom_mod, prof, values.skill_survival_prof, values.skill_survival_expert, values.skill_survival_bonus)
});
});
}
on("change:strength_mod change:dexterity_mod change:constitution_mod change:intelligence_mod change:wisdom_mod change:charisma_mod change:proficiency_bonus sheet:opened", updateSkills);
on("change:skill_acrobatics_prof change:skill_acrobatics_expert change:skill_acrobatics_bonus", updateSkills);
on("change:skill_animal_handling_prof change:skill_animal_handling_expert change:skill_animal_handling_bonus", updateSkills);
on("change:skill_arcana_prof change:skill_arcana_expert change:skill_arcana_bonus", updateSkills);
on("change:skill_athletics_prof change:skill_athletics_expert change:skill_athletics_bonus", updateSkills);
on("change:skill_deception_prof change:skill_deception_expert change:skill_deception_bonus", updateSkills);
on("change:skill_history_prof change:skill_history_expert change:skill_history_bonus", updateSkills);
on("change:skill_insight_prof change:skill_insight_expert change:skill_insight_bonus", updateSkills);
on("change:skill_intimidation_prof change:skill_intimidation_expert change:skill_intimidation_bonus", updateSkills);
on("change:skill_investigation_prof change:skill_investigation_expert change:skill_investigation_bonus", updateSkills);
on("change:skill_medicine_prof change:skill_medicine_expert change:skill_medicine_bonus", updateSkills);
on("change:skill_nature_prof change:skill_nature_expert change:skill_nature_bonus", updateSkills);
on("change:skill_perception_prof change:skill_perception_expert change:skill_perception_bonus", updateSkills);
on("change:skill_performance_prof change:skill_performance_expert change:skill_performance_bonus", updateSkills);
on("change:skill_persuasion_prof change:skill_persuasion_expert change:skill_persuasion_bonus", updateSkills);
on("change:skill_religion_prof change:skill_religion_expert change:skill_religion_bonus", updateSkills);
on("change:skill_sleight_of_hand_prof change:skill_sleight_of_hand_expert change:skill_sleight_of_hand_bonus", updateSkills);
on("change:skill_stealth_prof change:skill_stealth_expert change:skill_stealth_bonus", updateSkills);
on("change:skill_survival_prof change:skill_survival_expert change:skill_survival_bonus", updateSkills);
/* =========================
ATTACK BONUSES
========================= */
function updateRepeatingAttackBonuses() {
getSectionIDs("attacks", function(ids) {
var baseFields = [
"strength_mod",
"dexterity_mod",
"intelligence_mod",
"wisdom_mod",
"charisma_mod",
"proficiency_bonus"
];
var rowFields = [];
ids.forEach(function(id) {
rowFields.push("repeating_attacks_" + id + "_attack_stat");
rowFields.push("repeating_attacks_" + id + "_attack_proficient");
rowFields.push("repeating_attacks_" + id + "_attack_weapon_bonus");
});
getAttrs(baseFields.concat(rowFields), function(values) {
var updates = {};
var prof = FF5E.number(values.proficiency_bonus, 2);
ids.forEach(function(id) {
var statKey = values["repeating_attacks_" + id + "_attack_stat"] || "strength_mod";
var statMod = FF5E.number(values[statKey], 0);
var proficient = FF5E.bool(values["repeating_attacks_" + id + "_attack_proficient"]);
var weaponBonus = FF5E.number(values["repeating_attacks_" + id + "_attack_weapon_bonus"], 0);
updates["repeating_attacks_" + id + "_attack_total_bonus"] =
statMod + weaponBonus + (proficient ? prof : 0);
});
setAttrs(updates);
});
});
}
on(
"change:strength_mod change:dexterity_mod change:intelligence_mod change:wisdom_mod change:charisma_mod change:proficiency_bonus change:repeating_attacks:attack_stat change:repeating_attacks:attack_proficient change:repeating_attacks:attack_weapon_bonus remove:repeating_attacks sheet:opened",
updateRepeatingAttackBonuses
);
/* =========================
MATERIA BONUSES + SPELL LINKS
========================= */
function updateMateriaBonuses() {
getSectionIDs("materia", function(ids) {
var fields = [];
ids.forEach(function(id) {
fields.push("repeating_materia_" + id + "_materia_equipped");
fields.push("repeating_materia_" + id + "_materia_grants_spell");
fields.push("repeating_materia_" + id + "_materia_mp_bonus");
fields.push("repeating_materia_" + id + "_materia_str_bonus");
fields.push("repeating_materia_" + id + "_materia_dex_bonus");
fields.push("repeating_materia_" + id + "_materia_con_bonus");
fields.push("repeating_materia_" + id + "_materia_int_bonus");
fields.push("repeating_materia_" + id + "_materia_wis_bonus");
fields.push("repeating_materia_" + id + "_materia_cha_bonus");
});
getAttrs(fields, function(values) {
var mpBonus = 0;
var strBonus = 0;
var dexBonus = 0;
var conBonus = 0;
var intBonus = 0;
var wisBonus = 0;
var chaBonus = 0;
var grantedSpells = [];
ids.forEach(function(id) {
var equipped = values["repeating_materia_" + id + "_materia_equipped"] || "0";
if (equipped === "1") {
mpBonus += FF5E.number(values["repeating_materia_" + id + "_materia_mp_bonus"], 0);
strBonus += FF5E.number(values["repeating_materia_" + id + "_materia_str_bonus"], 0);
dexBonus += FF5E.number(values["repeating_materia_" + id + "_materia_dex_bonus"], 0);
conBonus += FF5E.number(values["repeating_materia_" + id + "_materia_con_bonus"], 0);
intBonus += FF5E.number(values["repeating_materia_" + id + "_materia_int_bonus"], 0);
wisBonus += FF5E.number(values["repeating_materia_" + id + "_materia_wis_bonus"], 0);
chaBonus += FF5E.number(values["repeating_materia_" + id + "_materia_cha_bonus"], 0);
var spell = values["repeating_materia_" + id + "_materia_grants_spell"];
if (spell) {
grantedSpells.push(String(spell).toLowerCase());
}
}
});
setAttrs({
materia_mp_bonus: mpBonus,
materia_str_bonus: strBonus,
materia_dex_bonus: dexBonus,
materia_con_bonus: conBonus,
materia_int_bonus: intBonus,
materia_wis_bonus: wisBonus,
materia_cha_bonus: chaBonus,
materia_granted_spells: grantedSpells.join(", ")
});
});
});
}
on(
"change:repeating_materia:materia_equipped change:repeating_materia:materia_mp_bonus change:repeating_materia:materia_str_bonus change:repeating_materia:materia_dex_bonus change:repeating_materia:materia_con_bonus change:repeating_materia:materia_int_bonus change:repeating_materia:materia_wis_bonus change:repeating_materia:materia_cha_bonus change:repeating_materia:materia_grants_spell remove:repeating_materia sheet:opened",
updateMateriaBonuses
);
function updateSpellUnlocksFromMateria() {
getSectionIDs("spells", function(spellIds) {
getAttrs(["materia_granted_spells"], function(baseValues) {
var granted = String(baseValues.materia_granted_spells || "").toLowerCase();
var fields = [];
spellIds.forEach(function(id) {
fields.push("repeating_spells_" + id + "_spell_name");
fields.push("repeating_spells_" + id + "_spell_source");
});
getAttrs(fields, function(values) {
var updates = {};
spellIds.forEach(function(id) {
var name = String(values["repeating_spells_" + id + "_spell_name"] || "").toLowerCase();
var source = values["repeating_spells_" + id + "_spell_source"] || "";
if (source === "Materia") {
updates["repeating_spells_" + id + "_spell_unlocked"] =
name && granted.indexOf(name) !== -1 ? "Yes" : "No";
} else {
updates["repeating_spells_" + id + "_spell_unlocked"] = "Yes";
}
});
setAttrs(updates);
});
});
});
}
on(
"change:materia_granted_spells change:repeating_spells:spell_name change:repeating_spells:spell_source remove:repeating_spells sheet:opened",
updateSpellUnlocksFromMateria
);
/* =========================
SPELLCASTING / MP
========================= */
function updateSpellcastingStats() {
getAttrs([
"spellcasting_ability",
"intelligence_mod",
"wisdom_mod",
"charisma_mod",
"level",
"proficiency_bonus",
"racial_mp_bonus",
"materia_mp_bonus",
"aetherial_ineptitude"
], function(values) {
if (values.aetherial_ineptitude === "Yes") {
setAttrs({
spellcasting_mod: 0,
spell_attack_bonus: 0,
spell_save_dc: 0,
total_mp_bonus: 0,
mp_max: 0,
mp_current: 0
});
return;
}
var level = FF5E.number(values.level, 1);
var prof = FF5E.number(values.proficiency_bonus, FF5E.prof(level));
var spellMod = FF5E.number(values.intelligence_mod, 0);
if (values.spellcasting_ability === "wisdom_mod") {
spellMod = FF5E.number(values.wisdom_mod, 0);
}
if (values.spellcasting_ability === "charisma_mod") {
spellMod = FF5E.number(values.charisma_mod, 0);
}
var racialMP = FF5E.number(values.racial_mp_bonus, 0);
var materiaMP = FF5E.number(values.materia_mp_bonus, 0);
var totalBonus = racialMP + materiaMP;
setAttrs({
spellcasting_mod: spellMod,
spell_attack_bonus: spellMod + prof,
spell_save_dc: 8 + prof + spellMod,
total_mp_bonus: totalBonus,
mp_max: Math.max(0, (spellMod * 2) + level + totalBonus)
});
});
}
on(
"change:spellcasting_ability change:intelligence_mod change:wisdom_mod change:charisma_mod change:level change:proficiency_bonus change:racial_mp_bonus change:materia_mp_bonus change:aetherial_ineptitude sheet:opened",
updateSpellcastingStats
);
/* =========================
ARMOR CLASS
========================= */
function updateArmorClass() {
getAttrs([
"armor_type",
"armor_base_ac",
"natural_ac_base",
"armor_bonus",
"shield_bonus",
"gear_ac_bonus",
"dexterity_mod"
], function(values) {
var dexMod = FF5E.number(values.dexterity_mod, 0);
var armorType = values.armor_type || "unarmored";
var base = FF5E.number(values.armor_base_ac, 10);
var naturalBase = FF5E.number(values.natural_ac_base, 0);
var armorBonus = FF5E.number(values.armor_bonus, 0);
var shield = FF5E.number(values.shield_bonus, 0);
var gear = FF5E.number(values.gear_ac_bonus, 0);
if (armorType === "natural" && naturalBase > 0) {
base = naturalBase;
}
var dexToAC = dexMod;
if (armorType === "medium") dexToAC = Math.min(dexMod, 2);
if (armorType === "heavy") dexToAC = 0;
setAttrs({
ac: base + dexToAC + armorBonus + shield + gear
});
});
}
on(
"change:armor_type change:armor_base_ac change:natural_ac_base change:armor_bonus change:shield_bonus change:gear_ac_bonus change:dexterity_mod sheet:opened",
updateArmorClass
);
/* =========================
LIMIT READY
========================= */
on("change:limit_current change:limit_max sheet:opened", function() {
getAttrs(["limit_current", "limit_max"], function(values) {
var current = FF5E.number(values.limit_current, 0);
var max = FF5E.number(values.limit_max, 100);
setAttrs({
limit_ready: current >= max ? "Yes" : "No"
});
});
});
/* =========================
NPC / BOSS AUTOMATION
========================= */
on("change:npc_level sheet:opened", function() {
getAttrs(["npc_level"], function(values) {
var level = FF5E.number(values.npc_level, 1);
setAttrs({
npc_proficiency_bonus: FF5E.prof(level)
});
});
});
on("change:npc_hp_current change:npc_hp_max sheet:opened", function() {
getAttrs(["npc_hp_current", "npc_hp_max"], function(values) {
var current = FF5E.number(values.npc_hp_current, 0);
var max = Math.max(1, FF5E.number(values.npc_hp_max, 1));
var pct = Math.floor((current / max) * 100);
var phaseSuggestion = 1;
if (pct <= 50) phaseSuggestion = 2;
if (pct <= 25) phaseSuggestion = 3;
if (pct <= 10) phaseSuggestion = 4;
setAttrs({
npc_hp_percent: pct,
boss_phase_suggested: phaseSuggestion
});
});
});
/* =========================
NPC AFFINITY DAMAGE HELPER
========================= */
function updateNpcAdjustedDamage() {
getAttrs([
"npc_incoming_damage",
"npc_incoming_element",
"npc_affinity_fire",
"npc_affinity_ice",
"npc_affinity_lightning",
"npc_affinity_water",
"npc_affinity_wind",
"npc_affinity_earth",
"npc_affinity_holy",
"npc_affinity_dark",
"npc_affinity_poison"
], function(values) {
var element = values.npc_incoming_element || "none";
var affinity = "Normal";
if (element !== "none") {
affinity = values["npc_affinity_" + element] || "Normal";
}
var result = FF5E.affinityDamage(values.npc_incoming_damage, affinity);
setAttrs({
npc_adjusted_damage: result.damage,
npc_damage_affinity_result: result.result
});
});
}
on(
"change:npc_incoming_damage change:npc_incoming_element change:npc_affinity_fire change:npc_affinity_ice change:npc_affinity_lightning change:npc_affinity_water change:npc_affinity_wind change:npc_affinity_earth change:npc_affinity_holy change:npc_affinity_dark change:npc_affinity_poison sheet:opened",
updateNpcAdjustedDamage
);
/* =========================
VEHICLE AUTOMATION
========================= */
on("change:vehicle_type sheet:opened", function() {
getAttrs(["vehicle_type", "vehicle_hp_max"], function(values) {
var type = values.vehicle_type || "land_vehicle";
var updates = {
vehicle_scale: FF5E_VEHICLE.defaultScale(type)
};
if (!values.vehicle_hp_max || FF5E.number(values.vehicle_hp_max, 0) === 0) {
updates.vehicle_hp_max = FF5E_VEHICLE.scaleHPBase(type);
}
setAttrs(updates);
});
});
on("change:vehicle_hp_current change:vehicle_hp_max sheet:opened", function() {
getAttrs(["vehicle_hp_current", "vehicle_hp_max"], function(values) {
var current = FF5E.number(values.vehicle_hp_current, 0);
var max = Math.max(1, FF5E.number(values.vehicle_hp_max, 1));
var pct = Math.max(0, Math.min(100, Math.floor((current / max) * 100)));
var condition = "Operational";
if (pct <= 50) condition = "Damaged";
if (pct <= 25) condition = "Critical";
if (pct <= 0) condition = "Disabled";
setAttrs({
vehicle_hp_percent: pct,
vehicle_condition: condition
});
});
});
/* =========================
SCALE DAMAGE HELPER
========================= */
function updateScaleDamageHelper() {
getAttrs(["scale_base_damage", "scale_attacker", "scale_target"], function(values) {
var baseDamage = FF5E.number(values.scale_base_damage, 0);
var attacker = values.scale_attacker || "personal";
var target = values.scale_target || "personal";
var finalDamage = FF5E.scaleDamage(baseDamage, attacker, target);
var text = "Same scale: normal damage.";
if ((FF5E.scaleRank[attacker] || 1) < (FF5E.scaleRank[target] || 1)) {
text = "Smaller attacker vs larger target: damage divided by 10.";
}
if ((FF5E.scaleRank[attacker] || 1) > (FF5E.scaleRank[target] || 1)) {
text = "Larger attacker vs smaller target: damage multiplied by 10.";
}
setAttrs({
scale_final_damage: finalDamage,
scale_result_text: text
});
});
}
on(
"change:scale_base_damage change:scale_attacker change:scale_target sheet:opened",
updateScaleDamageHelper
);
</script>