Files
Space-Game/js/pages/ships.js
2026-05-25 13:00:20 -04:00

556 lines
34 KiB
JavaScript
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.
window.GDD = window.GDD || {};
function ShipsPage() {
const [activeSection, setActiveSection] = React.useState('classes');
const shipClasses = [
{
name: 'Frigate',
hull: 400, armor: 350, shield: 300,
highSlots: 3, medSlots: 3, lowSlots: 2,
cpu: 120, powerGrid: 40, cargo: 150,
speed: 280, mass: 1200,
role: 'Fast scout and tackle. Low slot count but quick to align and warp. Good for new players.',
examples: ['Merlin', 'Rifter', 'Incursus', 'Punisher'],
},
{
name: 'Destroyer',
hull: 650, armor: 550, shield: 500,
highSlots: 7, medSlots: 3, lowSlots: 3,
cpu: 180, powerGrid: 65, cargo: 300,
speed: 210, mass: 1800,
role: 'Anti-frigate platform. Many turret hardpoints but slow and vulnerable to larger ships.',
examples: ['Cormorant', 'Thrasher', 'Catalyst', 'Coercer'],
},
{
name: 'Cruiser',
hull: 1200, armor: 1000, shield: 900,
highSlots: 5, medSlots: 4, lowSlots: 4,
cpu: 280, powerGrid: 110, cargo: 600,
speed: 175, mass: 3500,
role: 'Versatile workhorse. Can mine, fight, or explore. Good cargo hold and balanced slot layout.',
examples: ['Osprey', 'Rupture', 'Vexor', 'Maller'],
},
{
name: 'Battlecruiser',
hull: 2800, armor: 2400, shield: 2000,
highSlots: 7, medSlots: 5, lowSlots: 5,
cpu: 380, powerGrid: 180, cargo: 1000,
speed: 130, mass: 7000,
role: 'Command ship. Can fit warfare links and project damage. Excellent fleet support.',
examples: ['Drake', 'Hurricane', 'Myrmidon', 'Harbinger'],
},
{
name: 'Battleship',
hull: 6000, armor: 5000, shield: 4500,
highSlots: 8, medSlots: 5, lowSlots: 6,
cpu: 520, powerGrid: 280, cargo: 1800,
speed: 90, mass: 15000,
role: 'Heavy assault platform. Maximum firepower and tank but very slow. Fleet anchor.',
examples: ['Rokh', 'Tempest', 'Dominix', 'Apocalypse'],
},
];
const slotTypes = [
{
name: 'High Slots',
color: 'var(--red)',
icon: '◆',
description: 'Weapons, mining lasers, cloaks, salvagers. The things that do stuff to other things.',
modules: ['150mm Railgun', '200mm Autocannon', 'Heavy Missile Launcher', 'Mining Laser II', 'Salvager I', 'Cloaking Device'],
fitting: 'Turrets and launchers require both CPU and Power Grid. Heavy weapons need more of both.',
},
{
name: 'Medium Slots',
color: 'var(--cyan)',
icon: '◇',
description: 'Shields, propulsion, electronic warfare, tackle. The things that keep you alive or stop them.',
modules: ['Shield Booster', '1MN Afterburner', 'Warp Scrambler', 'Stasis Webifier', 'ECM Jammer', 'Shield Extender'],
fitting: 'Shield and propulsion modules are CPU-heavy. EWAR fits are tight on CPU, light on grid.',
},
{
name: 'Low Slots',
color: 'var(--green)',
icon: '○',
description: 'Armor, damage mods, cargo expanders, power diagnostics. Passive upgrades and tank.',
modules: ['Armor Plate', 'Magnetic Field Stabilizer', 'Cargo Expander', 'Power Diagnostic System', 'Capacitor Power Relay', 'Armor Repairer'],
fitting: 'Armor and damage modules are Power Grid-heavy. Passive modules use less CPU.',
},
];
return (
<div className="content-inner">
<h1 style={{ marginBottom: '8px' }}>Ships & Fitting System</h1>
<p style={{ color: 'var(--fg-dim)', fontSize: '0.95rem', maxWidth: '680px' }}>
Ships are the player's primary asset. Each ship has a slot layout with CPU and Power Grid limits
that constrain what modules can be fitted. Players own multiple ships and can assign AI crew to
pilot them on autonomous tasks.
</p>
{/* Tab navigation */}
<div style={{ display: 'flex', gap: 'var(--sp-2)', marginBottom: 'var(--sp-6)' }}>
{[
{ id: 'classes', label: 'Ship Classes' },
{ id: 'fitting', label: 'Fitting / Slots' },
{ id: 'acquisition', label: '🚀 Acquisition' },
{ id: 'crew', label: 'AI Crew' },
].map(t => (
<button key={t.id} className={`btn btn-sm${activeSection === t.id ? ' btn-primary' : ''}`}
onClick={() => setActiveSection(t.id)}>{t.label}</button>
))}
</div>
{/* SHIP CLASSES */}
{activeSection === 'classes' && (
<>
<div className="callout callout-info" style={{ marginBottom: 'var(--sp-5)' }}>
<strong>MVP scope:</strong> One ship class per faction to start (Frigate). Expand to Destroyer
and Cruiser in Phase 5+. Full roster is the launch target.
</div>
<div style={{ overflowX: 'auto' }}>
<table className="data-table">
<thead>
<tr>
<th>Class</th>
<th>Hull</th>
<th>Armor</th>
<th>Shield</th>
<th>High</th>
<th>Med</th>
<th>Low</th>
<th>CPU</th>
<th>Grid</th>
<th>Speed</th>
<th>Cargo</th>
</tr>
</thead>
<tbody>
{shipClasses.map((ship, i) => (
<tr key={i}>
<td style={{ color: 'var(--accent)', fontWeight: 600 }}>{ship.name}</td>
<td className="mono">{ship.hull}</td>
<td className="mono">{ship.armor}</td>
<td className="mono">{ship.shield}</td>
<td style={{ color: 'var(--red)' }}>{ship.highSlots}</td>
<td style={{ color: 'var(--cyan)' }}>{ship.medSlots}</td>
<td style={{ color: 'var(--green)' }}>{ship.lowSlots}</td>
<td className="mono">{ship.cpu}</td>
<td className="mono">{ship.powerGrid}</td>
<td className="mono">{ship.speed}</td>
<td className="mono">{ship.cargo}</td>
</tr>
))}
</tbody>
</table>
</div>
<div style={{ marginTop: 'var(--sp-6)' }}>
<h3>Class Details</h3>
<div className="grid-2">
{shipClasses.slice(0, 4).map((ship, i) => (
<div key={i} className="card">
<h4 style={{ color: 'var(--accent)', marginBottom: 'var(--sp-2)' }}>{ship.name}</h4>
<p style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: '0 0 var(--sp-3) 0' }}>{ship.role}</p>
<div style={{ fontSize: '0.75rem', color: 'var(--muted)' }}>
<strong>Variants:</strong> {ship.examples.join(', ')}
</div>
</div>
))}
</div>
</div>
</>
)}
{/* FITTING / SLOTS */}
{activeSection === 'fitting' && (
<>
<div className="section-header">
<span className="section-num">SHIP-FIT</span>
<h2 style={{ margin: 0 }}>Slot Types & Fitting Constraints</h2>
</div>
<div className="grid-2" style={{ marginBottom: 'var(--sp-6)' }}>
{slotTypes.map((slot, i) => (
<div key={i} className="card" style={{ borderLeft: `3px solid ${slot.color}` }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 'var(--sp-3)', marginBottom: 'var(--sp-3)' }}>
<span style={{ color: slot.color, fontSize: '1.2rem' }}>{slot.icon}</span>
<h4 style={{ color: slot.color, margin: 0 }}>{slot.name}</h4>
</div>
<p style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: '0 0 var(--sp-3) 0' }}>{slot.description}</p>
<div style={{ fontSize: '0.8rem', color: 'var(--fg-dim)', marginBottom: 'var(--sp-2)' }}>
<strong style={{ color: 'var(--muted)' }}>Typical modules:</strong>
</div>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 'var(--sp-1)' }}>
{slot.modules.map((m, j) => (
<span key={j} className="pill" style={{ background: 'var(--surface-raised)', color: 'var(--fg-dim)', border: '1px solid var(--border)', fontSize: '0.7rem' }}>
{m}
</span>
))}
</div>
</div>
))}
</div>
<div className="section-header">
<span className="section-num">SHIP-CPU</span>
<h2 style={{ margin: 0 }}>CPU & Power Grid</h2>
</div>
<div className="card card-accent">
<h4>Fitting Mechanics</h4>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.82rem', color: 'var(--fg-dim)', lineHeight: 2 }}>
1. Each module has a CPU cost and a Power Grid cost.<br/>
2. Total fitted module costs must not exceed ship's CPU and Power Grid.<br/>
3. Some modules have ship bonuses (e.g. "+5% mining laser yield per Cruiser level").<br/>
4. Rig slots add permanent modifications cannot be removed, only destroyed.<br/>
5. Fitting is only possible when docked at a station with fitting service.
</div>
</div>
<div className="grid-2" style={{ marginTop: 'var(--sp-5)' }}>
<div className="card">
<h4 style={{ color: 'var(--accent)' }}>Example: Mining Cruiser Fit</h4>
<table className="data-table">
<thead><tr><th>Slot</th><th>Module</th><th>CPU</th><th>Grid</th></tr></thead>
<tbody>
<tr><td style={{ color: 'var(--red)' }}>High 1</td><td>Mining Laser II</td><td className="mono">30</td><td className="mono">10</td></tr>
<tr><td style={{ color: 'var(--red)' }}>High 2</td><td>Mining Laser II</td><td className="mono">30</td><td className="mono">10</td></tr>
<tr><td style={{ color: 'var(--cyan)' }}>Med 1</td><td>1MN Afterburner</td><td className="mono">25</td><td className="mono">15</td></tr>
<tr><td style={{ color: 'var(--cyan)' }}>Med 2</td><td>Shield Booster I</td><td className="mono">30</td><td className="mono">10</td></tr>
<tr><td style={{ color: 'var(--cyan)' }}>Med 3</td><td>Market Analyzer (AI)</td><td className="mono">15</td><td className="mono">0</td></tr>
<tr><td style={{ color: 'var(--green)' }}>Low 1</td><td>Mining Upgrade I</td><td className="mono">20</td><td className="mono">5</td></tr>
<tr><td style={{ color: 'var(--green)' }}>Low 2</td><td>Cargo Expander I</td><td className="mono">15</td><td className="mono">0</td></tr>
<tr><td style={{ color: 'var(--green)' }}>Low 3</td><td>Nav Processor (AI)</td><td className="mono">10</td><td className="mono">0</td></tr>
<tr style={{ borderTop: '2px solid var(--border-light)' }}>
<td colSpan="2" style={{ fontWeight: 600 }}>Total</td>
<td className="mono" style={{ fontWeight: 600, color: 'var(--cyan)' }}>175/280</td>
<td className="mono" style={{ fontWeight: 600, color: 'var(--green)' }}>50/110</td>
</tr>
</tbody>
</table>
<div style={{ marginTop: 'var(--sp-2)', fontFamily: 'var(--font-mono)', fontSize: '0.72rem', color: 'var(--purple)' }}>
AI modules: Market Analyzer (med) tracks local prices and flags arbitrage opportunities. Nav Processor (low) optimizes warp routes. See Ship AI \u2192 Module Gates tab.
</div>
</div>
<div className="card">
<h4 style={{ color: 'var(--red)' }}>Example: Combat Frigate Fit</h4>
<table className="data-table">
<thead><tr><th>Slot</th><th>Module</th><th>CPU</th><th>Grid</th></tr></thead>
<tbody>
<tr><td style={{ color: 'var(--red)' }}>High 1</td><td>150mm Railgun</td><td className="mono">35</td><td className="mono">12</td></tr>
<tr><td style={{ color: 'var(--red)' }}>High 2</td><td>200mm Autocannon</td><td className="mono">30</td><td className="mono">14</td></tr>
<tr><td style={{ color: 'var(--cyan)' }}>Med 1</td><td>Warp Scrambler I</td><td className="mono">25</td><td className="mono">1</td></tr>
<tr><td style={{ color: 'var(--cyan)' }}>Med 2</td><td>1MN Afterburner</td><td className="mono">25</td><td className="mono">15</td></tr>
<tr><td style={{ color: 'var(--green)' }}>Low 1</td><td>Armor Plate I</td><td className="mono">10</td><td className="mono">20</td></tr>
<tr><td style={{ color: 'var(--green)' }}>Low 2</td><td>Magnetic Field Stab.</td><td className="mono">15</td><td className="mono">5</td></tr>
<tr style={{ borderTop: '2px solid var(--border-light)' }}>
<td colSpan="2" style={{ fontWeight: 600 }}>Total</td>
<td className="mono" style={{ fontWeight: 600, color: 'var(--cyan)' }}>140/120 </td>
<td className="mono" style={{ fontWeight: 600, color: 'var(--green)' }}>67/40 </td>
</tr>
</tbody>
</table>
<div className="callout callout-danger" style={{ marginTop: 'var(--sp-3)', fontSize: '0.8rem' }}>
<strong>Overfit!</strong> CPU 140/120 and Grid 67/40 exceeds ship capacity. Drop a turret or fit lower-tier modules.
</div>
</div>
</div>
</>
)}
{/* SHIP ACQUISITION */}
{activeSection === 'acquisition' && (<>
<div className="section-header">
<span className="section-num">SHIP-ACQ</span>
<h2 style={{ margin: 0 }}>Ship Acquisition & Hangar</h2>
</div>
<div className="callout callout-info" style={{ marginBottom: 'var(--sp-5)' }}>
<strong>Ships are the player's primary asset, and acquiring them is a core economic milestone.</strong>
The system balances accessibility (new players always have a ship) with economic consequence
(better ships cost real ISK and represent player investment). Players can own multiple ships
stored in station hangars, but only fly one at a time. Switching ships requires docking.
</div>
<h3 style={{ marginBottom: 'var(--sp-4)' }}>Ship Ownership Model</h3>
<div className="grid-2" style={{ marginBottom: 'var(--sp-6)' }}>
<div className="card" style={{ borderLeft: '3px solid var(--green)' }}>
<h4 style={{ color: 'var(--green)' }}>Single Active Ship</h4>
<p style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: '0 0 var(--sp-3) 0' }}>
A player has exactly <strong style={{ color: 'var(--fg)' }}>one active ship</strong> at a time — the ship they're currently piloting.
This is the ship that appears in the star system, has a position, and can perform actions (mine, fight, warp).
The active ship cannot be traded, contracted, or stored while it is active.
</p>
</div>
<div className="card" style={{ borderLeft: '3px solid var(--cyan)' }}>
<h4 style={{ color: 'var(--cyan)' }}>Hangar Storage</h4>
<p style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: '0 0 var(--sp-3) 0' }}>
Ships not currently being piloted are stored in a <strong style={{ color: 'var(--fg)' }}>station hangar</strong>.
Each station has a hangar per player. A player can store unlimited ships at any station they have docking access to.
Hangar ships are safe they cannot be destroyed or stolen while stored.
</p>
</div>
</div>
<h3 style={{ marginBottom: 'var(--sp-4)' }}>How Players Get Ships</h3>
<div style={{ overflowX: 'auto', marginBottom: 'var(--sp-6)' }}>
<table className="data-table">
<thead>
<tr><th>Method</th><th>Cost</th><th>Available At</th><th>Phase</th></tr>
</thead>
<tbody>
{[
{ method: 'Rookie Frigate (free)', cost: '0 ISK — granted on first spawn and on death respawn', available: 'Automatic on new player creation. Automatic on respawn after ship destruction.', phase: 'Phase 0', color: 'var(--green)' },
{ method: 'NPC Market (sell orders)', cost: 'Hull base value × 1.01.5 (station markup)', available: 'Any station with Market service. NPC sell orders seeded at galaxy gen.', phase: 'Phase 6', color: 'var(--cyan)' },
{ method: 'Player Market (sell orders)', cost: 'Player-set price — typically below NPC price for T1, above for T2', available: 'Any station with Market service. Player-placed sell orders.', phase: 'Phase 10', color: 'var(--accent)' },
{ method: 'Manufacturing', cost: 'Minerals (from refining ore) + blueprint + factory fee + time', available: 'Stations with Factory service. Requires Industry skill ≥ ship class tier.', phase: 'Phase 5', color: 'var(--purple)' },
{ method: 'Loyalty Point Store', cost: 'ISK + LP — faction ships at below-market rates', available: 'Faction stations only. Requires high standing + LP balance.', phase: 'Phase 12', color: 'var(--red)' },
].map((row, i) => (
<tr key={i}>
<td style={{ fontWeight: 600, color: row.color }}>{row.method}</td>
<td style={{ color: 'var(--fg-dim)', fontSize: '0.85rem' }}>{row.cost}</td>
<td style={{ color: 'var(--fg-dim)', fontSize: '0.85rem' }}>{row.available}</td>
<td className="mono">{row.phase}</td>
</tr>
))}
</tbody>
</table>
</div>
<h3 style={{ marginBottom: 'var(--sp-4)' }}>The Rookie Frigate</h3>
<div className="grid-2" style={{ marginBottom: 'var(--sp-6)' }}>
<div className="card" style={{ borderLeft: '3px solid var(--green)' }}>
<h4 style={{ color: 'var(--green)' }}>Free Ship Policy</h4>
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
<li><strong style={{ color: 'var(--fg)' }}>On first spawn:</strong> New player receives a Rookie Frigate at their faction's starter station.</li>
<li><strong style={{ color: 'var(--fg)' }}>On death (ship destroyed):</strong> Player respawns at their home station with a <em>new</em> Rookie Frigate. Always free.</li>
<li><strong style={{ color: 'var(--fg)' }}>Cannot be sold or traded:</strong> The Rookie Frigate has no market value.</li>
<li><strong style={{ color: 'var(--fg)' }}>Cannot be insured:</strong> Insurance doesn't apply you always get a new one free.</li>
<li><strong style={{ color: 'var(--fg)' }}>Basic stats:</strong> 2 high slots, 2 mid slots, 1 low slot. 200 hull, 150 armor, 100 shield. 100 cargo. Very limited enough for basic mining and combat, but weak.</li>
<li><strong style={{ color: 'var(--fg)' }}>NPC market exclusion:</strong> Rookie Frigates are never sold on the NPC market they exist only as free grants.</li>
</ul>
</div>
<div className="card" style={{ borderLeft: '3px solid var(--red)' }}>
<h4 style={{ color: 'var(--red)' }}>Why Free Respawn?</h4>
<p style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: '0 0 var(--sp-3) 0' }}>
A player without a ship has no way to earn ISK they can't mine, fight, or trade. A permanent
"ship-less" state is a dead-end that causes player churn. The free Rookie Frigate ensures that
<strong style={{ color: 'var(--fg)' }}> every player always has a path back into the game</strong>, no matter how
many times they're destroyed. The cost of death is the <em>upgraded</em> ship and modules you lost
not the ability to play at all.
</p>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.72rem', color: 'var(--muted)' }}>
Design rule: "Never softlock the player out of the game loop." The Rookie Frigate is the safety net.
</div>
</div>
</div>
<h3 style={{ marginBottom: 'var(--sp-4)' }}>NPC Market Ship Pricing</h3>
<div className="callout callout-info" style={{ marginBottom: 'var(--sp-5)' }}>
<strong>NPC sell orders provide baseline ship availability.</strong> At galaxy generation, the server seeds NPC sell orders
for every ship type at stations with Factory services. These orders have <em>infinite</em> quantity (they never run out)
but are priced at a premium over manufacturing cost. This ensures:
(1) players can always buy a basic ship hull, (2) player manufacturers can undercut NPC prices profitably,
(3) the economy has a known ISK sink ceiling per ship class.
</div>
<div style={{ overflowX: 'auto', marginBottom: 'var(--sp-6)' }}>
<table className="data-table">
<thead>
<tr><th>Ship Class</th><th>Manufacturing Cost</th><th>NPC Sell Price</th><th>Insurance (Standard)</th><th>Effective Replacement</th></tr>
</thead>
<tbody>
{[
{ cls: 'Frigate', mfg: '~8,000 ISK', npc: '~15,000 ISK', insurance: '~10,500 ISK (70%)', effective: '~4,500 ISK + modules' },
{ cls: 'Destroyer', mfg: '~20,000 ISK', npc: '~35,000 ISK', insurance: '~24,500 ISK (70%)', effective: '~10,500 ISK + modules' },
{ cls: 'Cruiser', mfg: '~60,000 ISK', npc: '~100,000 ISK', insurance: '~70,000 ISK (70%)', effective: '~30,000 ISK + modules' },
{ cls: 'Battlecruiser', mfg: '~180,000 ISK', npc: '~300,000 ISK', insurance: '~210,000 ISK (70%)', effective: '~90,000 ISK + modules' },
{ cls: 'Battleship', mfg: '~500,000 ISK', npc: '~800,000 ISK', insurance: '~560,000 ISK (70%)', effective: '~240,000 ISK + modules' },
].map((row, i) => (
<tr key={i}>
<td style={{ fontWeight: 600, color: 'var(--accent)' }}>{row.cls}</td>
<td className="mono">{row.mfg}</td>
<td className="mono" style={{ color: 'var(--red)' }}>{row.npc}</td>
<td className="mono" style={{ color: 'var(--green)' }}>{row.insurance}</td>
<td className="mono" style={{ color: 'var(--fg-dim)' }}>{row.effective}</td>
</tr>
))}
</tbody>
</table>
</div>
<h3 style={{ marginBottom: 'var(--sp-4)' }}>Ship Switching Flow</h3>
<div className="card card-accent" style={{ marginBottom: 'var(--sp-5)' }}>
<h4 style={{ marginBottom: 'var(--sp-4)' }}>Docked Ship Switch</h4>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.82rem', color: 'var(--fg-dim)', lineHeight: 2.2 }}>
<span style={{ color: 'var(--cyan)' }}>1. Dock at station</span> — Player must be docked. Cannot switch ships while in space.<br/>
<span style={{ color: 'var(--accent)' }}>2. Open Hangar panel</span> — Station Mode → Hangar tab. Shows all ships stored at this station.<br/>
<span style={{ color: 'var(--green)' }}>3. Select a ship</span> — Shows ship name, class, fitting summary, cargo, insurance status.<br/>
<span style={{ color: 'var(--purple)' }}>4. Activate</span> — Click "Make Active". Current active ship moves to hangar. Selected ship becomes active.<br/>
<span style={{ color: 'var(--fg)' }}>5. Cargo transfer</span> — Prompt to transfer cargo between ships (limited by destination capacity). Remaining stays in station inventory.<br/>
<span style={{ color: 'var(--muted)' }}>6. Undock</span> Player undocks in the new active ship. Old ship stays in hangar.
</div>
</div>
<div className="callout callout-warn" style={{ marginBottom: 'var(--sp-5)' }}>
<strong>Cannot switch while in space.</strong> If your ship is destroyed, you respawn at your home station
in a Rookie Frigate you cannot switch to a hangar ship remotely. You must fly to the station where the ship is stored and dock.
This is intentional: it creates geographic identity ("my ships are in Amarr") and makes home station choice meaningful.
</div>
<div className="section-header" style={{ marginTop: 'var(--sp-6)' }}>
<span className="section-num">SHIP-ACQ-DB</span>
<h2 style={{ margin: 0 }}>Backend Impact</h2>
</div>
<div className="card card-accent">
<h4 style={{ marginBottom: 'var(--sp-4)' }}>Schema & Reducer Changes</h4>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.82rem', color: 'var(--fg-dim)', lineHeight: 2 }}>
<span style={{ color: 'var(--accent)' }}>ships</span> add column: <code>storage_location</code> (enum: active / hangar:station_id). When active, ship has system_id/x/y/z. When in hangar, stored at station.<br/>
<span style={{ color: 'var(--cyan)' }}>ships</span> add column: <code>is_rookie</code> (bool, default false). Rookie frigates are untradeable, uninsurable, free-replace.<br/>
<span style={{ color: 'var(--green)' }}>npc_sell_orders</span> seeded at galaxy gen for every <code>ship_types</code> entry at Factory stations. Infinite quantity. Price = <code>base_hull_value × 1.5</code>.<br/>
<span style={{ color: 'var(--purple)' }}>New reducer:</span> <code>switch_ship(player_id, target_ship_id)</code> validate docked, validate target in same station hangar, swap active hangar.<br/>
<span style={{ color: 'var(--red)' }}>Updated reducer:</span> <code>connect_player(display_name)</code> on first connection, spawn Rookie Frigate at faction starter station. On subsequent, load existing active ship.<br/>
<span style={{ color: 'var(--fg)' }}>Updated reducer:</span> <code>respawn_player(player_id)</code> on ship destruction, create new Rookie Frigate at home station, set as active.
</div>
</div>
</>)}
{/* AI CREW */}
{activeSection === 'crew' && (
<>
<div className="callout callout-info" style={{ marginBottom: 'var(--sp-5)' }}>
<strong>Post-MVP feature.</strong> AI crew is designed here so the ship and backend architecture
supports it from the start, but implementation is planned after the core gameplay loop ships.
</div>
<div className="section-header">
<span className="section-num">SHIP-AI</span>
<h2 style={{ margin: 0 }}>AI Crew System</h2>
</div>
<p style={{ color: 'var(--fg-dim)', fontSize: '0.9rem', maxWidth: '680px', marginBottom: 'var(--sp-5)' }}>
Players can own multiple ships and assign AI crew members to pilot them. AI ships execute
autonomous tasks mining runs, patrol routes, trade delivery while the player controls
their primary ship directly. AI crew gain experience over time and improve at their assigned role.
</p>
<div className="grid-2" style={{ marginBottom: 'var(--sp-6)' }}>
<div className="card" style={{ borderLeft: '3px solid var(--accent)' }}>
<h4 style={{ color: 'var(--accent)' }}>Crew Roles</h4>
<table className="data-table">
<thead><tr><th>Role</th><th>Behavior</th><th>XP Growth</th></tr></thead>
<tbody>
<tr>
<td><span className="pill pill-amber">Miner</span></td>
<td style={{ color: 'var(--fg-dim)' }}>Warps to belt, mines until cargo full, returns to station, sells ore.</td>
<td style={{ color: 'var(--fg-dim)' }}>Faster cycle times, better ore selection.</td>
</tr>
<tr>
<td><span className="pill pill-cyan">Patrol</span></td>
<td style={{ color: 'var(--fg-dim)' }}>Circulates waypoints, engages hostiles, reports contacts.</td>
<td style={{ color: 'var(--fg-dim)' }}>Better target priority, longer patrol endurance.</td>
</tr>
<tr>
<td><span className="pill pill-green">Hauler</span></td>
<td style={{ color: 'var(--fg-dim)' }}>Moves cargo between stations along trade routes.</td>
<td style={{ color: 'var(--fg-dim)' }}>Faster warp align, larger cargo optimization.</td>
</tr>
<tr>
<td><span className="pill pill-red">Guard</span></td>
<td style={{ color: 'var(--fg-dim)' }}>Escorts player ship, engages threats within range.</td>
<td style={{ color: 'var(--fg-dim)' }}>Better reaction time, coordination with fleet.</td>
</tr>
</tbody>
</table>
</div>
<div className="card" style={{ borderLeft: '3px solid var(--cyan)' }}>
<h4 style={{ color: 'var(--cyan)' }}>Crew Progression</h4>
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.82rem', color: 'var(--fg-dim)', lineHeight: 2 }}>
<strong style={{ color: 'var(--fg)' }}>Rank levels:</strong><br/>
<span style={{ color: 'var(--muted)' }}>Cadet</span> <span style={{ color: 'var(--green)' }}>Ensign</span> {' '}
<span style={{ color: 'var(--cyan)' }}>Lieutenant</span> {' '}
<span style={{ color: 'var(--purple)' }}>Commander</span> {' '}
<span style={{ color: 'var(--accent)' }}>Captain</span><br/><br/>
<strong style={{ color: 'var(--fg)' }}>XP sources:</strong><br/>
Task completion (base XP)<br/>
Task success rate bonus<br/>
Survival bonus (ship not destroyed)<br/>
Player commendation (manual XP grant)
</div>
</div>
</div>
<div className="section-header">
<span className="section-num">SHIP-OPS</span>
<h2 style={{ margin: 0 }}>Task Assignment Flow</h2>
</div>
<div className="card card-accent">
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.82rem', color: 'var(--fg-dim)', lineHeight: 2 }}>
1. Player docks at station and opens <strong style={{ color: 'var(--fg)' }}>Crew Management</strong> panel<br/>
2. Selects an idle ship + available crew member<br/>
3. Assigns a <strong style={{ color: 'var(--accent)' }}>task template</strong> (mine system X, patrol route Y, haul to station Z)<br/>
4. Crew departs autonomously ship disappears from player's direct control<br/>
5. Player receives periodic <strong style={{ color: 'var(--cyan)' }}>status reports</strong> in a dedicated channel<br/>
6. Task completes (or ship is destroyed) → crew returns to station or sends distress signal<br/>
7. Resources earned are deposited in player's station inventory
</div>
</div>
<div className="callout callout-warn" style={{ marginTop: 'var(--sp-5)' }}>
<strong>Risk:</strong> AI crew earning passive income could trivialize the economy. Mitigation: AI
operations have costs (fuel, maintenance, crew wages) and diminishing returns at scale. A player
with 10 AI miners shouldn't earn 10× a single player — there should be coordination overhead.
</div>
<div className="callout callout-info" style={{ marginTop: 'var(--sp-4)' }}>
<strong>AI Crew vs. Zora (Ship AI):</strong> These are two different systems. <strong>AI Crew</strong> (this tab) are autonomous
pilots that fly <em>other</em> ships on your behalf — mining runs, patrol routes, hauling. <strong>Zora</strong> (see Ship AI page)
is a companion AI installed on <em>your current ship</em> that provides market intelligence, tactical advice,
and dialogue. Think of AI Crew as your employees and Zora as your ship's computer. They do not share
systems, modules, or XP. A future expansion may let Zora be assigned to an AI Crew ship, but that is post-MVP scope.
</div>
</>
)}
{/* Death & Loss */}
<div className="callout callout-info" style={{ marginTop: 'var(--sp-6)' }}>
<strong>Slot scope note:</strong> High, Medium, and Low slots cover combat, mining, propulsion, and tank modules. Ship AI modules (Communications Processor, Market Analyzer, etc.) are a separate system see the <em>Ship AI Module Gates</em> tab for the full AI module catalog and how they install alongside standard fittings.
</div>
<div className="section-header" style={{ marginTop: 'var(--sp-8)' }}>
<span className="section-num">SHIP-DEATH</span>
<h2 style={{ margin: 0 }}>Ship Destruction</h2>
</div>
<div className="grid-2">
<div className="card" style={{ borderLeft: '3px solid var(--red)' }}>
<h4 style={{ color: 'var(--red)' }}>What you lose</h4>
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
<li>The ship hull itself (destroyed)</li>
<li>All fitted modules (50% chance each to drop as loot)</li>
<li>Cargo destroyed or dropped (50/50 split)</li>
<li>AI crew aboard injured, require medical bay recovery time</li>
</ul>
</div>
<div className="card" style={{ borderLeft: '3px solid var(--green)' }}>
<h4 style={{ color: 'var(--green)' }}>What you keep</h4>
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
<li>Your other ships in hangars</li>
<li>Station inventory and assets</li>
<li>Player XP and progression</li>
<li>ISK in wallet ()</li>
</ul>
</div>
</div>
<div className="callout callout-danger" style={{ marginTop: 'var(--sp-5)' }}>
<strong>Respawn:</strong> Player respawns at their home station (or nearest friendly station) in a
rookie frigate. Insurance policies can partially reimburse ship loss.
</div>
</div>
);
}
window.GDD.ShipsPage = ShipsPage;