Merge pull request #14885 from GorgonsGrimoireLLC/Ghosts-of-Vietnam-The-RPG

Ghosts of Vietnam Character Sheet
This commit is contained in:
Lucas Hall
2026-03-24 14:19:03 -04:00
committed by GitHub
4 changed files with 1080 additions and 0 deletions
@@ -0,0 +1,340 @@
.sheet-gvn {
font-family: "Times New Roman", Georgia, serif;
font-size: 12px;
max-width: 1200px;
min-width: 900px;
margin: 0 auto;
background: #f7f7f7;
color: #000;
}
/* GLOBAL */
.sheet-gvn,
.sheet-gvn * {
box-sizing: border-box;
color: #000 !important;
}
/* INPUTS */
.sheet-gvn input,
.sheet-gvn textarea,
.sheet-gvn select {
font-family: inherit;
font-size: 12px;
line-height: 1.2;
}
.sheet-gvn input:not([type="checkbox"]),
.sheet-gvn textarea,
.sheet-gvn select {
width: 100%;
border: 1px solid #555;
background: #fff;
padding: 4px 6px; /* Slightly increased padding for comfort */
text-align: center;
}
.sheet-gvn textarea {
resize: vertical;
min-height: 60px;
}
/* LABELS */
.sheet-gvn label {
display: block;
font-weight: bold;
text-align: center;
margin-bottom: 2px;
font-size: 11px;
}
/* TITLES */
.sheet-title {
text-align: center;
font-size: 26px;
font-weight: bold;
margin: 6px 0 10px;
}
.sheet-subtitle {
text-align: center;
font-size: 18px;
font-weight: bold;
margin-bottom: 6px;
}
/* TABS */
.sheet-tabbar {
display: flex;
gap: 4px;
margin-bottom: 10px;
}
.sheet-tab-button {
flex: 1;
border: 2px solid #444;
background: #d8d8d8;
font-weight: bold;
padding: 5px;
cursor: pointer;
}
.sheet-tab { display: none; }
.sheet-gvn input[name="attr_sheetTab"][value="core"] ~ .sheet-core { display: block; }
.sheet-gvn input[name="attr_sheetTab"][value="equipment"] ~ .sheet-equipment { display: block; }
.sheet-gvn input[name="attr_sheetTab"][value="proficiencies"] ~ .sheet-proficiencies { display: block; }
.sheet-gvn input[name="attr_sheetTab"][value="command"] ~ .sheet-command { display: block; }
.sheet-gvn input[name="attr_sheetTab"][value="notes"] ~ .sheet-notes { display: block; }
/* SECTIONS */
.sheet-section {
border: 2px solid #444;
background: #ececec;
padding: 6px;
margin-bottom: 10px;
}
/* GRID */
.sheet-grid {
display: grid;
gap: 5px;
align-items: center;
}
.sheet-grid-2 { grid-template-columns: repeat(2, 1fr); }
.sheet-grid-3 { grid-template-columns: repeat(3, 1fr); }
.sheet-grid-4 { grid-template-columns: repeat(4, 1fr); }
.sheet-grid-5 { grid-template-columns: repeat(5, 1fr); }
.sheet-grid-6 { grid-template-columns: repeat(6, 1fr); }
.sheet-grid-7 { grid-template-columns: repeat(7, 1fr); }
.sheet-grid-10 { grid-template-columns: repeat(10, 1fr); }
/* SPECIAL GRIDS */
.sheet-grid-gov-weapons {
grid-template-columns: 2fr 0.6fr 0.6fr 0.7fr 0.7fr 1fr 0.7fr 0.6fr;
}
.sheet-grid-armor {
grid-template-columns: 3fr 1fr;
}
.sheet-grid-equipment-gov {
grid-template-columns: 3fr 0.8fr;
}
.sheet-grid-command-log {
grid-template-columns: 1fr 2fr 0.6fr;
gap: 6px; /* Slightly more space between columns */
align-items: center;
}
.sheet-grid-nwp {
grid-template-columns: 2fr 0.8fr 0.8fr 0.8fr 0.8fr;
}
.sheet-grid-wp {
grid-template-columns: 2fr 0.8fr;
}
/* Command Log specific input tweaks */
.sheet-grid-command-log input {
width: 100%;
text-align: left; /* Better for descriptive text like requests */
padding: 4px 6px;
}
/* LAYOUT */
.sheet-two-col {
display: flex;
gap: 10px;
align-items: flex-start;
}
.sheet-maincol {
flex: 2;
display: flex;
flex-direction: column;
gap: 10px;
}
.sheet-sidecol {
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
}
/* HEADERS */
.sheet-mount-header {
font-weight: bold;
text-align: center;
border-bottom: 2px solid #444; /* Thicker, more visible separator */
padding-bottom: 4px;
background: #e0e0e0; /* Subtle highlight for headers */
}
.sheet-mount-header div {
font-size: 10px;
}
/* HP */
.sheet-hp-box {
border: 2px solid #444;
background: #f4f4f4;
padding: 4px;
}
/* ATTACK */
.sheet-attack-table {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
}
.sheet-attack-header,
.sheet-attack-top,
.sheet-attack-row {
display: grid;
grid-template-columns: 90px 60px 90px;
gap: 8px;
justify-content: center;
}
.sheet-attack-top input,
.sheet-attack-row input {
width: 60px;
margin: 0 auto;
}
/* ABILITIES */
.sheet-ability-block {
display: flex;
flex-direction: column;
gap: 4px;
}
.sheet-ability-header,
.sheet-ability-row {
display: grid;
grid-template-columns: 110px repeat(7, 1fr);
gap: 2px;
}
.sheet-ability-header {
font-weight: bold;
text-align: center;
background: #dcdcdc;
border: 1px solid #444;
font-size: 10px;
}
.sheet-ability-name {
font-weight: bold;
text-align: left;
padding: 3px 4px;
background: #fff;
border: 1px solid #555;
}
/* TEXT */
.sheet-notes-area {
min-height: 450px;
text-align: left;
}
/* REPEATING — DO NOT TOUCH CORE STRUCTURE */
.sheet-gvn fieldset {
border: none;
margin: 0;
padding: 0;
}
/* IMPORTANT: leave these alone */
.sheet-gvn .repcontainer { }
.sheet-gvn .repitem { }
/* ONLY style your content */
.sheet-gvn .repeating_armor .sheet-grid,
.sheet-gvn .repeating_weapons .sheet-grid,
.sheet-gvn .repeating_equipment .sheet-grid,
.sheet-gvn .repeating_nwp .sheet-grid,
.sheet-gvn .repeating_wp .sheet-grid,
.sheet-gvn .repeating_command_log .sheet-grid {
display: grid;
width: 100%;
gap: 5px;
}
/* REMOVE BUTTON (add this if you include a remove button per row) */
.sheet-btn-remove {
margin-left: 4px;
background: #c00;
color: white;
border: none;
border-radius: 3px;
padding: 0 6px;
font-weight: bold;
cursor: pointer;
font-size: 12px;
line-height: 1;
}
/* BUTTONS */
.sheet-gvn .repcontrol {
margin-top: 4px;
}
.sheet-gvn .repcontrol .btn {
border: 1px solid #444;
background: #d8d8d8;
font-size: 10px;
font-weight: bold;
padding: 2px 6px;
}
/* MOBILE */
@media screen and (max-width: 1000px) {
.sheet-two-col {
flex-direction: column;
}
.sheet-grid,
.sheet-grid-10,
.sheet-grid-7,
.sheet-grid-6,
.sheet-grid-5,
.sheet-grid-4,
.sheet-grid-3,
.sheet-grid-2,
.sheet-grid-gov-weapons,
.sheet-grid-armor,
.sheet-grid-equipment-gov,
.sheet-grid-command-log,
.sheet-grid-nwp,
.sheet-grid-wp {
grid-template-columns: 1fr;
}
}
@@ -0,0 +1,732 @@
<div class="sheet-gvn">
<input type="hidden" name="attr_sheetTab" value="core">
<div class="sheet-tabbar">
<button type="action" name="act_core" class="sheet-tab-button">Core</button>
<button type="action" name="act_equipment" class="sheet-tab-button">Equipment</button>
<button type="action" name="act_proficiencies" class="sheet-tab-button">Proficiencies</button>
<button type="action" name="act_command" class="sheet-tab-button">Command Authority/Field Protocols</button>
<button type="action" name="act_notes" class="sheet-tab-button">Notes</button>
</div>
<!-- CORE TAB -->
<div class="sheet-tab sheet-core">
<div class="sheet-title">Ghosts of Vietnam</div>
<!-- HEADER -->
<div class="sheet-section">
<div class="sheet-grid sheet-grid-3">
<div class="sheet-field">
<label>Name</label>
<input type="text" name="attr_character_name">
</div>
<div class="sheet-field">
<label>Branch</label>
<input type="text" name="attr_branch">
</div>
<div class="sheet-field">
<label>Campaign Max Level</label>
<input type="text" name="attr_campaign_max_level">
</div>
</div>
<div class="sheet-grid sheet-grid-2">
<div class="sheet-field sheet-hp-box">
<label>Hit Points</label>
<div class="sheet-grid sheet-grid-2">
<div class="sheet-field">
<label>Current</label>
<input type="text" name="attr_hp_current">
</div>
<div class="sheet-field">
<label>Maximum</label>
<input type="text" name="attr_hp_max">
</div>
</div>
</div>
<div class="sheet-field">
<label>Experience Points</label>
<input type="text" name="attr_experience_points">
</div>
</div>
<div class="sheet-grid sheet-grid-6">
<div class="sheet-field">
<label>Class (MOS)</label>
<input type="text" name="attr_class_mos">
</div>
<div class="sheet-field">
<label>Level</label>
<input type="text" name="attr_level">
</div>
<div class="sheet-field">
<label>Nationality</label>
<input type="text" name="attr_nationality">
</div>
<div class="sheet-field">
<label>Height</label>
<input type="text" name="attr_height">
</div>
<div class="sheet-field">
<label>Weight</label>
<input type="text" name="attr_weight">
</div>
<div class="sheet-field">
<label>Age</label>
<input type="text" name="attr_age">
</div>
</div>
<div class="sheet-grid sheet-grid-2">
<div class="sheet-field">
<label>Alignment</label>
<input type="text" name="attr_alignment">
</div>
<div class="sheet-field">
<label>Religion</label>
<input type="text" name="attr_religion">
</div>
</div>
<div class="sheet-grid sheet-grid-2">
<div class="sheet-field">
<label>DEROS</label>
<input type="text" name="attr_deros">
</div>
<div class="sheet-field">
<label>Rank</label>
<input type="text" name="attr_rank">
</div>
</div>
<div class="sheet-field">
<label>Movement</label>
<input type="text" name="attr_movement">
</div>
<div class="sheet-field">
<label>Physical Description</label>
<textarea name="attr_physical_description"></textarea>
</div>
</div>
<!-- MAIN + RIGHT PANEL -->
<div class="sheet-two-col">
<!-- LEFT -->
<div class="sheet-maincol">
<!-- ABILITY SCORES -->
<div class="sheet-section">
<div class="sheet-subtitle">Ability Scores</div>
<div class="sheet-ability-block">
<!-- STRENGTH -->
<div class="sheet-ability-header">
<div></div>
<div>Score</div>
<div>To Hit Bonus</div>
<div>Damage Bonus</div>
<div>Weight Allow</div>
<div>Max Press</div>
<div>Brute Force Entry</div>
<div>Defeat Obstacles</div>
</div>
<div class="sheet-ability-row">
<div class="sheet-ability-name">Strength</div>
<input type="text" name="attr_strength">
<input type="text" name="attr_str_to_hit_bonus">
<input type="text" name="attr_str_damage_bonus">
<input type="text" name="attr_str_weight_allowance">
<input type="text" name="attr_str_max_press">
<input type="text" name="attr_str_brute_force_entry">
<input type="text" name="attr_str_defeat_obstacles">
</div>
<!-- DEXTERITY -->
<div class="sheet-ability-header">
<div></div>
<div>Score</div>
<div>Reaction Adj.</div>
<div>Ranged Attack</div>
<div>Defense Adj.</div>
<div></div><div></div><div></div>
</div>
<div class="sheet-ability-row">
<div class="sheet-ability-name">Dexterity</div>
<input type="text" name="attr_dexterity">
<input type="text" name="attr_dex_reaction_adjustment">
<input type="text" name="attr_dex_ranged_attack_bonus">
<input type="text" name="attr_dex_defense_adjustment">
<div></div><div></div><div></div>
</div>
<!-- CONSTITUTION -->
<div class="sheet-ability-header">
<div></div>
<div>Score</div>
<div>Hit Point Adj.</div>
<div>System Shock</div>
<div>Resurrection Survival</div>
<div>Poison Save Bonus</div>
<div></div><div></div>
</div>
<div class="sheet-ability-row">
<div class="sheet-ability-name">Constitution</div>
<input type="text" name="attr_constitution">
<input type="text" name="attr_con_hit_point_adjustment">
<input type="text" name="attr_con_system_shock">
<input type="text" name="attr_con_resurrection_survival">
<input type="text" name="attr_con_poison_save_bonus">
<div></div><div></div>
</div>
<!-- INTELLIGENCE -->
<div class="sheet-ability-header">
<div></div>
<div>Score</div>
<div># Languages</div>
<div>Technical Knowledge</div>
<div>Shock Adj.</div>
<div></div><div></div><div></div>
</div>
<div class="sheet-ability-row">
<div class="sheet-ability-name">Intelligence</div>
<input type="text" name="attr_intelligence">
<input type="text" name="attr_int_languages">
<input type="text" name="attr_int_technical_knowledge">
<input type="text" name="attr_int_shock_adjustment">
<div></div><div></div><div></div>
</div>
<!-- WISDOM -->
<div class="sheet-ability-header">
<div></div>
<div>Score</div>
<div>Resolve Adj.</div>
<div></div><div></div><div></div><div></div><div></div>
</div>
<div class="sheet-ability-row">
<div class="sheet-ability-name">Wisdom</div>
<input type="text" name="attr_wisdom">
<input type="text" name="attr_wis_resolve_adjustment">
<div></div><div></div><div></div><div></div><div></div>
</div>
<!-- CHARISMA -->
<div class="sheet-ability-header">
<div></div>
<div>Score</div>
<div>Max Henchmen</div>
<div>Loyalty Adj.</div>
<div>Reaction Adj.</div>
<div></div><div></div><div></div>
</div>
<div class="sheet-ability-row">
<div class="sheet-ability-name">Charisma</div>
<input type="text" name="attr_charisma">
<input type="text" name="attr_cha_max_henchmen">
<input type="text" name="attr_cha_loyalty_adjustment">
<input type="text" name="attr_cha_reaction_adjustment">
<div></div><div></div><div></div>
</div>
<!-- APPEARANCE -->
<div class="sheet-ability-header">
<div></div>
<div>Score</div>
<div>Reaction Adj.</div>
<div></div><div></div><div></div><div></div><div></div>
</div>
<div class="sheet-ability-row">
<div class="sheet-ability-name">Appearance</div>
<input type="text" name="attr_appearance">
<input type="text" name="attr_app_reaction_adjustment">
<div></div><div></div><div></div><div></div><div></div>
</div>
</div>
</div>
<!-- ARMOR -->
<div class="sheet-section">
<div class="sheet-subtitle">Armor</div>
<div class="sheet-grid sheet-grid-armor sheet-mount-header">
<div>Armor</div>
<div>AC</div>
</div>
<fieldset class="repeating_armor">
<div class="sheet-grid sheet-grid-armor">
<input type="text" name="attr_armor_name">
<input type="text" name="attr_armor_ac">
</div>
</fieldset>
</div>
<!-- WEAPONS -->
<div class="sheet-section">
<div class="sheet-subtitle">Weapons</div>
<div class="sheet-grid sheet-grid-gov-weapons sheet-mount-header">
<div>Weapon</div>
<div># Attacks</div>
<div>ROF</div>
<div>Att Mod</div>
<div>Dmg Mod</div>
<div>Range</div>
<div>Damage</div>
<div>Mag</div>
</div>
<fieldset class="repeating_weapons">
<div class="sheet-grid sheet-grid-gov-weapons">
<input type="text" name="attr_weapon">
<input type="text" name="attr_attacks_num">
<input type="text" name="attr_rof">
<input type="text" name="attr_attack_adjustment">
<input type="text" name="attr_damage_adjustment">
<input type="text" name="attr_ranges">
<input type="text" name="attr_damage">
<input type="text" name="attr_magazine">
</div>
</fieldset>
</div>
<!-- ROGUE -->
<div class="sheet-section">
<div class="sheet-subtitle">Rogue Abilities</div>
<div class="sheet-grid sheet-grid-10 sheet-mount-header">
<div>Pick Pockets</div>
<div>Open Locks</div>
<div>Find/Remove Traps</div>
<div>Move Silently</div>
<div>Hide in Shadows</div>
<div>Detect Noise</div>
<div>Climb Walls</div>
<div>Read Languages</div>
<div>Dual Wield</div>
<div>Kill Shot</div>
</div>
<div class="sheet-grid sheet-grid-10">
<input type="text" name="attr_rogue_pick_pockets">
<input type="text" name="attr_rogue_open_locks">
<input type="text" name="attr_rogue_find_remove_traps">
<input type="text" name="attr_rogue_move_silently">
<input type="text" name="attr_rogue_hide_in_shadows">
<input type="text" name="attr_rogue_detect_noise">
<input type="text" name="attr_rogue_climb_walls">
<input type="text" name="attr_rogue_read_languages">
<input type="checkbox" name="attr_dual_wield">
<select name="attr_kill_shot">
<option value=""></option>
<option value="x2">x2</option>
<option value="x3">x3</option>
<option value="x4">x4</option>
<option value="x5">x5</option>
</select>
</div>
</div>
<!-- SAVING THROWS -->
<div class="sheet-section">
<div class="sheet-subtitle">Saving Throws</div>
<div class="sheet-grid sheet-grid-7 sheet-mount-header">
<div>Paralyzation</div>
<div>Poison</div>
<div>Death</div>
<div>Shock</div>
<div>Transformation</div>
<div>Evasion</div>
<div>Resolve</div>
</div>
<div class="sheet-grid sheet-grid-7">
<input type="text" name="attr_save_paralyzation">
<input type="text" name="attr_save_poison">
<input type="text" name="attr_save_death">
<input type="text" name="attr_save_shock">
<input type="text" name="attr_save_transformation">
<input type="text" name="attr_save_evasion">
<input type="text" name="attr_save_resolve">
</div>
</div>
</div>
<!-- RIGHT SIDE -->
<div class="sheet-sidecol">
<div class="sheet-attack-table">
<!-- HEADERS -->
<div class="sheet-attack-header">
<div>Melee</div>
<div>THAC0</div>
<div>Ranged</div>
</div>
<!-- INPUT ROW -->
<div class="sheet-attack-top">
<input type="text" name="attr_attack_table_melee">
<input type="text" name="attr_attack_table_thaco">
<input type="text" name="attr_attack_table_ranged">
</div>
<!-- AC ROWS -->
<div class="sheet-attack-rows">
<div class="sheet-attack-row">
<div><label>AC 1</label><input type="text" name="attr_to_hit_ac_1"></div>
<div class="sheet-attack-spacer"></div>
<div><label>AC -1</label><input type="text" name="attr_to_hit_ac_neg1"></div>
</div>
<div class="sheet-attack-row">
<div><label>AC 2</label><input type="text" name="attr_to_hit_ac_2"></div>
<div class="sheet-attack-spacer"></div>
<div><label>AC -2</label><input type="text" name="attr_to_hit_ac_neg2"></div>
</div>
<div class="sheet-attack-row">
<div><label>AC 3</label><input type="text" name="attr_to_hit_ac_3"></div>
<div class="sheet-attack-spacer"></div>
<div><label>AC -3</label><input type="text" name="attr_to_hit_ac_neg3"></div>
</div>
<div class="sheet-attack-row">
<div><label>AC 4</label><input type="text" name="attr_to_hit_ac_4"></div>
<div class="sheet-attack-spacer"></div>
<div><label>AC -4</label><input type="text" name="attr_to_hit_ac_neg4"></div>
</div>
<div class="sheet-attack-row">
<div><label>AC 5</label><input type="text" name="attr_to_hit_ac_5"></div>
<div class="sheet-attack-spacer"></div>
<div><label>AC -5</label><input type="text" name="attr_to_hit_ac_neg5"></div>
</div>
<div class="sheet-attack-row">
<div><label>AC 6</label><input type="text" name="attr_to_hit_ac_6"></div>
<div class="sheet-attack-spacer"></div>
<div><label>AC -6</label><input type="text" name="attr_to_hit_ac_neg6"></div>
</div>
<div class="sheet-attack-row">
<div><label>AC 7</label><input type="text" name="attr_to_hit_ac_7"></div>
<div class="sheet-attack-spacer"></div>
<div><label>AC -7</label><input type="text" name="attr_to_hit_ac_neg7"></div>
</div>
<div class="sheet-attack-row">
<div><label>AC 8</label><input type="text" name="attr_to_hit_ac_8"></div>
<div class="sheet-attack-spacer"></div>
<div><label>AC -8</label><input type="text" name="attr_to_hit_ac_neg8"></div>
</div>
<div class="sheet-attack-row">
<div><label>AC 9</label><input type="text" name="attr_to_hit_ac_9"></div>
<div class="sheet-attack-spacer"></div>
<div><label>AC -9</label><input type="text" name="attr_to_hit_ac_neg9"></div>
</div>
<div class="sheet-attack-row">
<div><label>AC 10</label><input type="text" name="attr_to_hit_ac_10"></div>
<div class="sheet-attack-spacer"></div>
<div><label>AC -10</label><input type="text" name="attr_to_hit_ac_neg10"></div>
</div>
</div>
<div class="sheet-help">Attack success requires an equal to or above roll to hit.</div>
</div>
<div class="sheet-section">
<div class="sheet-subtitle">Armor Class</div>
<div class="sheet-grid sheet-grid-2">
<div class="sheet-field">
<label>Natural</label>
<input type="text" name="attr_ac_natural">
</div>
<div class="sheet-field">
<label>Armored</label>
<input type="text" name="attr_ac_armored">
</div>
<div class="sheet-field">
<label>Surprised</label>
<input type="text" name="attr_ac_surprised">
</div>
<div class="sheet-field">
<label>Rear</label>
<input type="text" name="attr_ac_rear">
</div>
</div>
<div class="sheet-field">
<label>Other Defenses</label>
<textarea name="attr_other_defenses"></textarea>
</div>
</div>
</div>
</div>
</div>
<!-- EQUIPMENT TAB -->
<div class="sheet-tab sheet-equipment">
<div class="sheet-section">
<div class="sheet-subtitle">Carried Equipment</div>
<div class="sheet-grid sheet-grid-equipment-gov sheet-mount-header">
<div>Carried Item</div>
<div>Weight</div>
</div>
<fieldset class="repeating_equipment">
<div class="sheet-grid sheet-grid-equipment-gov">
<input type="text" name="attr_carried_item">
<input type="text" name="attr_item_weight">
</div>
</fieldset>
<div class="sheet-grid sheet-grid-2">
<div class="sheet-field">
<label>Total Weight</label>
<input type="text" name="attr_total_weight" readonly>
</div>
<div class="sheet-field">
<label>Wealth</label>
<input type="text" name="attr_wealth">
</div>
</div>
</div>
</div>
<!-- PROFICIENCIES TAB -->
<div class="sheet-tab sheet-proficiencies">
<div class="sheet-two-col">
<div class="sheet-maincol">
<div class="sheet-section">
<div class="sheet-subtitle">Nonweapon Proficiencies</div>
<div class="sheet-grid sheet-grid-nwp sheet-mount-header">
<div>Name</div>
<div>Ability</div>
<div>Mod</div>
<div>Slots</div>
<div>Roll</div>
</div>
<fieldset class="repeating_nwp">
<div class="sheet-grid sheet-grid-nwp">
<input type="text" name="attr_nwp_name">
<input type="text" name="attr_nwp_ability">
<input type="text" name="attr_nwp_mod">
<input type="text" name="attr_nwp_slots">
<input type="text" name="attr_nwp_roll">
</div>
</fieldset>
</div>
</div>
<div class="sheet-sidecol">
<div class="sheet-section">
<div class="sheet-subtitle">Weapon Proficiencies</div>
<div class="sheet-grid sheet-grid-wp sheet-mount-header">
<div>Weapon Name</div>
<div>Slots</div>
</div>
<fieldset class="repeating_wp">
<div class="sheet-grid sheet-grid-wp">
<input type="text" name="attr_wp_weapon_name">
<input type="text" name="attr_wp_slots">
</div>
</fieldset>
</div>
</div>
</div>
</div>
<!-- COMMAND TAB -->
<div class="sheet-tab sheet-command">
<div class="sheet-section">
<div class="sheet-subtitle">Command Authority/Field Protocols</div>
<div class="sheet-grid sheet-grid-2">
<div class="sheet-field">
<label>Clearance Level</label>
<input type="text" name="attr_command_clearance_level">
</div>
<div class="sheet-field">
<label>Daily Slots Available</label>
<input type="text" name="attr_command_daily_slots">
</div>
</div>
<div class="sheet-grid sheet-grid-2">
<div class="sheet-field">
<label>Routine Clearance / Basic Issue</label>
<input type="text" name="attr_command_routine_basic">
</div>
<div class="sheet-field">
<label>Priority / Section Allocation</label>
<input type="text" name="attr_command_priority_section">
</div>
<div class="sheet-field">
<label>Immediate / Command Directive</label>
<input type="text" name="attr_command_immediate_directive">
</div>
<div class="sheet-field">
<label>Flash / Special Authorization</label>
<input type="text" name="attr_command_flash_special">
</div>
<div class="sheet-field">
<label>Top Secret / MACV Compartmentalized</label>
<input type="text" name="attr_command_topsecret_macv">
</div>
</div>
</div>
<div class="sheet-section">
<div class="sheet-subtitle">Request Log</div>
<div class="sheet-grid sheet-grid-command-log sheet-mount-header">
<div>Slot Tier</div>
<div>Command Calls / Kits</div>
<div>Used (Y/N)</div>
</div>
<fieldset class="repeating_command-log"> <!-- ← hyphen here -->
<div class="sheet-grid sheet-grid-command-log">
<div><input type="text" name="attr_cmdlog_slot_tier"></div>
<div><input type="text" name="attr_cmdlog_request"></div>
<div><input type="text" name="attr_cmdlog_used" placeholder="Y/N"></div>
</div>
</fieldset>
</div>
</div>
<!-- NOTES TAB -->
<div class="sheet-tab sheet-notes">
<div class="sheet-section">
<div class="sheet-subtitle">Character Notes</div>
<textarea class="sheet-notes-area" name="attr_character_notes"></textarea>
</div>
</div>
<script type="text/worker">
on("clicked:core", function() {
setAttrs({ sheetTab: "core" });
});
on("clicked:equipment", function() {
setAttrs({ sheetTab: "equipment" });
});
on("clicked:proficiencies", function() {
setAttrs({ sheetTab: "proficiencies" });
});
on("clicked:command", function() {
setAttrs({ sheetTab: "command" });
});
on("clicked:notes", function() {
setAttrs({ sheetTab: "notes" });
});
const updateTotalWeight = function() {
getSectionIDs("repeating_equipment", function(ids) {
const fields = ids.map(function(id) {
return "repeating_equipment_" + id + "_item_weight";
});
getAttrs(fields, function(values) {
let total = 0;
ids.forEach(function(id) {
const weight = parseFloat(values["repeating_equipment_" + id + "_item_weight"]) || 0;
total += weight;
});
// Round to 2 decimal places and convert to string
const roundedTotal = total.toFixed(2);
setAttrs({
total_weight: roundedTotal
});
});
});
};
const updateAttackTable = function() {
getAttrs(["attack_table_thaco"], function(values) {
const thaco = parseInt(values.attack_table_thaco, 10);
if (isNaN(thaco)) return;
const updates = {};
// Calculate needed roll for each AC (descending: lower AC needs higher roll)
const needed = (ac) => thaco - ac;
// Clamp helper: show actual if ≤20, else 20* (meaning nat 20 required)
const display = (val) => {
if (val <= 20) return Math.max(val, 1); // nothing below 1 (auto except possible fumble)
return 20; // or you can return "20*" as string if you make fields text
};
updates.to_hit_ac_1 = display(needed(1));
updates.to_hit_ac_2 = display(needed(2));
updates.to_hit_ac_3 = display(needed(3));
updates.to_hit_ac_4 = display(needed(4));
updates.to_hit_ac_5 = display(needed(5));
updates.to_hit_ac_6 = display(needed(6));
updates.to_hit_ac_7 = display(needed(7));
updates.to_hit_ac_8 = display(needed(8));
updates.to_hit_ac_9 = display(needed(9));
updates.to_hit_ac_10 = display(needed(10));
updates.to_hit_ac_neg1 = display(needed(-1));
updates.to_hit_ac_neg2 = display(needed(-2));
updates.to_hit_ac_neg3 = display(needed(-3));
updates.to_hit_ac_neg4 = display(needed(-4));
updates.to_hit_ac_neg5 = display(needed(-5));
updates.to_hit_ac_neg6 = display(needed(-6));
updates.to_hit_ac_neg7 = display(needed(-7));
updates.to_hit_ac_neg8 = display(needed(-8));
updates.to_hit_ac_neg9 = display(needed(-9));
updates.to_hit_ac_neg10 = display(needed(-10));
setAttrs(updates);
});
};
on("sheet:opened", function() {
updateTotalWeight();
updateAttackTable();
});
on("remove:repeating_equipment", updateTotalWeight);
on("change:repeating_equipment", updateTotalWeight);
on("change:attack_table_thaco", updateAttackTable);
</script>
Binary file not shown.

After

Width:  |  Height:  |  Size: 702 KiB

+8
View File
@@ -0,0 +1,8 @@
{
"html": "Ghosts_of_Vietnam_Character_Sheet_v2.html",
"css": "Ghosts_of_Vietnam_Character_Sheet_v2.css",
"authors": "Richard L. Littles",
"roll20userid": "17745109",
"preview": "Roll20 GOV Character Sheet.jpg",
"instructions": "A fully functional character sheet for Ghosts of Vietnam."
}