Ringworld 0.5.0: v13/v14 compatibility, Ringworld '84 theme, combat automation
- Foundry v13/v14 compatibility (verified on 14.364) - Complete "Ringworld '84" retheme: CSS custom properties, warm space-black + bronze + ring-arc amber palette, uniform across sheets, dialogs, chat cards, hit-location picker, and impulse HUD - Fix HP damage evaporating on re-prepare: maximums always derived, current values source-authoritative, with a one-time world migration - Ammunition tracking: per-attack consumption, reload button, ammo badge; empty weapons block attacks - Energy weapons auto-link a carried power pack instead of failing - Special Success rolls damage dice twice; fumbles flag GM adjudication (both toggleable world settings) - Defender Dodge prompt before damage (special hits need special dodge) - Damage Mod and derived rolls always recompute; shown read-only - Creature sheet rebuilt to full parity: characteristics, derived rolls, body-schema hit grid with AP totals, weapons/armor/skills - Seeded "Ringworld GM Reference" journal (outcomes, impulses, attack workflow, wounds, 1984 quirks, quick start) - Shared characteristic-check dialog between explorer and creature Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
import { SYSTEM_ID } from "./constants";
|
||||
|
||||
const JOURNAL_NAME = "Ringworld GM Reference";
|
||||
|
||||
interface ReferencePage {
|
||||
name: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
function buildPages(): ReferencePage[] {
|
||||
return [
|
||||
{
|
||||
name: "Percentile Outcomes",
|
||||
content: `
|
||||
<p>Every check is a d100 roll against a target percentage. The system classifies results automatically:</p>
|
||||
<ul>
|
||||
<li><strong>Success</strong> — roll ≤ target.</li>
|
||||
<li><strong>Special Success</strong> — roll ≤ one fifth of the target (minimum 1). Attacks roll their damage dice twice when <em>Automate Special Success Damage</em> is enabled.</li>
|
||||
<li><strong>Failure</strong> — roll > target.</li>
|
||||
<li><strong>Fumble</strong> — roll of 96–100 when the target is below 50, or a natural 100 otherwise. The GM adjudicates a mishap: dropped or damaged weapon, hit an ally, drained power pack.</li>
|
||||
</ul>
|
||||
<p>Characteristic checks use Characteristic × Multiplier (usually ×5): click any characteristic button on a sheet to pick the multiplier.</p>
|
||||
`
|
||||
},
|
||||
{
|
||||
name: "Combat Sequence (Impulses)",
|
||||
content: `
|
||||
<p>Ringworld does not use simple initiative. Combat rounds are split into <strong>impulses</strong> and each combatant acts on a rhythm set by their <strong>Action Ranking (AR)</strong>, which is derived from DEX (lower is faster) and worsened by encumbrance.</p>
|
||||
<ol>
|
||||
<li>Add combatants to the Combat Tracker as normal. The Ringworld impulse panel replaces the core tracker list.</li>
|
||||
<li>Each combatant schedules an action: a <strong>major action</strong> (attack, full move, complex task) completes after AR impulses; a <strong>minor action</strong> (drop prone, shout, draw) completes after 1 impulse.</li>
|
||||
<li>Advance the clock with <em>Next Completion</em> or <em>+1</em>. When a combatant's action completes, resolve it, then let them schedule the next one.</li>
|
||||
</ol>
|
||||
<p>The floating impulse HUD can be dragged anywhere on screen and mirrors the tracker for quick play.</p>
|
||||
`
|
||||
},
|
||||
{
|
||||
name: "Attack Workflow",
|
||||
content: `
|
||||
<p>Target a token, then press the weapon's <strong>Use</strong> button on the attacker's sheet. The system walks through the 1984 rules in order:</p>
|
||||
<ol>
|
||||
<li><strong>Aim state</strong> (ranged only): unaimed fires at quarter skill, partially aimed at half, fully aimed at full skill. Cover, movement, range and situational modifiers are applied before the aim multiplier.</li>
|
||||
<li><strong>Ammunition and energy</strong> are spent. Projectile weapons with an ammo capacity are blocked when empty — use the <em>Reload</em> button on the weapon row. Energy weapons draw from the actor pool or a linked power pack.</li>
|
||||
<li><strong>Dodge</strong>: on a hit, the defender is offered a Dodge roll (DEX ×5). A successful dodge evades a normal hit; only a <em>special</em> dodge evades a <em>special</em> hit. Disable with the <em>Prompt Defender Dodge</em> setting.</li>
|
||||
<li><strong>Hit location</strong> is rolled on a d20 (or picked manually). Species use their own body schema — puppeteers, dolphins, trinocs, bandersnatchi and kzinti map differently.</li>
|
||||
<li><strong>Damage</strong> is rolled, stacked armor at that location is subtracted, and the result reduces <em>both</em> the location HP and the general HP.</li>
|
||||
</ol>
|
||||
`
|
||||
},
|
||||
{
|
||||
name: "Wounds & Conditions",
|
||||
content: `
|
||||
<p>When a hit location reaches 0 HP or less, conditions are applied automatically:</p>
|
||||
<ul>
|
||||
<li><strong>Head or Chest at 0</strong> — unconscious and prone.</li>
|
||||
<li><strong>Abdomen at 0</strong> — prone, both legs unusable.</li>
|
||||
<li><strong>Arm at 0</strong> — that arm is unusable.</li>
|
||||
<li><strong>Leg at 0</strong> — that leg is unusable, and the character falls prone.</li>
|
||||
<li><strong>General HP at 0</strong> — dying.</li>
|
||||
<li><strong>Head, chest or abdomen at negative full value</strong> — dying; a head at negative full value is death outright.</li>
|
||||
</ul>
|
||||
<p>Limbs cannot go below their negative maximum. Use <em>Reset Conditions</em> on a sheet after treatment or recovery. Prone, unconscious and dead sync to token status icons.</p>
|
||||
`
|
||||
},
|
||||
{
|
||||
name: "Running the 1984 Rules",
|
||||
content: `
|
||||
<p>Quirks of the original boxed set that the system encodes for you:</p>
|
||||
<ul>
|
||||
<li><strong>General HP = CON + MAS.</strong> MAS (mass) replaces the familiar SIZ. Location HP scale from general HP by body schema.</li>
|
||||
<li><strong>Damage modifier</strong> comes from STR + MAS and is recomputed automatically when characteristics change.</li>
|
||||
<li><strong>Skill pools:</strong> Education points = (EDU − 10) × 20, Pursuit points = (Age − EDU − 6) × 20, Special points = INT × 10. The character builder on the Skills tab tracks all three.</li>
|
||||
<li><strong>Skill category caps:</strong> each category is capped by a characteristic pair (e.g. Agility by STR + DEX). The builder enforces the caps.</li>
|
||||
<li><strong>Gravity matters:</strong> carried weight is halved in light gravity and doubled in heavy gravity before comparing to the STR limit; over-limit explorers slow to Move 2 and suffer an Action Ranking penalty.</li>
|
||||
<li><strong>Energy economy:</strong> most Ringworld tech runs on power packs (R20/R50/R100). Weapons can draw from a linked pack — keep spares, and remember fumbles can drain them.</li>
|
||||
</ul>
|
||||
`
|
||||
},
|
||||
{
|
||||
name: "GM Quick Start",
|
||||
content: `
|
||||
<p>To get a table playing quickly:</p>
|
||||
<ol>
|
||||
<li><strong>Seed the catalog</strong> (Items sidebar button) — species, 55 base skills, pursuits, weapons, armor and gear from the boxed set appear in organised folders. This runs automatically for new worlds.</li>
|
||||
<li><strong>Create Random Explorer</strong> (Actors sidebar button) — rolls characteristics by species and gravity, adds base skills and a starter kit.</li>
|
||||
<li>For bespoke characters, unlock the sheet tools (padlock, top right of the sheet) and use the <strong>Character Builder</strong> on the Skills tab: pick pursuits, then allocate the three point pools.</li>
|
||||
<li>Creatures get the same automation — hit locations, dodge, armor stacking — via the creature sheet, with a body schema selector for non-humanoids.</li>
|
||||
<li>Check <strong>System Settings</strong> for the automation toggles (special success damage, defender dodge prompts).</li>
|
||||
</ol>
|
||||
`
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
export async function seedGmReference(): Promise<boolean> {
|
||||
if (!game.user?.isGM) return false;
|
||||
|
||||
const journals = (game as any).journal;
|
||||
const existing = journals?.find((entry: any) => entry.getFlag?.(SYSTEM_ID, "gmReference") === true)
|
||||
?? journals?.getName?.(JOURNAL_NAME);
|
||||
if (existing) return false;
|
||||
|
||||
const pages = buildPages().map((page, index) => ({
|
||||
name: page.name,
|
||||
type: "text",
|
||||
sort: (index + 1) * 100000,
|
||||
text: {
|
||||
format: 1,
|
||||
content: page.content.trim()
|
||||
}
|
||||
}));
|
||||
|
||||
await (getDocumentClass("JournalEntry") as any).create({
|
||||
name: JOURNAL_NAME,
|
||||
pages,
|
||||
flags: {
|
||||
[SYSTEM_ID]: {
|
||||
gmReference: true
|
||||
}
|
||||
},
|
||||
ownership: { default: 0 }
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user