- Restructure flat static prototype into pnpm workspace monorepo - apps/game: playable shell with R3F 3D scene, HUD, SpacetimeDB connection - apps/docs: design docs and prototypes - apps/site: landing page - packages/ui: shared Button and Panel primitives - services/spacetimedb: backend module (9 tables, 11 reducers) - Archive legacy static files to archive/legacy-static/ - Game loop: connect, undock, target, approach, dock, mine, sell - Add pnpm-workspace.yaml, tsconfig.base.json, spacetime.json
591 lines
38 KiB
JavaScript
591 lines
38 KiB
JavaScript
window.GDD = window.GDD || {};
|
||
|
||
function SocialPage() {
|
||
const [activeSection, setActiveSection] = React.useState('progression');
|
||
|
||
const skillCategories = [
|
||
{
|
||
name: 'Combat',
|
||
color: 'var(--red)',
|
||
skills: ['Gunnery', 'Missiles', 'Shield Operation', 'Armor Tanking', 'Electronic Warfare'],
|
||
xpSource: 'Dealing damage, destroying NPCs, completing combat missions',
|
||
},
|
||
{
|
||
name: 'Industry',
|
||
color: 'var(--accent)',
|
||
skills: ['Mining', 'Refining', 'Manufacturing', 'Blueprint Research', 'Resource Processing'],
|
||
xpSource: 'Mining cycles, refining batches, manufactured items, research jobs',
|
||
},
|
||
{
|
||
name: 'Navigation',
|
||
color: 'var(--cyan)',
|
||
skills: ['Warp Drive Operation', 'Afterburner', 'Evasive Maneuvering', 'Capital Navigation'],
|
||
xpSource: 'Distance warped, systems visited, successful evasion from combat',
|
||
},
|
||
{
|
||
name: 'Trade',
|
||
color: 'var(--green)',
|
||
skills: ['Market Analysis', 'Broker Relations', 'Hauling', 'Contracting', 'Regional Trading'],
|
||
xpSource: 'Completed trades, market orders filled, cargo hauled between systems',
|
||
},
|
||
{
|
||
name: 'Leadership',
|
||
color: 'var(--purple)',
|
||
skills: ['Fleet Command', 'Wing Command', 'AI Coordination', 'Crew Management'],
|
||
xpSource: 'Fleet actions, AI crew task completions, group mission success (post-MVP)',
|
||
},
|
||
];
|
||
|
||
const chatChannels = [
|
||
{ name: 'Local', range: 'Current system', delay: 'Instant', description: 'Everyone in the same star system sees messages immediately. Core social channel.', color: 'var(--fg-bright)' },
|
||
{ name: 'Private Message', range: 'Based on distance', delay: 'Light-speed delayed', description: 'Direct messages to another player. Messages arrive after a delay proportional to light-years between systems. Across the galaxy = minutes of delay.', color: 'var(--cyan)' },
|
||
{ name: 'Trade', range: 'Station / Region', delay: 'Instant at station, delayed region-wide', description: 'Buy/sell offers, price checks, trade negotiations. Station-local is instant; regional relay has a 30s delay.', color: 'var(--green)' },
|
||
];
|
||
|
||
const bountyTiers = [
|
||
{ tier: 'Petty', threshold: '500 ISK', reward: '10% of bounty', visibility: 'Current system only', color: 'var(--muted)' },
|
||
{ tier: 'Standard', threshold: '5,000 ISK', reward: '15% of bounty', visibility: 'Current region (constellation cluster)', color: 'var(--cyan)' },
|
||
{ tier: 'Dangerous', threshold: '50,000 ISK', reward: '20% of bounty + kill bonus', visibility: 'All regions (galaxy-wide board)', color: 'var(--accent)' },
|
||
{ tier: 'Most Wanted', threshold: '500,000 ISK', reward: '25% + unique cosmetic reward', visibility: 'Galaxy-wide + leaderboard', color: 'var(--red)' },
|
||
];
|
||
|
||
return (
|
||
<div className="content-inner">
|
||
<h1 style={{ marginBottom: '8px' }}>Progression & Social</h1>
|
||
<p style={{ color: 'var(--fg-dim)', fontSize: '0.95rem', maxWidth: '680px' }}>
|
||
XP-based progression across five skill categories. Chat ranges from instant local to
|
||
light-speed-delayed private messages. Bounty system creates emergent player-driven justice
|
||
and piracy consequences. Designed for ~3-hour play sessions with meaningful progression per session.
|
||
</p>
|
||
|
||
{/* Tab navigation */}
|
||
<div style={{ display: 'flex', gap: 'var(--sp-2)', marginBottom: 'var(--sp-6)' }}>
|
||
{[
|
||
{ id: 'progression', label: 'XP & Skills' },
|
||
{ id: 'chat', label: 'Chat & Comms' },
|
||
{ id: 'bounty', label: 'Bounty System' },
|
||
{ id: 'waypoints', label: 'Waypoints' },
|
||
{ id: 'corps', label: 'Corporations' },
|
||
].map(t => (
|
||
<button key={t.id} className={`btn btn-sm${activeSection === t.id ? ' btn-primary' : ''}`}
|
||
onClick={() => setActiveSection(t.id)}>{t.label}</button>
|
||
))}
|
||
</div>
|
||
|
||
{/* PROGRESSION */}
|
||
{activeSection === 'progression' && (
|
||
<>
|
||
<div className="stat-grid">
|
||
<div className="stat-card">
|
||
<div className="stat-value" style={{ color: 'var(--accent)' }}>Action-based</div>
|
||
<div className="stat-label">XP Model</div>
|
||
</div>
|
||
<div className="stat-card">
|
||
<div className="stat-value" style={{ color: 'var(--cyan)' }}>5 Categories</div>
|
||
<div className="stat-label">Skill Trees</div>
|
||
</div>
|
||
<div className="stat-card">
|
||
<div className="stat-value" style={{ color: 'var(--green)' }}>~3 hours</div>
|
||
<div className="stat-label">Session Target</div>
|
||
</div>
|
||
<div className="stat-card">
|
||
<div className="stat-value" style={{ color: 'var(--purple)' }}>V Levels</div>
|
||
<div className="stat-label">Per Skill</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="callout callout-info" style={{ marginBottom: 'var(--sp-5)' }}>
|
||
<strong>Design intent:</strong> XP comes from doing things, not waiting. A 3-hour mining session
|
||
should unlock at least one meaningful skill upgrade. Combat and trade have comparable XP rates
|
||
so no playstyle feels punished.
|
||
</div>
|
||
|
||
<div className="section-header">
|
||
<span className="section-num">SOC-SKL</span>
|
||
<h2 style={{ margin: 0 }}>Skill Categories</h2>
|
||
</div>
|
||
|
||
{skillCategories.map((cat, i) => (
|
||
<div key={i} className="card" style={{ borderLeft: `3px solid ${cat.color}`, marginBottom: 'var(--sp-4)' }}>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 'var(--sp-3)', marginBottom: 'var(--sp-3)' }}>
|
||
<h4 style={{ color: cat.color, margin: 0 }}>{cat.name}</h4>
|
||
</div>
|
||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 'var(--sp-1)', marginBottom: 'var(--sp-3)' }}>
|
||
{cat.skills.map((s, j) => (
|
||
<span key={j} className="pill" style={{ background: 'var(--surface-raised)', color: cat.color, border: `1px solid ${cat.color}40`, fontSize: '0.7rem' }}>
|
||
{s}
|
||
</span>
|
||
))}
|
||
</div>
|
||
<div style={{ fontSize: '0.82rem', color: 'var(--fg-dim)' }}>
|
||
<strong style={{ color: 'var(--muted)' }}>XP source:</strong> {cat.xpSource}
|
||
</div>
|
||
</div>
|
||
))}
|
||
|
||
<div className="section-header" style={{ marginTop: 'var(--sp-6)' }}>
|
||
<span className="section-num">SOC-LVL</span>
|
||
<h2 style={{ margin: 0 }}>Level Progression</h2>
|
||
</div>
|
||
|
||
<div className="card card-accent">
|
||
<h4 style={{ marginBottom: 'var(--sp-4)' }}>XP Curve (per skill)</h4>
|
||
<div style={{ overflowX: 'auto' }}>
|
||
<table className="data-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Level</th>
|
||
<th>Cumulative XP</th>
|
||
<th>Approx. Active Play</th>
|
||
<th>Typical Unlock</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td style={{ color: 'var(--muted)' }}>I</td><td className="mono">100</td><td className="mono">~15 min</td><td style={{ color: 'var(--fg-dim)' }}>Basic modules, rookie ships</td></tr>
|
||
<tr><td style={{ color: 'var(--green)' }}>II</td><td className="mono">500</td><td className="mono">~1 hour</td><td style={{ color: 'var(--fg-dim)' }}>Standard modules, refining</td></tr>
|
||
<tr><td style={{ color: 'var(--cyan)' }}>III</td><td className="mono">2,000</td><td className="mono">~3 hours</td><td style={{ color: 'var(--fg-dim)' }}>T2 modules, cruisers, manufacturing</td></tr>
|
||
<tr><td style={{ color: 'var(--purple)' }}>IV</td><td className="mono">8,000</td><td className="mono">~8 hours</td><td style={{ color: 'var(--fg-dim)' }}>Advanced fittings, battlecruisers</td></tr>
|
||
<tr><td style={{ color: 'var(--accent)' }}>V</td><td className="mono">32,000</td><td className="mono">~20 hours</td><td style={{ color: 'var(--fg-dim)' }}>Battleships, T2 ships, mastery</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div className="section-header" style={{ marginTop: 'var(--sp-8)' }}>
|
||
<span className="section-num">SOC-RESPEC</span>
|
||
<h2 style={{ margin: 0 }}>Respec (Skill Reallocation)</h2>
|
||
</div>
|
||
|
||
<div className="callout callout-info" style={{ marginBottom: 'var(--sp-5)' }}>
|
||
<strong>Mistakes should be fixable, but not free.</strong> Players can reallocate (respec) their skill points,
|
||
returning XP from one skill and applying it to another. This prevents permanent lock-in from early uninformed
|
||
decisions while making frequent respeccing uneconomical.
|
||
</div>
|
||
|
||
<div className="grid-2" style={{ marginBottom: 'var(--sp-6)' }}>
|
||
<div className="card" style={{ borderLeft: '3px solid var(--accent)' }}>
|
||
<h4 style={{ color: 'var(--accent)' }}>Respec Mechanics</h4>
|
||
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Cost:</strong> 20% XP penalty on reallocated points. Respeccing 1,000 XP returns 800 XP to redistribute.</li>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Cooldown:</strong> 7 real-world days between respeccs. Cannot be bypassed.</li>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Scope:</strong> Full respec (all skills) or single-skill respec. Full respec costs 30% instead of 20%.</li>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Location:</strong> Must be docked at a station with a "Neural Remapping" facility (not all stations have this).</li>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Preview:</strong> Before confirming, the respec UI shows the exact XP loss and resulting skill levels. No surprises.</li>
|
||
</ul>
|
||
</div>
|
||
<div className="card" style={{ borderLeft: '3px solid var(--cyan)' }}>
|
||
<h4 style={{ color: 'var(--cyan)' }}>Design Rationale</h4>
|
||
<p style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: '0 0 var(--sp-3) 0' }}>
|
||
The 20% cost ensures that respeccing is a meaningful decision, not a free toggle. A player who respeccs
|
||
from Mining to Gunnery loses 200 of their 1,000 mining XP — they can try combat, but they've paid for the
|
||
privilege. The cooldown prevents rapid role-switching and preserves the value of specialization.
|
||
Players who plan their skill progression carefully are rewarded with more total XP than those who respec frequently.
|
||
</p>
|
||
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.72rem', color: 'var(--muted)' }}>
|
||
Example: Mining III (2,000 XP) \u2192 respec \u2192 receive 1,600 XP \u2192 invest in Gunnery (now Gunnery II at 500 XP + 1,100 banked)
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</>
|
||
)}
|
||
|
||
{/* CHAT & COMMS */}
|
||
{activeSection === 'chat' && (
|
||
<>
|
||
<div className="section-header">
|
||
<span className="section-num">SOC-COM</span>
|
||
<h2 style={{ margin: 0 }}>Communication System</h2>
|
||
</div>
|
||
|
||
<p style={{ color: 'var(--fg-dim)', fontSize: '0.9rem', maxWidth: '680px', marginBottom: 'var(--sp-5)' }}>
|
||
Communication range is physical — messages travel at light speed. Local chat in the same system
|
||
is instant. Private messages to someone across the galaxy are delayed by minutes. This creates
|
||
meaningful tactical information asymmetry and makes relay networks valuable.
|
||
</p>
|
||
|
||
{chatChannels.map((ch, i) => (
|
||
<div key={i} className="card" style={{ borderLeft: `3px solid ${ch.color}`, marginBottom: 'var(--sp-4)' }}>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 'var(--sp-3)', marginBottom: 'var(--sp-3)' }}>
|
||
<h4 style={{ color: ch.color, margin: 0 }}>{ch.name}</h4>
|
||
<span className="pill" style={{ background: 'var(--surface-raised)', color: 'var(--fg-dim)', border: '1px solid var(--border)', fontSize: '0.7rem' }}>
|
||
{ch.range}
|
||
</span>
|
||
</div>
|
||
<p style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: '0 0 var(--sp-2) 0' }}>{ch.description}</p>
|
||
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.75rem', color: 'var(--muted)' }}>
|
||
Delay: {ch.delay}
|
||
</div>
|
||
</div>
|
||
))}
|
||
|
||
<div className="section-header" style={{ marginTop: 'var(--sp-6)' }}>
|
||
<span className="section-num">SOC-PHYS</span>
|
||
<h2 style={{ margin: 0 }}>Light-Speed Delay Mechanics</h2>
|
||
</div>
|
||
|
||
<div className="card card-accent">
|
||
<h4 style={{ marginBottom: 'var(--sp-4)' }}>Message Travel Time</h4>
|
||
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.82rem', color: 'var(--fg-dim)', lineHeight: 2 }}>
|
||
<strong style={{ color: 'var(--fg)' }}>Same system:</strong> 0s (quantum relay)<br/>
|
||
<strong style={{ color: 'var(--fg)' }}>Adjacent system (1 gate):</strong> ~2s<br/>
|
||
<strong style={{ color: 'var(--fg)' }}>5 jumps:</strong> ~10s<br/>
|
||
<strong style={{ color: 'var(--fg)' }}>20 jumps:</strong> ~45s<br/>
|
||
<strong style={{ color: 'var(--fg)' }}>Across galaxy:</strong> ~2–3 minutes<br/>
|
||
<br/>
|
||
<span style={{ color: 'var(--muted)' }}>Formula: baseDelay × sqrt(gateDistance) × 2s</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="grid-2" style={{ marginTop: 'var(--sp-5)' }}>
|
||
<div className="card">
|
||
<h4 style={{ color: 'var(--accent)' }}>Strategic implications</h4>
|
||
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
|
||
<li>Fleet commanders near the front have better intel</li>
|
||
<li>Market data is delayed — arbitrage exists between regions</li>
|
||
<li>Distress calls from deep null-sec arrive minutes late</li>
|
||
<li>Players can set up communication relay networks</li>
|
||
</ul>
|
||
</div>
|
||
<div className="card">
|
||
<h4 style={{ color: 'var(--cyan)' }}>Post-MVP channels</h4>
|
||
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
|
||
<li><strong>Corporation</strong> — instant for corp members (post-MVP)</li>
|
||
<li><strong>Fleet</strong> — instant for fleet members (post-MVP)</li>
|
||
<li><strong>Relay Beacons</strong> — player-placed structures that boost range</li>
|
||
<li><strong>Alliance</strong> — meta-corp channels (far future)</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</>
|
||
)}
|
||
|
||
{/* BOUNTY SYSTEM */}
|
||
{activeSection === 'bounty' && (
|
||
<>
|
||
<div className="section-header">
|
||
<span className="section-num">SOC-BNT</span>
|
||
<h2 style={{ margin: 0 }}>Bounty System</h2>
|
||
</div>
|
||
|
||
<p style={{ color: 'var(--fg-dim)', fontSize: '0.9rem', maxWidth: '680px', marginBottom: 'var(--sp-5)' }}>
|
||
Any player can place a bounty on another player. Bounties create consequences for piracy
|
||
and emergent "space justice" dynamics. Higher bounties attract more bounty hunters and
|
||
increase visibility across the galaxy.
|
||
</p>
|
||
|
||
<div style={{ overflowX: 'auto' }}>
|
||
<table className="data-table">
|
||
<thead>
|
||
<tr><th>Tier</th><th>Bounty Threshold</th><th>Hunter Reward</th><th>Visibility (Sector-Specific)</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
{bountyTiers.map((tier, i) => (
|
||
<tr key={i}>
|
||
<td><span className={`pill ${i === 0 ? 'pill-green' : i === 1 ? 'pill-cyan' : i === 2 ? 'pill-amber' : 'pill-red'}`}>
|
||
{tier.tier}
|
||
</span></td>
|
||
<td className="mono">{tier.threshold}</td>
|
||
<td style={{ color: 'var(--fg-dim)' }}>{tier.reward}</td>
|
||
<td style={{ color: tier.color }}>{tier.visibility}</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div className="grid-2" style={{ marginTop: 'var(--sp-5)' }}>
|
||
<div className="card" style={{ borderLeft: '3px solid var(--red)' }}>
|
||
<h4 style={{ color: 'var(--red)' }}>How bounties work</h4>
|
||
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.82rem', color: 'var(--fg-dim)', lineHeight: 2 }}>
|
||
1. Player A places bounty on Player B (ISK deducted immediately)<br/>
|
||
2. Bounty pool accumulates — multiple players can contribute<br/>
|
||
3. When Player B's ship is destroyed, bounty pays out<br/>
|
||
4. Payout = percentage of bounty pool based on tier<br/>
|
||
5. Killer gets the reward; remaining pool stays active<br/>
|
||
6. If Player B stays clean for 30 days, bounty decays 10%/week
|
||
</div>
|
||
</div>
|
||
<div className="card" style={{ borderLeft: '3px solid var(--green)' }}>
|
||
<h4 style={{ color: 'var(--green)' }}>Anti-abuse rules</h4>
|
||
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
|
||
<li>You cannot claim your own bounty (alt check)</li>
|
||
<li>Bounty payout never exceeds ship loss value</li>
|
||
<li>Minimum bounty placement: 500 ISK (prevents spam)</li>
|
||
<li>Bounty target must have negative security status or have committed a hostile act in the last 24h (<em>see Gameplay → Security Levels</em>)</li>
|
||
<li>Kill feed shows bounty collected, not total pool</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="callout callout-info" style={{ marginTop: 'var(--sp-5)' }}>
|
||
<strong>Sector-specific bounties:</strong> Bounty visibility is sector-based, not galaxy-wide by default. A petty bounty
|
||
in Jita is invisible in Amarr. This means a pirate can be hunted in one region while operating freely in another.
|
||
Only Dangerous and Most Wanted bounties propagate galaxy-wide. This creates regional justice ecosystems and
|
||
makes bounty hunting a localized profession rather than a galaxy-wide pursuit.
|
||
</div>
|
||
|
||
<div className="callout callout-warn" style={{ marginTop: 'var(--sp-4)' }}>
|
||
<strong>Kill feed:</strong> A galaxy-wide feed shows ship destruction events with pilot names,
|
||
ship types, system, and bounty collected. This creates reputation dynamics and emergent
|
||
storylines — "CMDR Worf has been destroyed in O-WAMW, 45,000 ISK bounty collected."
|
||
</div>
|
||
</>
|
||
)}
|
||
|
||
{/* WAYPOINTS */}
|
||
{activeSection === 'waypoints' && (
|
||
<>
|
||
<div className="section-header">
|
||
<span className="section-num">SOC-NAV</span>
|
||
<h2 style={{ margin: 0 }}>Waypoints & Bookmarks</h2>
|
||
</div>
|
||
|
||
<p style={{ color: 'var(--fg-dim)', fontSize: '0.9rem', maxWidth: '680px', marginBottom: 'var(--sp-5)' }}>
|
||
Players can bookmark arbitrary locations in space and create waypoint routes for navigation.
|
||
Bookmarks are personal; waypoints can be shared. Fleet beacons are visible to all fleet members
|
||
and create tactical rally points.
|
||
</p>
|
||
|
||
<div className="grid-2">
|
||
<div className="card" style={{ borderLeft: '3px solid var(--accent)' }}>
|
||
<h4 style={{ color: 'var(--accent)' }}>Bookmarks</h4>
|
||
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
|
||
<li>Save any point in space as a named bookmark</li>
|
||
<li>Personal — only you see them</li>
|
||
<li>Can warp to any bookmark (if in range)</li>
|
||
<li>Used for: safe spots, mining positions, ambush points, salvage sites</li>
|
||
<li>Storage limit: 100 bookmarks per player (MVP)</li>
|
||
</ul>
|
||
</div>
|
||
<div className="card" style={{ borderLeft: '3px solid var(--cyan)' }}>
|
||
<h4 style={{ color: 'var(--cyan)' }}>Waypoints & Routes</h4>
|
||
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
|
||
<li>Create multi-stop routes through star systems</li>
|
||
<li>Autopilot follows route automatically (slower than manual)</li>
|
||
<li>Route avoids low-sec if preference set</li>
|
||
<li>Share routes with other players (trade routes, patrol paths)</li>
|
||
<li>Optimize for: shortest, safest, or most profitable</li>
|
||
</ul>
|
||
</div>
|
||
<div className="card" style={{ borderLeft: '3px solid var(--purple)' }}>
|
||
<h4 style={{ color: 'var(--purple)' }}>Fleet Beacons</h4>
|
||
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
|
||
<li>Visible to all fleet members on star map</li>
|
||
<li>Create rally points and tactical positions</li>
|
||
<li>Any fleet member can create a beacon</li>
|
||
<li>Beacons expire after 1 hour or when creator leaves fleet</li>
|
||
<li>Post-MVP feature — designed into data model now</li>
|
||
</ul>
|
||
</div>
|
||
<div className="card" style={{ borderLeft: '3px solid var(--green)' }}>
|
||
<h4 style={{ color: 'var(--green)' }}>Map Annotations</h4>
|
||
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
|
||
<li>Mark systems with notes ("pirate camp", "good mining", "friendly station")</li>
|
||
<li>Notes visible on star map hover</li>
|
||
<li>Statistics overlay: jumps/hour, ship kills, pod kills</li>
|
||
<li>Color-code systems by danger level or personal preference</li>
|
||
<li>Export/import annotations for sharing</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="section-header" style={{ marginTop: 'var(--sp-6)' }}>
|
||
<span className="section-num">SOC-DB</span>
|
||
<h2 style={{ margin: 0 }}>Backend Tables (New)</h2>
|
||
</div>
|
||
|
||
<div className="callout callout-info" style={{ marginBottom: 'var(--sp-5)', fontSize: '0.82rem' }}>
|
||
<strong>Canonical location:</strong> These tables are also listed in the <em>Backend → Tables</em> tab, which serves as the master schema reference. The definitions here include Social-specific context.
|
||
</div>
|
||
|
||
<div style={{ overflowX: 'auto' }}>
|
||
<table className="data-table">
|
||
<thead><tr><th>Table</th><th>Purpose</th><th>Key Fields</th></tr></thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>bookmarks</code></td>
|
||
<td style={{ color: 'var(--fg-dim)' }}>Player-saved locations</td>
|
||
<td style={{ fontSize: '0.75rem', color: 'var(--muted)' }}>bookmark_id, player_id, system_id, x/y/z, name, created_at</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>waypoints</code></td>
|
||
<td style={{ color: 'var(--fg-dim)' }}>Multi-stop routes</td>
|
||
<td style={{ fontSize: '0.75rem', color: 'var(--muted)' }}>route_id, player_id, stops (ordered system list), name, shared</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>bounties</code></td>
|
||
<td style={{ color: 'var(--fg-dim)' }}>Bounty pool per target</td>
|
||
<td style={{ fontSize: '0.75rem', color: 'var(--muted)' }}>target_player_id, total_pool, tier, last_hostile_act</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>bounty_contributions</code></td>
|
||
<td style={{ color: 'var(--fg-dim)' }}>Individual bounty payments</td>
|
||
<td style={{ fontSize: '0.75rem', color: 'var(--muted)' }}>contribution_id, target_id, contributor_id, amount, timestamp</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>kill_feed</code></td>
|
||
<td style={{ color: 'var(--fg-dim)' }}>Ship destruction events</td>
|
||
<td style={{ fontSize: '0.75rem', color: 'var(--muted)' }}>kill_id, victim_id, killer_id, ship_type, system_id, bounty_collected, timestamp</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>player_skills</code></td>
|
||
<td style={{ color: 'var(--fg-dim)' }}>XP and levels per skill</td>
|
||
<td style={{ fontSize: '0.75rem', color: 'var(--muted)' }}>player_id, skill_name, xp, level, last_action_at</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>fleet_beacons</code></td>
|
||
<td style={{ color: 'var(--fg-dim)' }}>Temporary fleet rally points</td>
|
||
<td style={{ fontSize: '0.75rem', color: 'var(--muted)' }}>beacon_id, fleet_id, creator_id, system_id, x/y/z, expires_at</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</>
|
||
)}
|
||
{/* CORPORATIONS & TERRITORY */}
|
||
{activeSection === 'corps' && (<>
|
||
<div className="section-header">
|
||
<span className="section-num">SOC-CORP</span>
|
||
<h2 style={{ margin: 0 }}>Corporations & Territory</h2>
|
||
</div>
|
||
|
||
<div className="callout callout-info" style={{ marginBottom: 'var(--sp-5)' }}>
|
||
<strong>Era 2 feature — designed now, implemented in Phase 14.</strong>
|
||
Corporations ("corps") are player organizations: persistent groups with shared wallets, hangars, roles,
|
||
and territory claims. They are the endgame social structure — the reason players stay for years. This spec
|
||
establishes the design direction so the backend schema can accommodate it without breaking changes.
|
||
Implementation details may evolve, but the core model is fixed.
|
||
</div>
|
||
|
||
<h3 style={{ marginBottom: 'var(--sp-4)' }}>Corporation Lifecycle</h3>
|
||
<div className="card card-accent" style={{ marginBottom: 'var(--sp-6)' }}>
|
||
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.82rem', color: 'var(--fg-dim)', lineHeight: 2.2 }}>
|
||
<span style={{ color: 'var(--cyan)' }}>1. Found</span> — Any player pays 1,000,000 ₢ founding fee. Chooses name + ticker (3–5 chars). Becomes CEO. Minimum 1 member.
|
||
<br/>
|
||
<span style={{ color: 'var(--green)' }}>2. Recruit</span> — CEO (or Director) sends invite. Player accepts. Member appears on corp roster. Corp chat channel auto-created.
|
||
<br/>
|
||
<span style={{ color: 'var(--accent)' }}>3. Operate</span> — Members contribute to corp wallet (ISK tax on bounties/missions, optional). Shared hangar at corp HQ station. Roles control access.
|
||
<br/>
|
||
<span style={{ color: 'var(--purple)' }}>4. Claim</span> — Corp anchors a structure in a null-sec system. Structure asserts sovereignty. System shows on sov map as corp territory.
|
||
<br/>
|
||
<span style={{ color: 'var(--red)' }}>5. Defend</span> — Rival corps can contest sovereignty. Structure has a vulnerability window (CEO-configured, 4h/day). During vulnerability, structure can be attacked.
|
||
<br/>
|
||
<span style={{ color: 'var(--fg)' }}>6. Dissolve</span> — If CEO disbands or corp drops below 3 members for 14 days, corp dissolves. Assets liquidated to CEO wallet. Territory unclaimed.
|
||
</div>
|
||
</div>
|
||
|
||
<h3 style={{ marginBottom: 'var(--sp-4)' }}>Corporation Roles</h3>
|
||
<div style={{ overflowX: 'auto', marginBottom: 'var(--sp-6)' }}>
|
||
<table className="data-table">
|
||
<thead>
|
||
<tr><th>Role</th><th>Permissions</th><th>Assignment</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
{[
|
||
{ role: 'CEO', perms: 'All permissions. Can disband corp. Can transfer CEO role. Cannot be kicked.', assignment: 'Founder (auto). Transferable.' },
|
||
{ role: 'Director', perms: 'Invite/kick members, manage roles, corp wallet full access, anchor/destroy structures, set tax rate, configure vulnerability window.', assignment: 'Appointed by CEO or other Directors.' },
|
||
{ role: 'Accountant', perms: 'View corp wallet history. Pay bills. Set market orders from corp funds. Cannot withdraw ISK.', assignment: 'Appointed by Director+.' },
|
||
{ role: 'Pilot', perms: 'Access corp hangar (configured per station). Use corp fittings. Join corp fleet.', assignment: 'Default role for new members.' },
|
||
{ role: 'Recruit', perms: 'Corp chat access. View roster. No hangar access. No wallet access.', assignment: 'Probationary role (optional, 7-day default). Auto-promotes to Pilot.' },
|
||
].map((row, i) => (
|
||
<tr key={i}>
|
||
<td style={{ fontWeight: 600, color: ['var(--accent)', 'var(--cyan)', 'var(--green)', 'var(--purple)', 'var(--fg-dim)'][i] }}>{row.role}</td>
|
||
<td style={{ color: 'var(--fg-dim)', fontSize: '0.82rem' }}>{row.perms}</td>
|
||
<td style={{ color: 'var(--fg-dim)', fontSize: '0.82rem' }}>{row.assignment}</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<h3 style={{ marginBottom: 'var(--sp-4)' }}>Corporation Wallet & Tax</h3>
|
||
<div className="grid-2" style={{ marginBottom: 'var(--sp-6)' }}>
|
||
<div className="card" style={{ borderLeft: '3px solid var(--green)' }}>
|
||
<h4 style={{ color: 'var(--green)' }}>Corp Wallet</h4>
|
||
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
|
||
<li>Shared ISK balance separate from all member wallets</li>
|
||
<li>Funded by: tax on member income, voluntary donations, structure taxes, corp market orders</li>
|
||
<li>Spent on: structure fuel, alliance dues, SRP (ship replacement program), member bonuses</li>
|
||
<li>Full transaction log visible to Accountant+ roles</li>
|
||
<li>Withdrawal requires Director+ approval (or CEO)</li>
|
||
</ul>
|
||
</div>
|
||
<div className="card" style={{ borderLeft: '3px solid var(--accent)' }}>
|
||
<h4 style={{ color: 'var(--accent)' }}>Tax System</h4>
|
||
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Bounty tax:</strong> CEO sets % (0–100%). Deducted from NPC bounties and mission rewards. Default 10%.</li>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Market tax:</strong> Optional tax on market orders placed in corp-controlled stations. 0–5%. Set per station.</li>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Refining tax:</strong> Optional tax on refining at corp-controlled facilities. 0–5%.</li>
|
||
<li>Tax revenue goes to corp wallet automatically</li>
|
||
<li>Members see their personal tax contribution in wallet history</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<h3 style={{ marginBottom: 'var(--sp-4)' }}>Territory & Sovereignty</h3>
|
||
<div className="callout callout-info" style={{ marginBottom: 'var(--sp-5)' }}>
|
||
<strong>Null-sec only.</strong> Territory claims are only possible in null-sec (security ≤ 0.0). High-sec and low-sec systems
|
||
cannot be claimed. This preserves the "wild west" nature of null-sec as the player-driven frontier while keeping
|
||
NPC-controlled space as the shared commons.
|
||
</div>
|
||
|
||
<div className="grid-2" style={{ marginBottom: 'var(--sp-6)' }}>
|
||
<div className="card" style={{ borderLeft: '3px solid var(--red)' }}>
|
||
<h4 style={{ color: 'var(--red)' }}>Corporation Structures</h4>
|
||
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Starbase (Medium):</strong> Claims sovereignty in 1 system. Provides: refining bonus (+10%), market access, hangar, clone bay. Cost: 50M ₢ + fuel.</li>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Citadel (Large):</strong> Claims constellation-wide influence. Provides: all Starbase bonuses + manufacturing slots + insurance desk. Cost: 500M ₢ + fuel.</li>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Keepstar (XL):</strong> Regional capital. Provides: all Citadel bonuses + capital ship construction + super-capital docking. Cost: 5B ₢ + fuel. One per region.</li>
|
||
<li>Structures have shields, armor, and hull — they can be destroyed during vulnerability windows</li>
|
||
<li>Structure destruction = loss of territory claim. System becomes unclaimed.</li>
|
||
</ul>
|
||
</div>
|
||
<div className="card" style={{ borderLeft: '3px solid var(--cyan)' }}>
|
||
<h4 style={{ color: 'var(--cyan)' }}>Sovereignty Mechanics</h4>
|
||
<ul style={{ color: 'var(--fg-dim)', fontSize: '0.85rem', margin: 0, paddingLeft: 'var(--sp-5)' }}>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Anchoring:</strong> Corp anchors structure in unclaimed null-sec system. 24-hour onlining timer. During onlining, structure is invulnerable.</li>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Vulnerability window:</strong> CEO picks a 4-hour daily window (must overlap with corp prime time). Structure can only be attacked during this window.</li>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Reinforcement:</strong> When structure shields reach 0%, it enters reinforcement (18h timer). Armor becomes targetable after timer expires.</li>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Destruction:</strong> When structure hull reaches 0%, it explodes. Corp loses sovereignty. All items in corp hangar drop as loot (50%) or are destroyed (50%).</li>
|
||
<li><strong style={{ color: 'var(--fg)' }}>Strategic index:</strong> The longer a corp holds a system, the higher the strategic index (0–5). Higher index = longer reinforcement timer, stronger structure shields. Rewards long-term ownership.</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="callout callout-warn" style={{ marginBottom: 'var(--sp-5)' }}>
|
||
<strong>Design intent:</strong> Territory warfare is the endgame that keeps players engaged for years. A corp's home system
|
||
is its identity — losing it is a major event, conquering one is a major achievement. The vulnerability window ensures
|
||
battles happen when both sides can participate (no 3 AM structure kills). The strategic index rewards corps that invest
|
||
in their territory rather than nomadic expansion. The goal is <em>meaningful conflict</em>, not meaningless destruction.
|
||
</div>
|
||
|
||
<div className="section-header">
|
||
<span className="section-num">SOC-CORP-DB</span>
|
||
<h2 style={{ margin: 0 }}>Backend Impact</h2>
|
||
</div>
|
||
<div className="card card-accent" style={{ marginBottom: 'var(--sp-5)' }}>
|
||
<h4 style={{ marginBottom: 'var(--sp-4)' }}>New Tables (Phase 14)</h4>
|
||
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.82rem', color: 'var(--fg-dim)', lineHeight: 2 }}>
|
||
<span style={{ color: 'var(--accent)' }}>corporations</span> — <code>corp_id, name, ticker, ceo_player_id, founded_at, wallet_balance, tax_rate_bounty, tax_rate_market, tax_rate_refining, member_count, hq_station_id, vulnerability_window_start, vulnerability_window_hours, dissolved_at</code><br/>
|
||
<span style={{ color: 'var(--cyan)' }}>corp_members</span> — <code>corp_id, player_id, role (enum), joined_at, tax_contribution_lifetime</code><br/>
|
||
<span style={{ color: 'var(--green)' }}>corp_wallet_journal</span> — <code>entry_id, corp_id, entry_type (tax/donation/withdrawal/expense), amount, player_id, timestamp, description</code><br/>
|
||
<span style={{ color: 'var(--red)' }}>corp_structures</span> — <code>structure_id, corp_id, system_id, structure_type (starbase/citadel/keepstar), shield/armor/hull, state (onlining/online/reinforced/vulnerable/destroyed), reinforced_at, vulnerability_start, strategic_index</code><br/>
|
||
<span style={{ color: 'var(--purple)' }}>corp_hangar</span> — <code>hangar_id, corp_id, station_id, item_type, quantity, access_role_min</code><br/>
|
||
<span style={{ color: 'var(--fg)' }}>corp_fittings</span> — <code>fitting_id, corp_id, name, ship_type, modules_json, created_by, access_role_min</code><br/>
|
||
<br/>
|
||
<span style={{ color: 'var(--cyan)' }}>Reducers:</span> <code>found_corp(name, ticker)</code>, <code>invite_member(player_id)</code>, <code>kick_member(player_id)</code>, <code>set_role(player_id, role)</code>, <code>anchor_structure(system_id, type)</code>, <code>attack_structure(structure_id)</code>, <code>reinforce_structure(structure_id)</code>, <code>destroy_structure(structure_id)</code>, <code>set_tax_rate(type, rate)</code>, <code>deposit_corp_wallet(amount)</code>, <code>withdraw_corp_wallet(amount, reason)</code>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="callout callout-info">
|
||
<strong>Corp hangar integration:</strong> When a player is docked at a station with a corp hangar, they see a
|
||
"Corp Hangar" tab in the Inventory panel. Access is gated by role. Items in corp hangar can be used for corp
|
||
manufacturing jobs, corp market orders, or distributed to members. The hangar respects the same item/inventory
|
||
system as personal hangars — it's just owned by the corp entity rather than a player entity.
|
||
</div>
|
||
</>)}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
window.GDD.SocialPage = SocialPage;
|