Files
roll20-character-sheets/Anyscape/Anyscape_Charsheet_roll20.html
T
AnyscapeRPG d35b4ae0a9 ActionPoints
Added Value boxes for Action Points along with reset button. removed "readonly" from speed
2025-12-29 10:01:42 -05:00

1042 lines
38 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<rolltemplate class="sheet-rolltemplate-check">
<div class="sheet-template-container">
<div class="sheet-template-title">{{name}}</div>
<div class="sheet-template-row">
<strong>Check:</strong> {{check}}
</div>
<div class="sheet-template-row">
<strong>Roll:</strong> {{roll}}
</div>
<div class="sheet-template-row">
<strong>Result:</strong> {{computed::result}}
</div>
<div class="sheet-template-row">
<strong>Degrees:</strong> {{computed::degrees}}
</div>
</div>
</rolltemplate>
<input type="hidden" class="sheet-tabstoggle" name="attr_sheetTab" value="core" />
<div>
<button type="action" name="act_core" class="sheet-button0">Core Stats</button>
<button type="action" name="act_inventory" class="sheet-button1">Inventory</button>
<button type="action" name="act_leveling" class="sheet-button2">Leveling</button>
<button type="action" name="act_magic" class="sheet-button3">Magic</button>
<button type="action" name="act_survival" class="sheet-button4">Survival</button>
</div>
<div class="sheet-core">
<!-- Ability Scores -->
<section class="ability-scores">
<h2>Character Info</h2>
<div class="score-grid">
<div>
<label>STRENGTH</label>
<input type="number" name="attr_str" min="10" max="70" step="5" value="20">
<input type="text" name="attr_str_mod" placeholder="Modifier">
</div>
<div>
<label>PERCEPTION</label>
<input type="number" name="attr_per" min="10" max="70" step="5" value="20">
<input type="text" name="attr_per_mod" placeholder="Modifier">
</div>
<div>
<label>ENDURANCE</label>
<input type="number" name="attr_end" min="10" max="70" step="5" value="20">
<input type="text" name="attr_end_mod" placeholder="Modifier">
</div>
<div>
<label>INTELLIGENCE</label>
<input type="number" name="attr_int" min="10" max="70" step="5" value="20">
<input type="text" name="attr_int_mod" placeholder="Modifier">
</div>
<div>
<label>AGILITY</label>
<input type="number" name="attr_agl" min="10" max="70" step="5" value="20">
<input type="text" name="attr_agl_mod" placeholder="Modifier">
</div>
<div>
<label>ACCURACY</label>
<input type="number" name="attr_acc" min="10" max="70" step="5" value="20">
<input type="text" name="attr_acc_mod" placeholder="Modifier">
</div>
<div>
<label>CHARISMA</label>
<input type="number" name="attr_cha" min="10" max="70" step="5" value="20">
<input type="text" name="attr_cha_mod" placeholder="Modifier">
</div>
<div>
<label>LUCK</label>
<input type="number" name="attr_lck" min="10" max="70" step="5" value="20">
<input type="text" name="attr_lck_mod" placeholder="Modifier">
</div>
<div>
<label>Luck Points</label>
<input type="number" name="attr_luck_points_current" min="0" max="attr_luck_points_max" step="1">
<span>Luck Point Max</span>
<span name="attr_luck_points_max"></span>
<span>: +2 DoS, ignore 1 Wound</span>
</div>
<div>
<label>Name:</label>
<input type="text" name="attr_character_name">
</div>
<div>
<label>Race:</label>
<select name="attr_race">
<option value="Human">Human</option>
<option value="Aetherial">Aetherial</option>
<option value="Orc">Orc</option>
<option value="Dwarf">Dwarf</option>
<option value="Elf">Elf</option>
<option value="Halfling">Halfling</option>
<option value="Gnome">Gnome</option>
<option value="Granitetouched">Granitetouched</option>
<option value="Sylvan">Sylvan</option>
<option value="Lizardmen">Lizardmen</option>
<option value="Elemental">Elemental</option>
</select>
</div>
<div>
<label>Racial Benefits:</label>
<span name="attr_racial_benefits">
</div>
<div>
<label>Weight:</label>
<input type="text" name="attr_weight">
</div>
<div>
<label>Height:</label>
<input type="text" name="attr_height">
</div>
<div>
<label>Reputation:</label>
<input type="text" name="attr_reputation">
</div>
<div>
<label>Features:</label>
<input type="text" name="attr_features">
</div>
<div>
<label>Critical Bonus:</label>
<input type="number" name="attr_lck_mod">
</div>
<div class="rest-actions">
<label>Rest Actions</label>
<button type="action" name="act_break">Break</button>
<button type="action" name="act_sleep">Sleep</button>
<!-- Hidden "Yes/No" buttons for confirmations -->
<button type="action" name="act_break_confirm" style="display:none;"></button>
<button type="action" name="act_sleep_confirm" style="display:none;"></button>
</div>
</div>
</section> <!-- end ability scores -->
<!-- Skills -->
<section>
<h2>Skills</h2>
<div class="skill-check">
<label for="attr_selected_skill">Skill:</label>
<select name="attr_selected_skill" id="attr_selected_skill">
<option value="athletics">Athletics (Phys)</option>
<option value="bows">Bows (ACC)</option>
<option value="carouse">Carouse (CHA)</option>
<option value="computers">*Computers (INT)</option>
<option value="disable">Disable (INT,AGL)</option>
<option value="drive">Drive (INT,AGL)</option>
<option value="engineer">*Engineer (INT)</option>
<option value="fly">*Fly (INT,AGL)</option>
<option value="guns">Guns (ACC)</option>
<option value="history">History (INT)</option>
<option value="intimidate">Intimidate (CHA)</option>
<option value="investigate">Investigate (INT,PER)</option>
<option value="melee">Melee Weapons (STR,AGL)</option>
<option value="medicine">*Medicine (INT,AGL)</option>
<option value="navigation">Navigation (PER)</option>
<option value="persuade">Persuade (CHA)</option>
<option value="repair">Repair (INT)</option>
<option value="science">*Science (INT)</option>
<option value="spellcraft">*Spellcraft (INT,PER)</option>
<option value="stealth">Stealth (AGL,PER)</option>
<option value="survival">Survival (INT,END)</option>
<option value="tactics">Tactics (INT)</option>
<option value="unarmed">Unarmed (STR,AGL)</option>
<option value="willpower">Willpower</option>
</select>
<label for="attr_selected_skill_ability">Ability:</label>
<select name="attr_selected_skill_ability" id="attr_selected_skill_ability">
<option value="str">STR</option>
<option value="agl">AGL</option>
<option value="end">END</option>
<option value="int">INT</option>
<option value="cha">CHA</option>
<option value="lck">LCK</option>
<option value="per">PER</option>
<option value="acc">ACC</option>
</select>
<button type="action" name="act_roll_selected_skill">Roll Skill Check</button>
</div>
<div class="skills-grid skills-align">
<div><label>Athletics (Phys.):</label><input type="number" name="attr_athletics" min="0" max="30" step="5" value="0"></div>
<div><label>Bows (ACC):</label><input type="number" name="attr_bows" min="0" max="30" step="5" value="0"></div>
<div><label>Carouse (CHA):</label><input type="number" name="attr_carouse" min="0" max="30" step="5" value="0"></div>
<div><label>*Computers (INT):</label><input type="number" name="attr_computers" min="0" max="30" step="5" value="0"></div>
<div><label>Disable (INT, AGL):</label><input type="number" name="attr_disable" min="0" max="30" step="5" value="0"></div>
<div><label>Drive (INT, AGL):</label><input type="number" name="attr_drive" min="0" max="30" step="5" value="0"></div>
<div><label>*Engineer (INT):</label><input type="number" name="attr_engineer" min="0" max="30" step="5" value="0"></div>
<div><label>*Fly (INT, AGL):</label><input type="number" name="attr_fly" min="0" max="30" step="5" value="0"></div>
<div><label>Guns (ACC):</label><input type="number" name="attr_guns" min="0" max="30" step="5" value="0"></div>
<div><label>History (INT):</label><input type="number" name="attr_history" min="0" max="30" step="5" value="0"></div>
<div><label>Intimidate (CHA):</label><input type="number" name="attr_intimidate" min="0" max="30" step="5" value="0"></div>
<div><label>Investigate (INT, PER):</label><input type="number" name="attr_investigate" min="0" max="30" step="5" value="0"></div>
<div><label>Melee Weapons (STR, AGL):</label><input type="number" name="attr_melee" min="0" max="30" step="5" value="0"></div>
<div><label>*Medicine (INT, AGL):</label><input type="number" name="attr_medicine" min="0" max="30" step="5" value="0"></div>
<div><label>Navigation (PER):</label><input type="number" name="attr_navigation" min="0" max="30" step="5" value="0"></div>
<div><label>Persuade (CHA):</label><input type="number" name="attr_persuade" min="0" max="30" step="5" value="0"></div>
<div><label>Repair (INT):</label><input type="number" name="attr_repair" min="0" max="30" step="5" value="0"></div>
<div><label>*Science (INT):</label><input type="number" name="attr_science" min="0" max="30" step="5" value="0"></div>
<div><label>*Spellcraft (INT, PER):</label><input type="number" name="attr_spellcraft" min="0" max="30" step="5" value="0"></div>
<div><label>Stealth (AGL, PER):</label><input type="number" name="attr_stealth" min="0" max="30" step="5" value="0"></div>
<div><label>Survival (INT, END):</label><input type="number" name="attr_survival" min="0" max="30" step="5" value="0"></div>
<div><label>Tactics (INT):</label><input type="number" name="attr_tactics" min="0" max="30" step="5" value="0"></div>
<div><label>Unarmed (STR, AGL):</label><input type="number" name="attr_unarmed" min="0" max="30" step="5" value="0"></div>
<div><label>Willpower (INT, PER):</label><input type="number" name="attr_willpower" min="0" max="30" step="5" value="0">
</div>
</section> <!-- end skills -->
<!-- Combat Stats Section -->
<section class="combat-stats">
<h2>Combat Stats</h2>
<div class="stats-grid">
<label>Toughness:<input type="number" name="attr_toughness"></label>
<label>Total Wounds:<input type="number" name="attr_total_wounds" readonly></label>
<label>Current Wounds: <input type="number" name="attr_current_wounds"></label>
<input type="hidden" name="attr_current_wounds_max">
<label>Bonus Wounds:<input type="number" name="attr_bonus_wounds" value="0"></label>
<label>Armor Total:<input type="number" name="attr_armor_ar_total" readonly></label>
<label>Bonus Armor:<input type="number" name="attr_armor_bonus" value="0"></label>
<label>Speed:<input type="number" name="attr_speed"></label>
<label>Max Action Points:<input type="number" name="attr_actionpoints" value="6"></label>
<label>Current Action Points:<input type="number" name="attr_actionpoints_current"></label>
<div class="fatigue">
<label>Fatigue
<input type="number" name="attr_fatigue_value" min="0" max="50" value="0"></label>
<span name="attr_fatigue_status"></span>
</div>
<div class="wound-tracker">
<img src="https://images.squarespace-cdn.com/content/67dafda29b94da2a21600bce/ca339e87-bc65-49a0-9e29-e62bd7eac411/woundsSilouette.png?content-type=image%2Fpng" alt="Body Wound Tracker" class="wound-silhouette">
<!-- Head -->
<div class="wound-zone zone-head">
<div class="wound-boxes">
<input type="checkbox" name="attr_head_wound1">
<input type="checkbox" name="attr_head_wound2">
<input type="checkbox" name="attr_head_wound3">
<input type="checkbox" name="attr_head_wound4">
</div>
<span class="wound-status" name="attr_head_status">
</div>
<!-- Chest -->
<div class="wound-zone zone-chest">
<div class="wound-boxes">
<input type="checkbox" name="attr_chest_wound1">
<input type="checkbox" name="attr_chest_wound2">
<input type="checkbox" name="attr_chest_wound3">
<input type="checkbox" name="attr_chest_wound4">
</div>
<span class="wound-status" name="attr_chest_status">
</div>
<!-- Left Arm -->
<div class="wound-zone zone-larm">
<div class="wound-boxes">
<input type="checkbox" name="attr_larm_wound1">
<input type="checkbox" name="attr_larm_wound2">
<input type="checkbox" name="attr_larm_wound3">
<input type="checkbox" name="attr_larm_wound4">
</div>
<span class="wound-status" name="attr_larm_status">
</div>
<!-- Right Arm -->
<div class="wound-zone zone-rarm">
<div class="wound-boxes">
<input type="checkbox" name="attr_rarm_wound1">
<input type="checkbox" name="attr_rarm_wound2">
<input type="checkbox" name="attr_rarm_wound3">
<input type="checkbox" name="attr_rarm_wound4">
</div>
<span class="wound-status" name="attr_rarm_status">
</div>
<!-- Left Leg -->
<div class="wound-zone zone-lleg">
<div class="wound-boxes">
<input type="checkbox" name="attr_lleg_wound1">
<input type="checkbox" name="attr_lleg_wound2">
<input type="checkbox" name="attr_lleg_wound3">
<input type="checkbox" name="attr_lleg_wound4">
</div>
<span class="wound-status" name="attr_lleg_status">
</div>
<!-- Right Leg -->
<div class="wound-zone zone-rleg">
<div class="wound-boxes">
<input type="checkbox" name="attr_rleg_wound1">
<input type="checkbox" name="attr_rleg_wound2">
<input type="checkbox" name="attr_rleg_wound3">
<input type="checkbox" name="attr_rleg_wound4">
</div>
<span class="wound-status" name="attr_rleg_status">
</div>
</div> <!-- end wound tracker -->
</div> <!-- end stats grid -->
<div class="rest-actions">
<button type="action" name="act_resetap">Reset AP</button>
</div>
<div>
<h3>Weapons</h3>
<fieldset class="repeating_weapons">
<div class ="weapons-grid">
<label>Name:<input type="text" name="attr_wep_name"></label>
<label>Damage:<input type="number" name="attr_wep_dmg"></label>
<label>PEN:<input type="number" name="attr_wep_pen"></label>
<label>Burst/Combo:<input type="number" name="attr_wep_burst"></label>
<label>Auto:<input type="number" name="attr_wep_auto"></label>
<label>Heft/Recoil:<input type="number" name="attr_wep_recoil"></label>
<label>Magazine:<input type="number" name="attr_wep_mag"></label>
<label>Reload:<input type="number" name="attr_wep_reload"></label>
<label>Range:<input type="number" name="attr_wep_range"></label>
<label>Qualities:<input type="text" name="attr_wep_qualities"></label>
<label>Durability:<input type="number" name="attr_wep_durability" min="0" max="100"></label>
<label>Condition:<input type="number" name="attr_wep_condition" min="0" max="10"></label>
</div>
</fieldset> <!-- end weapons repeating -->
</div>
</section> <!-- end combat section -->
</div> <!-- end core sheet -->
<div class="sheet-survival">
<!-- Survival Stats -->
<section>
<h2>Survival Stats</h2>
<div class="survival-grid">
<label>Food:</label>
<div class="checkbox-group">
<label><input type="checkbox" name="attr_food1"> Healthy</label>
<label><input type="checkbox" name="attr_food2">
<label><input type="checkbox" name="attr_food3">
<label><input type="checkbox" name="attr_food4"> Starving</label>
</div>
<label>Water:</label>
<div class="checkbox-group">
<label><input type="checkbox" name="attr_water1"> Hydrated</label>
<label><input type="checkbox" name="attr_water2">
<label><input type="checkbox" name="attr_water3">
<label><input type="checkbox" name="attr_water4"> Dying</label>
</div>
<div class="radiation">
<label>Radiation (0300):</label>
<input type="number" name="attr_radiation" min="0" max="300" step="1">
</div>
</div> <!-- end survival grid -->
</section>
</div><!-- end survival sheet -->
<div class="sheet-inventory">
<!-- Carry Slots Section -->
<section class="carry-slots">
<h2>Carrying Capacity</h2>
<div class="carry-info">
<label>Carry Slots (6+STR):
<input type="number" name="attr_carry_slots" readonly></label>
</div>
<div class="carry-info">
<label>Carry Slots Current:
<input type="number" name="attr_carry_current" readonly></label>
</div>
<div class="carry-info">
<label>Carry Overflow:
<input type="number" name="attr_carry_overflow" readonly></label>
</div>
<div class="encumbrance">
<label>Encumbrance
<input type="number" name="attr_encumbrance" min="0" max="20"></label>
<span name="attr_encumbrance_status"></span>
</div>
</section> <!-- end carry capacity section -->
<!-- Items & Equipment -->
<section class="inventory">
<h2>Items & Equipment</h2>
<div class="items_equipment">
<label>Items and Carry Slots</label>
<fieldset class="repeating_items">
<div>
<input type="text" name="attr_item_name" placeholder="Item Name">
<input type="number" name="attr_item_slots" placeholder="Slots">
</div>
</fieldset>
</div> <!-- end items list -->
<!-- Armor Section -->
<div class="armor">
<h3>Armor</h3>
<fieldset class="repeating_armor">
<div class ="armor-grid">
<label>Name:<input type="text" name="attr_armor_name"></label>
<label>Encumbrance:<input type="number" name="attr_armor_enc"></label>
<label>Armor Rating:<input type="number" name="attr_armor_ar"></label>
<label>Qualities:<input type="text" name="attr_armor_qualities"></label>
<label>Durability:<input type="number" name="attr_armor_durability" min="0" max="100"></label>
<label>Condition:<input type="number" name="attr_armor_condition" min="0" max="10"></label>
</div>
</fieldset>
</div> <!-- end armor -->
<!-- Currency Section -->
<div>
<h3>Currency</h3>
<fieldset class="repeating_currency">
<div>
<label>Type:</label>
<select name="attr_currency_type">
<option value="Credits">Credits</option>
<option value="Bits">Bits</option>
<option value="Silver">Silver</option>
<option value="Gold">Gold</option>
</select>
<input type="number" name="attr_currency_amount" placeholder="0" min="0">
</div>
</fieldset>
</div> <!-- end currency -->
</section> <!-- end inventory section -->
</div> <!-- end inventory sheet -->
<div class="sheet-leveling">
<!-- Experience and Leveling -->
<section class="experience-leveling">
<h2>Experience and Leveling</h2>
<div>
<!-- Experience Section -->
<div class="experience">
<h3>Experience Tracker</h3>
<div class="xp-tracker">
<label>Experience Points:</label>
<input type="number" name="attr_xp_points" value="0" min="0" step="25">
<label>Total Experience Spent:</label>
<input type="number" name="attr_xp_spent" value="0" min="0" step="25">
</div> <!-- end exp tracker -->
</div> <!-- end exp div -->
<h3>Traits (Limit 3)</h3>
<fieldset class="repeating_traits">
<div>
<label>Trait</label>
<input type="text" name="attr_trait" placeholder="Trait">
<input type="text" name="attr_trait_desc" placeholder="Description">
</div>
</fieldset>
</div> <!-- end traits div -->
<div>
<h3>Perks</h3>
<fieldset class="repeating_perks">
<div>
<label>Perk</label>
<input type="text" name="attr_perk" placeholder="New Perk">
<input type="text" name="attr_perk_desc" placeholder="Description">
</div>
</fieldset>
</div> <!-- end perks div -->
<div>
<h3>Specializations (Limit 2)</h3>
<fieldset class="repeating_specializations">
<div>
<label>Specialization</label>
<input type="text" name="attr_specialization">
</div>
</fieldset>
</div> <!-- end specializations div -->
<div>
<h3>Skill and Ability Boosts</h3>
<fieldset class="repeating_boosts">
<div>
<label>Boost</label>
<input type="text" name="attr_boost">
</div>
</fieldset>
</div> <!-- end boosts -->
</section> <!-- end exp and lvl section -->
</div> <!-- end leveling tab -->
<div class="sheet-magic">
<!-- Magic -->
<h2>Magic</h2>
<section>
<label>Casting Ability:
<select name="attr_casting_ability" id="attr_casting-ability">
<option value="">-- Select --</option>
<option value="int">Intelligence</option>
<option value="cha">Charisma</option>
<option value="per">Perception</option>
</select>
</label>
<div class="stats-grid">
<label>Max MP: <input type="number" name="attr_max_mp" value="0"></label>
<label>Current MP: <input type="number" name="attr_current_mp" id="attr_current-mp" value="0" min="0"></label>
<label>Recovery Rate: <input type="number" name="attr_recovery_rate" placeholder="Casting Modifier"></label>
<label>Spell Range: <input type="number" name="attr_spell_range" placeholder="2x Ability Score"></label>
<label>Spells Known: <input type="number" name="attr_spells_known" placeholder="Modifier+3+1 per 10 Spellcraft"></label>
<label>Efficacy: <input type="number" name="attr_efficacy" placeholder="Modifier OR 1 per 5 Spellcraft"></label>
<label>Spell Attack: <input type="number" name="attr_spellattack" placeholder="Spellcraft+ACC" readonly></label>
</div> <!-- end magic stats grid -->
<label>Spells:</label>
<div class="spells-inputs">
<fieldset class="repeating_spells">
<div>
<input type="number" name="attr_spell_cost" placeholder="MP Cost">
<input type="text" name="attr_spell" placeholder="New Spell">
<input type="text" name="attr_spell_desc" placeholder="Description">
</div>
</fieldset>
</section> <!-- end magic section -->
</div> <!-- end magic sheet -->
<!-- ADDED FOR ROLL20 COMPAT -->
<input type="hidden" name="attr_winded">
<input type="hidden" name="attr_tired">
<input type="hidden" name="attr_exhausted">
<input type="hidden" name="attr_unconscious">
<input type="hidden" name="attr_encumbered">
<input type="hidden" name="attr_overencumbered">
<input type="hidden" name="attr_encstatus_current">
<input type="hidden" name="attr_speed_base">
<input type="hidden" name="attr_carry_overflow">
<input type="hidden" name="attr_armor_enc_total">
<input type="hidden" name="attr_currency_total">
<!-- END ADDED FOR ROLL20 COMPAT -->
<script type="text/worker">
const buttonlist = ["core", "inventory", "magic", "leveling","survival"];
buttonlist.forEach(button => {
on(`clicked:${button}`, function() {
setAttrs({
sheetTab: button
});
});
});
/*Stat Worker*/
on("change:str change:cha change:int change:agl change:per change:end change:acc change:lck change:encumbrance sheet:opened",function() {
getAttrs(["str", "agl", "int", "cha", "acc", "end", "per", "lck"], function(values) {
let endMod = Math.floor(parseInt(values.end)/10);
let aglMod = Math.floor(parseInt(values.agl)/10);
let strMod = Math.floor(parseInt(values.str)/10);
setAttrs({
str_mod: Math.floor(parseInt(values.str)/10),
per_mod: Math.floor(parseInt(values.per)/10),
end_mod: endMod,
cha_mod: Math.floor(parseInt(values.cha)/10),
int_mod: Math.floor(parseInt(values.int)/10),
agl_mod: aglMod,
lck_mod: Math.floor(parseInt(values.lck)/10),
acc_mod: Math.floor(parseInt(values.acc)/10),
toughness: endMod,
luck_points_max: 1+Math.floor(parseInt(values.lck)/10),
winded: endMod,
tired: 2*endMod,
exhausted: 3*endMod,
unconscious: 4*endMod,
speed: 1+aglMod,
carry_slots: 6+strMod,
encumbered: 1+strMod,
overencumbered: 2*(1+strMod)
});
});
});
/*Fatigue Workers*/
on("change:fatigue_value change:end sheet:opened", function() {
getAttrs(["fatigue_value", "fatigue_status", "winded", "tired", "exhausted","unconscious"], function(values) {
let fatigue = parseInt(values.fatigue_value);
let fatigueStatus = "";
if (fatigue >= parseInt(values.unconscious))
fatigueStatus = "Unconscious";
else if (fatigue >= parseInt(values.exhausted))
fatigueStatus = "Exhausted: -3 to all STR, AGL, END, and INT DoS. -2 AP per round.";
else if (fatigue >= parseInt(values.tired))
fatigueStatus = "Tired: -1 to all Athletics, STR, AGL DoS. -2 Speed to Run and Sprint.";
else if (fatigue < parseInt(values.tired))
fatigueStatus = " ";
setAttrs({
fatigue_status: fatigueStatus
});
});
});
/*Encumbrance Workers*/
on("change:encumbrance change:str sheet:opened", function() {
getAttrs(["encumbrance", "encumbered", "overencumbered"], function(values) {
let encValue = parseInt(values.encumbrance);
let encStatus = "";
let encCurrent = "";
if (encValue >= parseInt(values.overencumbered))
encStatus = "Over-Encumbered: -2 to AGL, 1/2 Speed, +4 spell cost, gain triple Fatigue.";
else if (encValue >= parseInt(values.encumbered))
encStatus = "Encumbered: -1 Speed, cannot Run, +2 spell cost, gain double Fatigue";
else if (encValue < parseInt(values.encumbered))
encStatus = " ";
setAttrs({
encumbrance_status: encStatus
});
});
});
/*Wounds Calculator*/
function raceWounds(selection){
let raceWounds = 0;
let raceBenefit = "";
if (selection === "Human") {
raceWounds = 5;
raceBenefit = "+1 Luck Point";
}
else if (selection === "Dwarf") {
raceWounds = 5;
raceBenefit = "+1 Encumbrance limit; +1 DoS on Trip, Grapple, Disarm, Block; Subterrain Vision";
}
else if (selection === "Lizardmen") {
raceWounds = 5;
raceBenefit = "Swimmer, Keen Scent, Jungle Immunity, Cold Blooded";
}
else if (selection === "Elemental") {
raceWounds = 5;
raceBenefit = "Become Incorporeal, Death... Again, Strange Anatomy";
}
else if (selection === "Elf") {
raceWounds = 4;
raceBenefit = "+1 DoS on Survival (INT), +1 Movement Speed";
}
else if (selection === "Aetherial") {
raceWounds = 4;
raceBenefit = "Magical Training is free";
}
else if (selection === "Sylvan") {
raceWounds = 4;
raceBenefit = "Carnivore, Regeneration, +1 PEN on Unarmed";
}
else if (selection === "Halfling") {
raceWounds = 4;
raceBenefit = "+2 DoS on Dodge";
}
else if (selection === "Gnome") {
raceWounds = 4;
raceBenefit = "+2 DoS on crafting, +5 Magic Points";
}
else if (selection === "Orc") {
raceWounds = 6;
raceBenefit = "+1 DoS on Carouse, Penny Pincher";
}
else if (selection === "Granitetouched") {
raceWounds = 6;
raceBenefit = "+1 AR, Subterrane Vision";
}
return [raceWounds, raceBenefit]
};
on("change:race change:bonus_wounds change:willpower sheet:opened", function() {
getAttrs(["race", "bonus_wounds", "willpower"], function(values) {
let willpowerBonus = Math.floor(parseInt(values.willpower)/10);
const temp = raceWounds(values.race);
const raceWds = temp[0];
const raceBen = temp[1];
let bonusWds = parseInt(values.bonus_wounds);
setAttrs({
total_wounds: willpowerBonus+bonusWds+raceWds,
racial_benefits: raceBen
});
});
});
/*Armor Worker*/
on("change:repeating_armor:armor_ar change:repeating_armor:armor_enc remove:repeating_armor change:armor_bonus change:carry_overflow sheet:opened", function() {
getSectionIDs("repeating_armor", function(armorIds) {
const fields = ["armor_bonus", "carry_overflow"];
armorIds.forEach(id => {
fields.push(`repeating_armor_${id}_armor_ar`);
fields.push(`repeating_armor_${id}_armor_enc`);
});
getAttrs(fields, function(values) {
let arTotal = 0;
let encTotal = 0;
// === Armor AR & ENC ===
armorIds.forEach(id => {
const arVal = parseInt(values[`repeating_armor_${id}_armor_ar`], 10) || 0;
const encVal = parseInt(values[`repeating_armor_${id}_armor_enc`], 10) || 0;
arTotal += arVal;
encTotal += encVal;
});
// === Armor Bonus ===
const bonus = parseInt(values.armor_bonus, 10) || 0;
arTotal += bonus;
// === Carry Overflow ===
const overflow = parseInt(values.carry_overflow, 10) || 0;
encTotal += overflow;
// === Set results ===
setAttrs({
armor_ar_total: arTotal,
encumbrance: encTotal
});
});
});
});
/*Carry Capacity Worker*/
on("change:repeating_items:item_slots remove:repeating_items change:carry_slots sheet:opened", function() {
getSectionIDs("repeating_items", function(itemIds) {
const fields = ["carry_slots"];
itemIds.forEach(id => fields.push(`repeating_items_${id}_item_slots`));
getAttrs(fields, function(values) {
let current = 0;
// === Sum item slots ===
itemIds.forEach(id => {
const val = parseInt(values[`repeating_items_${id}_item_slots`], 10) || 0;
current += val;
});
const maxSlots = parseInt(values.carry_slots, 10) || 0;
let overflow = 0;
if (current > maxSlots) {
overflow = current - maxSlots;
}
// === Set results ===
setAttrs({
carry_current: current,
carry_overflow: overflow
});
});
});
});
on("change:total_wounds \
change:head_wound1 change:head_wound2 change:head_wound3 change:head_wound4 \
change:chest_wound1 change:chest_wound2 change:chest_wound3 change:chest_wound4 \
change:larm_wound1 change:larm_wound2 change:larm_wound3 change:larm_wound4 \
change:rarm_wound1 change:rarm_wound2 change:rarm_wound3 change:rarm_wound4 \
change:lleg_wound1 change:lleg_wound2 change:lleg_wound3 change:lleg_wound4 \
change:rleg_wound1 change:rleg_wound2 change:rleg_wound3 change:rleg_wound4 \
sheet:opened", function() {
// Explicit wound fields
const woundFields = [
"total_wounds",
"head_wound1","head_wound2","head_wound3","head_wound4",
"chest_wound1","chest_wound2","chest_wound3","chest_wound4",
"larm_wound1","larm_wound2","larm_wound3","larm_wound4",
"rarm_wound1","rarm_wound2","rarm_wound3","rarm_wound4",
"lleg_wound1","lleg_wound2","lleg_wound3","lleg_wound4",
"rleg_wound1","rleg_wound2","rleg_wound3","rleg_wound4"
];
getAttrs(woundFields, function(values) {
const total = parseInt(values.total_wounds, 10) || 0;
// Helper: determine status
const getStatus = (count) => {
switch(count) {
case 1: return "Roughed Up";
case 2: return "Injured";
case 3: return "Crippled";
case 4: return "Fatal";
default: return " ";
}
};
// Count per-zone
let headCount = 0, chestCount = 0, larmCount = 0, rarmCount = 0, llegCount = 0, rlegCount = 0;
if (values.head_wound1 === "on") headCount++;
if (values.head_wound2 === "on") headCount++;
if (values.head_wound3 === "on") headCount++;
if (values.head_wound4 === "on") headCount++;
if (values.chest_wound1 === "on") chestCount++;
if (values.chest_wound2 === "on") chestCount++;
if (values.chest_wound3 === "on") chestCount++;
if (values.chest_wound4 === "on") chestCount++;
if (values.larm_wound1 === "on") larmCount++;
if (values.larm_wound2 === "on") larmCount++;
if (values.larm_wound3 === "on") larmCount++;
if (values.larm_wound4 === "on") larmCount++;
if (values.rarm_wound1 === "on") rarmCount++;
if (values.rarm_wound2 === "on") rarmCount++;
if (values.rarm_wound3 === "on") rarmCount++;
if (values.rarm_wound4 === "on") rarmCount++;
if (values.lleg_wound1 === "on") llegCount++;
if (values.lleg_wound2 === "on") llegCount++;
if (values.lleg_wound3 === "on") llegCount++;
if (values.lleg_wound4 === "on") llegCount++;
if (values.rleg_wound1 === "on") rlegCount++;
if (values.rleg_wound2 === "on") rlegCount++;
if (values.rleg_wound3 === "on") rlegCount++;
if (values.rleg_wound4 === "on") rlegCount++;
// Total wounds lost
const woundsLost = headCount + chestCount + larmCount + rarmCount + llegCount + rlegCount;
const current = Math.max(0, total - woundsLost);
// Set individually
setAttrs({
current_wounds: current,
head_status: getStatus(headCount),
chest_status: getStatus(chestCount),
larm_status: getStatus(larmCount),
rarm_status: getStatus(rarmCount),
lleg_status: getStatus(llegCount),
rleg_status: getStatus(rlegCount)
});
});
});
// --- AP Reset button pressed ---
on("clicked:resetap", function() {
getAttrs(["actionpoints","actionpoints_current"], function(values) {
let maxAP = parseInt(values.actionpoints, 10) || 0;
setAttrs({
actionpoints_current: maxAP
});
});
});
// --- Break button pressed: ask in chat ---
on("clicked:break", function() {
startRoll("&{template:default} {{name=Take a Break?}} {{Click=[Yes](~break_confirm) / [No](~cancel)}}");
});
// --- Sleep button pressed: ask in chat ---
on("clicked:sleep", function() {
startRoll("&{template:default} {{name=Go to Sleep?}} {{Click=[Yes](~sleep_confirm) / [No](~cancel)}}");
});
// --- Break confirmed ---
on("clicked:break_confirm", function() {
getAttrs(["fatigue_value","end_mod","current_mp","max_mp","recovery_rate","character_name"], function(values) {
let fatigue = parseInt(values.fatigue_value, 10) || 0;
let endMod = parseInt(values.end_mod, 10) || 0;
let currentMP = parseInt(values.current_mp, 10) || 0;
let maxMP = parseInt(values.max_mp, 10) || 0;
let recovery = parseInt(values.recovery_rate, 10) || 0;
let charName = values.character_name || "This character";
const newFatigue = Math.max(0, fatigue - endMod);
const newMP = Math.min(maxMP, currentMP + recovery);
setAttrs({
fatigue_value: newFatigue,
current_mp: newMP
}, () => {
startRoll(`&{template:default} {{name=${charName}}} {{action=Took a Break}} {{Fatigue=${newFatigue}}} {{MP=${newMP}}}`);
});
});
});
// --- Sleep confirmed ---
on("clicked:sleep_confirm", function() {
getAttrs(["recovery_rate","current_mp","max_mp","character_name"], function(values) {
let recovery = parseInt(values.recovery_rate, 10) || 0;
let currentMP = parseInt(values.current_mp, 10) || 0;
let maxMP = parseInt(values.max_mp, 10) || 0;
let charName = values.character_name || "This character";
const newFatigue = 0;
const newMP = Math.min(maxMP, currentMP + (2 * recovery));
setAttrs({
fatigue_value: newFatigue,
current_mp: newMP
}, () => {
startRoll(`&{template:default} {{name=${charName}}} {{action=Went to Sleep}} {{Fatigue=${newFatigue}}} {{MP=${newMP}}}`);
});
});
});
// --- Cancel does nothing (but placeholder in chat) ---
on("clicked:cancel", function() {
startRoll("&{template:default} {{name=Action Cancelled}}");
});
on("change:casting_ability change:int change:int_mod change:cha change:cha_mod change:per change:per_mod change:spellcraft sheet:opened", function() {
getAttrs(["casting_ability","int","int_mod","cha","cha_mod","per","per_mod","spellcraft","acc"], function(values) {
let ability = values.casting_ability || "intelligence"; // default
let abilityVal = 0;
let abilityMod = 0;
// Pick correct ability & mod
switch(ability) {
case "cha":
abilityVal = parseInt(values.cha, 10) || 0;
abilityMod = parseInt(values.cha_mod, 10) || 0;
break;
case "per":
abilityVal = parseInt(values.per, 10) || 0;
abilityMod = parseInt(values.per_mod, 10) || 0;
break;
case "int":
default:
abilityVal = parseInt(values.int, 10) || 0;
abilityMod = parseInt(values.int_mod, 10) || 0;
break;
}
const spellcraft = parseInt(values.spellcraft, 10) || 0;
const spellcraftAlt = Math.floor(spellcraft / 5);
const recovery_rate = abilityMod;
const spell_range = 2*abilityVal;
const spells_known = 3 + abilityMod + Math.floor(spellcraft/10);
const efficacy = Math.max(abilityMod, spellcraftAlt);
const spellAttack = parseInt(values.spellcraft)+parseInt(values.acc);
setAttrs({
recovery_rate: recovery_rate,
spell_range: spell_range,
spells_known: spells_known,
efficacy: efficacy,
spellattack: spellAttack
});
});
});
on("clicked:roll_selected_skill", function() {
getAttrs(["selected_skill", "selected_skill_ability", "character_name"], function(sel) {
const skillKey = sel.selected_skill || "";
const abilityKey = sel.selected_skill_ability || "str";
const charName = sel.character_name || "Character";
getAttrs([skillKey, abilityKey, "lck_mod"], function(values) {
const skillVal = parseInt(values[skillKey], 10) || 0;
const abilityVal = parseInt(values[abilityKey], 10) || 0;
const check = Math.min(skillVal + abilityVal, 95);
const luckMod = parseInt(values.lck_mod);
startRoll(
"&{template:check} " +
"{{name=" + charName + ": " + skillKey.toUpperCase() + " + " + abilityKey.toUpperCase() + "}} " +
"{{check=" + check + "}} " +
"{{roll=[[1d100]]}} " + "{{degrees=[[0]]}} {{result=[[0]]}}", (results) => {
const roll = results.results.roll.result;
const success = roll <= check;
const tens = Math.floor(roll / 10);
const degSuccess = Math.max(1, tens);
const degFailure = 10 - tens;
const isDouble = (roll % 11 === 0) || roll === 100;
let resultText, degreesText;
let critBonus = 0;
if (success) {
resultText = isDouble ? "Critical Success!" : "Success";
degreesText = degSuccess;
critbonus = isDouble ? luckMod : 0;
} else {
resultText = isDouble ? "Critical Failure!" : "Failure";
degreesText = degFailure;
critbonus = isDouble ? 3 : 0;
}
finishRoll(results.rollId,
{
result: resultText,
degrees: degreesText+critbonus
});
});
});
});
});
</script>